aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bazel/compiler_flags.bazelrc28
-rw-r--r--.bazelignore1
-rw-r--r--.bazelrc11
-rw-r--r--.config27
-rw-r--r--.gitignore15
-rw-r--r--BUILD.bazel13
-rw-r--r--Kconfig22
-rw-r--r--MODULE.bazel12
-rw-r--r--Makefile64
-rw-r--r--Makefile.all61
-rw-r--r--Makefile.config72
-rw-r--r--README.md6
-rw-r--r--arch/i386/BUILD.bazel44
-rw-r--r--arch/i386/boot.s (renamed from i686/boot.S)37
-rw-r--r--arch/i386/gdt.c (renamed from i686/gdt.c)6
-rw-r--r--arch/i386/gdt.h55
-rw-r--r--arch/i386/idt.h (renamed from i686/idt.h)8
-rw-r--r--arch/i386/init.s (renamed from i686/init.s)0
-rw-r--r--arch/i386/isr.c (renamed from i686/isr.c)2
-rw-r--r--arch/i386/lgdt.c25
-rw-r--r--arch/i386/lidt.c55
-rw-r--r--arch/i386/linker.ld (renamed from i686/linker.ld)0
-rw-r--r--arch/i386/paging.h59
-rw-r--r--arch/i386/sys/control.h24
-rw-r--r--arch/i386/sys/cpuid.h (renamed from i686/sys/cpuid.h)2
-rw-r--r--arch/i386/sys/io.h92
-rw-r--r--arch/i386/sys/syscall.h (renamed from i686/sys/syscall.h)0
-rw-r--r--arch/i386/test_gdt.cc25
-rw-r--r--devices/BUILD.bazel22
-rw-r--r--devices/Makefile11
-rw-r--r--devices/i8042.c29
-rw-r--r--devices/include/keyboard.h (renamed from devices/keyboard.h)0
-rw-r--r--devices/include/mouse.h (renamed from devices/mouse.h)0
-rw-r--r--devices/include/pic.h (renamed from devices/pic.h)0
-rw-r--r--devices/include/ps2_controller.h (renamed from devices/ps2_controller.h)0
-rw-r--r--devices/include/uart.h32
-rw-r--r--devices/include/vga.h33
-rw-r--r--devices/mouse.c26
-rw-r--r--devices/pckbd.c16
-rw-r--r--devices/pic_8259.c34
-rw-r--r--devices/uart.hpp7
-rw-r--r--devices/uart/sys_io.hh34
-rw-r--r--devices/uart/uart_16550.c78
-rw-r--r--devices/uart/uart_16550.h49
-rw-r--r--devices/uart/unittest_uart_16550.cc116
-rw-r--r--devices/uart_16550.cpp110
-rw-r--r--devices/vga.c (renamed from devices/vga.cpp)88
-rw-r--r--devices/vga.hpp51
-rw-r--r--grub/BUILD.bazel9
-rw-r--r--grub/include/multiboot2.h (renamed from grub/multiboot2.h)0
-rw-r--r--i686-elf-gcc.txt9
-rw-r--r--i686/Makefile13
-rw-r--r--i686/gdt.h55
-rw-r--r--i686/lgdt.c35
-rw-r--r--i686/lidt.c53
-rw-r--r--i686/macros.s25
-rw-r--r--i686/paging.h59
-rw-r--r--i686/sys/control.h25
-rw-r--r--i686/sys/io.h102
-rw-r--r--i686/sys/io.hpp33
-rw-r--r--i686/test/gdt.c20
-rw-r--r--i686/toolchain.mk40
-rw-r--r--kernel/BUILD.bazel37
-rw-r--r--kernel/boot.h21
-rw-r--r--kernel/conf.h.in4
-rw-r--r--kernel/kernel.c (renamed from src/kernel.cpp)28
-rw-r--r--kernel/mem.h (renamed from src/mem.h)0
-rw-r--r--kernel/mem/vmm.c (renamed from src/mem/vmm.c)26
-rw-r--r--kernel/mmap.c (renamed from src/mmap.c)26
-rw-r--r--kernel/mmap.h (renamed from src/mmap.h)0
-rw-r--r--kernel/multiboot2.c (renamed from src/multiboot2.c)7
-rw-r--r--kernel/sched.hpp (renamed from src/sched.hpp)0
-rw-r--r--kernel/sched/roundrobin.cpp (renamed from src/sched/roundrobin.cpp)0
-rw-r--r--kernel/sched/test_roundrobin.cc (renamed from src/tst/roundrobin.cc)2
-rw-r--r--kernel/sched/test_taskqueue.cc (renamed from src/tst/taskqueue.cc)0
-rw-r--r--kernel/task.h (renamed from src/task.h)0
-rw-r--r--lib/Makefile17
-rw-r--r--lib/blake2/BUILD.bazel28
-rw-r--r--lib/blake2/blake2s.c37
-rwxr-xr-xlib/blake2/blake2s_genkat.py (renamed from lib/tst/blake2s_genkat.py)0
-rw-r--r--lib/blake2/blake2s_kat.h (renamed from lib/tst/blake2s_kat.h)2
-rw-r--r--lib/blake2/blake2s_selftest.cc (renamed from lib/tst/blake2s_selftest.cc)12
-rw-r--r--lib/blake2/include/blake2s.h (renamed from lib/blake2/blake2s.h)24
-rw-r--r--lib/libk/BUILD.bazel80
-rw-r--r--lib/libk/endian/little.c4
-rw-r--r--lib/libk/endian/test_endian_little.cc (renamed from lib/tst/endian_little.cc)2
-rw-r--r--lib/libk/include/endian.h (renamed from lib/libk/endian.h)8
-rw-r--r--lib/libk/include/stdio.h (renamed from lib/libk/stdio.h)41
-rw-r--r--lib/libk/include/stdlib.h (renamed from lib/libk/stdlib.h)10
-rw-r--r--lib/libk/include/string.h14
-rw-r--r--lib/libk/stdio/fprintf.c5
-rw-r--r--lib/libk/stdio/printf.c5
-rw-r--r--lib/libk/stdio/vfprintf.c (renamed from lib/libk/stdio/vfprintf.cpp)25
-rw-r--r--lib/libk/stdlib/linked_list_allocator.c15
-rw-r--r--lib/libk/stdlib/memcpy.c2
-rw-r--r--lib/libk/stdlib/memset.c3
-rw-r--r--lib/libk/stdlib/test_allocator.hh (renamed from lib/tst/allocator.hh)0
-rw-r--r--lib/libk/stdlib/test_linked_list_allocator.cc (renamed from lib/tst/linked_list_allocator.cc)4
-rw-r--r--lib/libk/stdlib/test_mem.cc (renamed from lib/tst/mem.cc)4
-rw-r--r--lib/libk/string.h28
-rw-r--r--lib/libk/string/itoa.c6
-rw-r--r--lib/libk/string/test_string.cc (renamed from lib/tst/string.cc)2
-rw-r--r--platforms/BUILD.bazel7
-rw-r--r--project_config.bzl2
-rw-r--r--rules.mk142
-rwxr-xr-xscripts/test_runner.py40
-rw-r--r--src/Makefile20
-rw-r--r--src/boot.h24
-rw-r--r--src/conf.h.in4
-rw-r--r--toolchains/BUILD.bazel34
-rw-r--r--toolchains/i386_elf_gcc.bzl123
-rw-r--r--toolchains/i386_qemu.bzl8
-rw-r--r--tools/BUILD.bazel6
-rw-r--r--tools/configure_file.bzl29
-rw-r--r--tools/interface_generator/.bazelrc2
-rw-r--r--tools/interface_generator/BUILD.bazel13
-rw-r--r--tools/interface_generator/LICENSE.md16
-rw-r--r--tools/interface_generator/MODULE.bazel20
-rw-r--r--tools/interface_generator/bin/BUILD.bazel45
-rw-r--r--tools/interface_generator/bin/interface_declaration.py58
-rw-r--r--tools/interface_generator/bin/interface_declaration_unittest.py19
-rwxr-xr-xtools/interface_generator/bin/interface_generator.py86
-rw-r--r--tools/interface_generator/bin/templates.py19
-rw-r--r--tools/interface_generator/bin/templates/__c_functions.mako4
-rw-r--r--tools/interface_generator/bin/templates/__c_system_include.mako4
-rw-r--r--tools/interface_generator/bin/templates/__c_types.mako6
-rw-r--r--tools/interface_generator/bin/templates/__header.mako5
-rw-r--r--tools/interface_generator/bin/templates/interface.h.mako8
-rw-r--r--tools/interface_generator/bin/templates/interface_mock.cpp.mako32
-rw-r--r--tools/interface_generator/bin/templates/interface_mock.hpp.mako26
-rw-r--r--tools/interface_generator/bin/templates_unittest.py30
-rw-r--r--tools/interface_generator/defs.bzl53
-rw-r--r--tools/interface_generator/private/BUILD.bazel9
-rw-r--r--tools/interface_generator/private/defs.bzl29
-rw-r--r--tools/interface_generator/private/mypyrc2
-rw-r--r--tools/interface_generator/private/pylintrc0
-rwxr-xr-xtools/interface_generator/private/pytest_wrapper.py7
-rw-r--r--tools/interface_generator/requirements.txt6
-rw-r--r--tools/interface_generator/requirements_lock.txt220
-rw-r--r--tools/interface_generator/test/BUILD.bazel24
-rw-r--r--tools/interface_generator/test/test_kstdio.cpp20
-rw-r--r--tools/kconfig/.gitignore8
-rw-r--r--tools/kconfig/Makefile28
-rw-r--r--tools/kconfig/README.md9
-rw-r--r--tools/kconfig/conf.c921
-rw-r--r--tools/kconfig/confdata.c1263
-rw-r--r--tools/kconfig/expr.c1303
-rw-r--r--tools/kconfig/expr.h326
-rw-r--r--tools/kconfig/internal.h9
-rw-r--r--tools/kconfig/lexer.l468
-rw-r--r--tools/kconfig/list.h132
-rw-r--r--tools/kconfig/lkc.h150
-rw-r--r--tools/kconfig/lkc_proto.h52
-rw-r--r--tools/kconfig/lxdialog/BIG.FAT.WARNING4
-rw-r--r--tools/kconfig/lxdialog/checklist.c319
-rw-r--r--tools/kconfig/lxdialog/dialog.h238
-rw-r--r--tools/kconfig/lxdialog/inputbox.c289
-rw-r--r--tools/kconfig/lxdialog/menubox.c424
-rw-r--r--tools/kconfig/lxdialog/textbox.c395
-rw-r--r--tools/kconfig/lxdialog/util.c700
-rw-r--r--tools/kconfig/lxdialog/yesno.c101
-rw-r--r--tools/kconfig/mconf.c1042
-rw-r--r--tools/kconfig/menu.c859
-rw-r--r--tools/kconfig/parser.y716
-rw-r--r--tools/kconfig/preprocess.c574
-rw-r--r--tools/kconfig/symbol.c1270
-rw-r--r--tools/kconfig/util.c129
-rw-r--r--tools/make_iso.bzl41
-rwxr-xr-xtools/make_iso.py58
-rw-r--r--tools/qemu.bzl33
170 files changed, 2474 insertions, 13098 deletions
diff --git a/.bazel/compiler_flags.bazelrc b/.bazel/compiler_flags.bazelrc
new file mode 100644
index 0000000..2b2e5d1
--- /dev/null
+++ b/.bazel/compiler_flags.bazelrc
@@ -0,0 +1,28 @@
+build --copt=-Wall
+build --copt=-Wextra
+build --copt=-Wpedantic
+build --copt=-Werror=shadow
+build --copt=-Wunused-parameter
+build --copt=-Wmisleading-indentation
+build --copt=-Wundef
+build --copt=-Wuninitialized
+
+# cast warnings
+build --copt=-Wcast-align
+build --copt=-Wcast-qual
+
+# conversion
+build --copt=-Wconversion
+build --copt=-Wsign-conversion
+build --copt=-Wdouble-promotion
+
+# pointers
+build --copt=-Wpointer-arith
+build --copt=-Wnull-dereference
+
+# cpp flags
+build --cxxopt=-std=c++20
+build --cxxopt=-Wnon-virtual-dtor
+build --cxxopt=-Woverloaded-virtual
+build --cxxopt=-Wold-style-cast
+
diff --git a/.bazelignore b/.bazelignore
new file mode 100644
index 0000000..c6094bc
--- /dev/null
+++ b/.bazelignore
@@ -0,0 +1 @@
+tools/interface_generator
diff --git a/.bazelrc b/.bazelrc
new file mode 100644
index 0000000..2a0a947
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1,11 @@
+# compiler flags
+try-import %workspace%/.bazel/compiler_flags.bazelrc
+
+build --instrument_test_targets
+
+build:i386 --compilation_mode=opt
+build:i386 --platforms=//platforms:i386
+
+coverage --combined_report=lcov
+
+test --compilation_mode=dbg
diff --git a/.config b/.config
deleted file mode 100644
index e04ec16..0000000
--- a/.config
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Automatically generated file; DO NOT EDIT.
-# Main menu
-#
-
-#
-# Toolchain
-#
-CONFIG_CFLAGS="-g -Og"
-CONFIG_CXXFLAGS="-g -Og"
-CONFIG_LDFLAGS=""
-# end of Toolchain
-
-#
-# Target
-#
-CONFIG_ARCH_i686=y
-# end of Target
-
-#
-# Devices
-#
-CONFIG_PIC_8259=y
-CONFIG_UART_16550=y
-CONFIG_VGA_TEXT_MODE=y
-CONFIG_KB_PS2=y
-# end of Devices
diff --git a/.gitignore b/.gitignore
index 19429b0..57c461f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,2 @@
-lib/musl*
-build*
-*.d
-*.o
-*.a
-*.elf
-*.iso
-isodir
-src/conf.h
-.config.old
-test_*
-doc
-include/
+bazel-*
+
diff --git a/BUILD.bazel b/BUILD.bazel
new file mode 100644
index 0000000..9c05b27
--- /dev/null
+++ b/BUILD.bazel
@@ -0,0 +1,13 @@
+load("//tools:make_iso.bzl", "make_iso")
+load("//tools:qemu.bzl", "qemu")
+
+make_iso(
+ name = "glitch",
+ bootloader = "//grub:grub.cfg",
+ kernel = "//kernel:glitch.elf",
+)
+
+qemu(
+ name = "qemu",
+ cdrom = ":glitch",
+)
diff --git a/Kconfig b/Kconfig
index d50a25e..db565cc 100644
--- a/Kconfig
+++ b/Kconfig
@@ -1,4 +1,18 @@
menu "Toolchain"
+ choice
+ prompt "Target architecture"
+ config ARCH_i686
+ bool "i686"
+ config ARCH_mips
+ bool "mips"
+ endchoice
+ choice
+ prompt "Toolchain"
+ config TOOLCHAIN_i686_gcc
+ bool "i686-elf-gcc"
+ depends on ARCH_i686
+ endchoice
+
config CFLAGS
string "Additional C compiler flags"
config CXXFLAGS
@@ -7,14 +21,6 @@ menu "Toolchain"
string "Additional linker flags"
endmenu
-menu "Target"
- choice
- prompt "Target architecture"
- config ARCH_i686
- bool "i686"
- endchoice
-endmenu
-
menu "Devices"
config PIC_8259
bool "PIC 8259"
diff --git a/MODULE.bazel b/MODULE.bazel
new file mode 100644
index 0000000..fbf1ad8
--- /dev/null
+++ b/MODULE.bazel
@@ -0,0 +1,12 @@
+###############################################################################
+# Bazel now uses Bzlmod by default to manage external dependencies.
+# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel.
+#
+# For more details, please check https://github.com/bazelbuild/bazel/issues/18958
+###############################################################################
+
+register_toolchains(
+ "//toolchains:i386_elf_gcc",
+)
+
+bazel_dep(name = "googletest", version = "1.14.0")
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 33b5f76..0000000
--- a/Makefile
+++ /dev/null
@@ -1,64 +0,0 @@
-# =====================================================================
-# spdx-license-identifier: ISC
-# glitch top-level makefile
-# =====================================================================
-
-MAKE := make
-MAKEID := $(shell ${MAKE} --version | head -n1)
-MAKEFLAGS += -rR --no-print-directory
-
-ARCH := $(shell sed -nE "s/CONFIG_ARCH_(.+)=y/\1/p" .config)
-
-.PHONY: all help info run doc clean test valgrind
-all: Makefile.config
- @${MAKE} -f Makefile.all
-
-help:
- @echo "info: show current configuration"
- @echo "all: build kernel image"
- @echo "run: run kernel image in qemu"
- @echo "test: run all tests"
- @echo "valgrind: run all tests in valgrind"
-
-info: Makefile.config
- @echo "- make:"
- @echo " MAKE: ${MAKE}"
- @echo " MAKEID: ${MAKEID}"
- @echo " MAKEFLAGS: ${MAKEFLAGS}"
- @${MAKE} -f Makefile.all $@
-
-run: Makefile.config
- @${MAKE} -f Makefile.all $@
-
-doc: doxygen.config
- doxygen $<
-
-clean:
- @${MAKE} -C lib clean
- @${MAKE} -C ${ARCH} clean
- @${MAKE} -C devices clean
- @${MAKE} -C src clean
-
-test:
- @echo " -> Running tests in src"
- @make -C src test > /dev/null
- @echo " -> Running tests in lib"
- @make -C lib test > /dev/null
-
-valgrind:
- @echo " -> Running valgrind on tests in lib"
- @make -C lib valgrind &> /dev/null
- @echo " -> Running valgrind on tests in src"
- @make -C src valgrind &> /dev/null
-
-# configure targets
-.config: Kconfig
- @alldefconfig
-
-Makefile.config: .config ${ARCH}/toolchain.mk
- @echo -e '## This is a generated file, manual edits might be lost' > Makefile.config
- @echo -e '\n## .config' >> Makefile.config
- @cat .config >> Makefile.config
- @echo -e '\n## toolchain.mk' >> Makefile.config
- @cat ${ARCH}/toolchain.mk >> Makefile.config
-
diff --git a/Makefile.all b/Makefile.all
deleted file mode 100644
index a92631f..0000000
--- a/Makefile.all
+++ /dev/null
@@ -1,61 +0,0 @@
-# =====================================================================
-# spdx-license-identifier: ISC
-# glitch kernel binary and image generation
-# =====================================================================
-
-include Makefile.config
-
-${ARCH}_LDFLAGS += -T ${ARCH}/linker.ld
-
-TARGETBIN += glitch
-glitch.OBJS += ${ARCH}/arch.a src/kernel.a devices/devs.a lib/libk.a
-
-include rules.mk
-
-.PHONY: run info
-run: glitch.iso
- @${QEMU} -cdrom $^ -d cpu_reset -display gtk,zoom-to-fit=on
-
-info:
- @echo "- target:"
- @echo " ARCH: ${ARCH}"
- @echo " CC: ${${ARCH}_CC}"
- @echo " CCID: ${${ARCH}_CCID}"
- @echo " CFLAGS: ${${ARCH}_CFLAGS}"
- @echo " CXX: ${${ARCH}_CXX}"
- @echo " CXXID: ${${ARCH}_CXXID}"
- @echo " CXXFLAGS: ${${ARCH}_CXXFLAGS}"
- @echo " LD: ${${ARCH}_LD}"
- @echo " LDID: ${${ARCH}_LDID}"
- @echo " LDFLAGS: ${${ARCH}_LDFLAGS}"
- @echo "- host:"
- @echo " CC: ${HOST_CC}"
- @echo " CFLAGS: ${HOST_CFLAGS}"
- @echo " CXX: ${HOST_CXX}"
- @echo " CXXFLAGS: ${HOST_CXXFLAGS}"
- @echo " QEMU: ${QEMU}"
-
-# build targets
-
-glitch.iso: glitch.elf grub/grub.cfg
- @grub-file --is-x86-multiboot2 glitch.elf
- @mkdir -p isodir/boot/grub
- @mkdir -p isodir/boot/glitch
- @grub-script-check grub/grub.cfg
- @cp grub/grub.cfg isodir/boot/grub/grub.cfg
- @cp glitch.elf isodir/boot/glitch/glitch.elf
- @i686-elf-strip isodir/boot/glitch/glitch.elf
- @rm -f isodir/boot/glitch/checksums
- @sha512sum isodir/boot/glitch/* > isodir/boot/glitch/checksums
- @sed -i s/isodir// isodir/boot/glitch/checksums
- @grub-mkrescue -o glitch.iso isodir
-
-lib/libk.a: FORCE
- @${MAKE} -C lib libk.a
-i686/arch.a: FORCE
- @${MAKE} -C ${ARCH} arch.a
-devices/devs.a: FORCE
- @${MAKE} -C devices devs.a
-src/kernel.a: FORCE
- @${MAKE} -C src kernel.a
-
diff --git a/Makefile.config b/Makefile.config
deleted file mode 100644
index c771677..0000000
--- a/Makefile.config
+++ /dev/null
@@ -1,72 +0,0 @@
-## This is a generated file, manual edits might be lost
-
-## .config
-#
-# Automatically generated file; DO NOT EDIT.
-# Main menu
-#
-
-#
-# Toolchain
-#
-CONFIG_CFLAGS="-g -Og"
-CONFIG_CXXFLAGS="-g -Og"
-CONFIG_LDFLAGS=""
-# end of Toolchain
-
-#
-# Target
-#
-CONFIG_ARCH_i686=y
-# end of Target
-
-#
-# Devices
-#
-CONFIG_PIC_8259=y
-CONFIG_UART_16550=y
-CONFIG_VGA_TEXT_MODE=y
-CONFIG_KB_PS2=y
-# end of Devices
-
-## toolchain.mk
-ARCH=i686
-
-# define compiler, linker, archiver and strip and their flags
-# FIXME: cpp threadsafe statics
-${ARCH}_AS := i686-elf-as
-
-${ARCH}_CC := i686-elf-gcc
-${ARCH}_CCID := $(shell ${${ARCH}_CC} --version | head -n1)
-${ARCH}_CFLAGS := -Wall -Wextra -Wpedantic -Werror=shadow -Wconversion -fanalyzer -ffreestanding -std=gnu11 \
- -mgeneral-regs-only \
- $(shell echo ${CONFIG_CFLAGS})
-
-${ARCH}_CXX := i686-elf-g++
-${ARCH}_CXXID := $(shell ${${ARCH}_CXX} --version | head -n1)
-${ARCH}_CXXFLAGS := -Wall -Wextra -Wpedantic -Werror=shadow -Wconversion -ffreestanding -std=c++17 \
- -mgeneral-regs-only -fno-use-cxa-atexit -fno-threadsafe-statics -fno-exceptions -fno-rtti \
- $(shell echo ${CONFIG_CXXFLAGS})
-
-${ARCH}_LD := i686-elf-ld
-${ARCH}_LDID := $(shell ${${ARCH}_LD} --version | head -n1)
-${ARCH}_LDFLAGS := -static -nostdlib \
- $(shell echo ${CONFIG_LDFLAGS})
-
-${ARCH}_AR := i686-elf-ar
-${ARCH}_ARFLAGS := -crus
-
-${ARCH}_STRIP := i686-elf-strip
-
-# define compiler and flags for test targets
-HOST_CC := gcc
-HOST_CFLAGS := -Wall -Wextra -Wpedantic -Werror=shadow -Wconversion \
- ${CFLAGS}
-HOST_CXX := g++
-HOST_CXXFLAGS := -Wall -Wextra -Wpedantic -Werror=shadow -Wconversion -g -Og \
- $(shell pkg-config --cflags --libs gtest gtest_main gmock) \
- ${CXXFLAGS}
-
-# emulator name and flags
-QEMU := qemu-system-i386 -accel kvm -machine pc
-
diff --git a/README.md b/README.md
index 5323f56..e8adecd 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,10 @@
## A simple kernel written in C
+## supported platforms
+- i686
+
+Supported toolchains are defined in $ARCH/toolchain.mk
+
## drivers
- uart: 16550 (write)
- vga text mode
@@ -7,6 +12,7 @@
- ps2 controller: i8042, with keyboard and mouse
## building
+- Code is ANSI C
prerequisites:
* i686-elf-gcc, i686-elf-binutils
* for bootable iso image: grub, mtools
diff --git a/arch/i386/BUILD.bazel b/arch/i386/BUILD.bazel
new file mode 100644
index 0000000..2842a5b
--- /dev/null
+++ b/arch/i386/BUILD.bazel
@@ -0,0 +1,44 @@
+exports_files(
+ ["linker.ld"],
+ visibility = ["//visibility:public"],
+)
+
+cc_library(
+ name = "arch",
+ srcs = [
+ "boot.s",
+ "gdt.c",
+ "init.s",
+ "isr.c",
+ "lgdt.c",
+ "lidt.c",
+ ],
+ hdrs = [
+ "gdt.h",
+ "idt.h",
+ "paging.h",
+ ] + glob(["sys/*.h"]),
+ includes = ["."],
+ target_compatible_with = [
+ "@platforms//os:none",
+ ],
+ visibility = ["//visibility:public"],
+ deps = ["//lib/libk:k"],
+)
+
+# tests
+cc_test(
+ name = "test_gdt",
+ srcs = [
+ "gdt.c",
+ "gdt.h",
+ "test_gdt.cc",
+ ],
+ target_compatible_with = select({
+ "@platforms//os:none": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ }),
+ deps = [
+ "@googletest//:gtest_main",
+ ],
+)
diff --git a/i686/boot.S b/arch/i386/boot.s
index 1eea9a3..40b0389 100644
--- a/i686/boot.S
+++ b/arch/i386/boot.s
@@ -1,6 +1,37 @@
-#define ASM_FILE
-#include <multiboot2.h>
-#include "macros.s"
+/* The magic field should contain this. */
+.set MULTIBOOT2_HEADER_MAGIC, 0xe85250d6
+/* This should be in %eax. */
+.set MULTIBOOT2_BOOTLOADER_MAGIC, 0x36d76289
+.set MULTIBOOT_ARCHITECTURE_I386, 0
+.set MULTIBOOT_HEADER_TAG_END, 0
+.set MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST, 1
+.set MULTIBOOT_TAG_TYPE_MMAP, 6
+
+.set PAGE_RO, 0x001
+.set PAGE_RW, 0x003
+
+/* write section to page table macro
+ *
+ * Registers used:
+ * %ecx: loop counter [ set to $1024 ]
+ * %edx: temporary
+ * %esi: current page being mapped
+ * %edi: page entry [ set to $page_addr ]
+ */
+.macro mmap_section begin, end, access
+ mov $\begin, %esi # from $begin
+1: cmpl $\end, %esi # until $end
+ jge 2f
+
+ movl %esi, %edx
+ orl $\access, %edx
+ movl %edx, (%edi)
+
+ addl $4096, %esi # move to next page
+ addl $4, %edi # size of page entry is 4 bytes
+ loop 1b # loop according to %ecx
+2:
+.endm
/* Declare a multiboot header that marks this program as a kernel */
.section .multiboot.header, "a"
diff --git a/i686/gdt.c b/arch/i386/gdt.c
index c0898f3..3148096 100644
--- a/i686/gdt.c
+++ b/arch/i386/gdt.c
@@ -4,11 +4,11 @@ void
SegmentDescriptor(struct SegmentDescriptor_t *self, unsigned base, unsigned limit, uint8_t access)
{
self->base_15_0 = base & 0xffff;
- self->base_23_16 = (base >> 16) & 0xff;
- self->base_31_24 = (base >> 24) & 0xff;
+ self->base_23_16 = (uint8_t)(base >> 16);
+ self->base_31_24 = (uint8_t)(base >> 24);
self->limit_15_0 = (limit <= 0xffff) ? (limit & 0xffff) : ((limit >> 12) & 0xffff);
- self->limit_19_16 = (limit <= 0xffff) ? 0 : ((limit >> 28) & 0xf);
+ self->limit_19_16 = 0xfu & (uint8_t)((limit <= 0xffff) ? 0 : (limit >> 28));
self->access = access;
diff --git a/arch/i386/gdt.h b/arch/i386/gdt.h
new file mode 100644
index 0000000..2bdfb22
--- /dev/null
+++ b/arch/i386/gdt.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+enum Ring { Ring0 = 0x0, Ring1 = 0x1, Ring2 = 0x2, Ring3 = 0x3 };
+
+struct __attribute__((packed)) Access {
+ unsigned accessed : 1; /* if 0, is set by processor when accessed */
+ unsigned readwrite : 1; /* code seg: read toggle; data seg: write toggle */
+ unsigned direction : 1; /* code seg: conforming bit; data seg: direction bit */
+ unsigned executable : 1; /* executable bit */
+ unsigned segment : 1; /* true for code/data; false for gates/tss */
+ unsigned privilege : 2; /* descriptor privilege level */
+ unsigned present : 1; /* true for every active segment */
+};
+/* _Static_assert(sizeof(struct Access) == 1, "access byte size"); */
+
+static const struct Access null_access = {0, 0, 0, 0, 0, Ring0, 0};
+static const struct Access ktext_access = {0, 1, 0, 1, 1, Ring0, 1};
+static const struct Access kdata_access = {0, 1, 0, 0, 1, Ring0, 1};
+
+/* Segment Descriptor
+ * A memory structure (part of a table) that tells the CPU the attributes of a given segment
+ * |31| | | | | | |24|23|22|21|20|19| | |16|15| | | | | | | 8| 7| | | | | | | 0|
+ * | base_31_24 | G|DB| | A| lim_19_16 | access | base_23_16 |
+ * | base_15_0 | limit_15_0 |
+ * |31| | | | | | | | | | | | | | |16|15| | | | | | | | | | | | | | | 0|
+ * limit size of segment - 1, either in bytes or in 4KiB chunks (check flags)
+ * base address of segment
+ * access
+ * flags defines the segment chunks and 16/32 bit */
+struct __attribute__((packed)) SegmentDescriptor_t {
+ uint16_t limit_15_0; /* low bits of segment limit */
+ uint16_t base_15_0; /* low bits of segment base address */
+ uint8_t base_23_16; /* middle bits of segment base address */
+ uint8_t access; /* access byte */
+ unsigned limit_19_16 : 4; /* high bits of segment limit */
+ /* flags */
+ bool a : 1; /* unused, available for software use */
+ bool rsv : 1; /* reserved */
+ bool db : 1; /* false => 16-bit seg; true => 32-bit seg */
+ bool granularity : 1; /* limit scaled by 4k when set */
+ uint8_t base_31_24; /* high bits of segment address */
+};
+/* _Static_assert(sizeof(struct SegmentDescriptor_t) == 8, "segment descriptor size"); */
+
+void SegmentDescriptor(struct SegmentDescriptor_t *self, unsigned base, unsigned limit, uint8_t access);
+
+void gdt_install();
+
+enum SegmentIndex {
+ ktextDescriptor = 2 * sizeof(struct SegmentDescriptor_t),
+ kdataDescriptor = 3 * sizeof(struct SegmentDescriptor_t)
+};
diff --git a/i686/idt.h b/arch/i386/idt.h
index 45744dc..ca39bde 100644
--- a/i686/idt.h
+++ b/arch/i386/idt.h
@@ -10,14 +10,14 @@ struct interrupt_frame {
uint32_t ss;
};
-// typedef void (*irq_handler)();
+/* typedef void (*irq_handler)(); */
/* isr.c */
void abort_handler(struct interrupt_frame *frame);
void syscall_handler(struct interrupt_frame *frame);
-void irq0x00(struct interrupt_frame *frame); // timer interrupt
-void irq0x01(struct interrupt_frame *frame); // keyboard interrupt
-void irq0x0c(struct interrupt_frame *frame); // mouse interrupt
+void irq0x00(struct interrupt_frame *frame); /* timer interrupt */
+void irq0x01(struct interrupt_frame *frame); /* keyboard interrupt */
+void irq0x0c(struct interrupt_frame *frame); /* mouse interrupt */
/* lidt.c */
void idt_install();
diff --git a/i686/init.s b/arch/i386/init.s
index ad329bb..ad329bb 100644
--- a/i686/init.s
+++ b/arch/i386/init.s
diff --git a/i686/isr.c b/arch/i386/isr.c
index 8af5d33..acc2961 100644
--- a/i686/isr.c
+++ b/arch/i386/isr.c
@@ -20,7 +20,7 @@ __attribute__((interrupt)) void
syscall_handler(__attribute__((unused)) struct interrupt_frame *frame)
{
unsigned int n;
- asm volatile("mov %%eax, %0" : "=r"(n));
+ __asm__("mov %%eax, %0" : "=r"(n));
printf("syscall %x\n, n");
abort();
}
diff --git a/arch/i386/lgdt.c b/arch/i386/lgdt.c
new file mode 100644
index 0000000..473a91d
--- /dev/null
+++ b/arch/i386/lgdt.c
@@ -0,0 +1,25 @@
+#include "gdt.h"
+
+struct __attribute__((packed)) Pointer {
+ uint16_t limit;
+ uint32_t base;
+};
+
+static struct SegmentDescriptor_t segments[8] __attribute__((aligned(32)));
+
+void
+gdt_install()
+{
+ const struct Pointer ptr = {sizeof(segments) - 1, (unsigned)&segments};
+ SegmentDescriptor(&segments[0], 0, 0, 0); /* null segment */
+ SegmentDescriptor(&segments[2], 0, 0xffffffff, 0x9a); /* ktext segment */
+ SegmentDescriptor(&segments[3], 0, 0xffffffff, 0x92); /* kdata segment */
+
+ __asm__("lgdt (%0)" : : "a"(&ptr));
+
+ /* load the kernel data segment */
+ __asm__("mov %0, %%ds; mov %0, %%es; mov %0, %%fs; mov %0, %%gs; mov %0, %%ss" : : "ax"(kdataDescriptor));
+
+ /* load the kernel code segment */
+ __asm__("ljmp %0, $1f\n1:" : : "i"(ktextDescriptor));
+}
diff --git a/arch/i386/lidt.c b/arch/i386/lidt.c
new file mode 100644
index 0000000..86567f8
--- /dev/null
+++ b/arch/i386/lidt.c
@@ -0,0 +1,55 @@
+#include "idt.h"
+#include <stdint.h>
+
+struct __attribute__((packed)) Pointer {
+ uint16_t limit;
+ uint32_t base;
+};
+
+enum Type {
+ Null = 0,
+ Intr = 0x8e /* 1000 1110 32-bit interrupt */
+};
+
+struct __attribute__((packed)) Gate_t {
+ uint16_t offset_15_0; /* segment offset low */
+ uint16_t selector; /* code segment selector */
+ uint8_t __unused; /* unused in protected mode */
+ uint8_t type; /* interrupt type */
+ uint16_t offset_31_16; /* segment offset high */
+};
+/* _Static_assert(sizeof(struct Gate_t) == 8, "interrupt gate size"); */
+
+void
+Gate(struct Gate_t *entry, void (*f)(struct interrupt_frame *), uint16_t selector)
+{
+ uint32_t f_addr = (uint32_t)f;
+ entry->offset_15_0 = f_addr & 0xffff;
+ entry->offset_31_16 = (uint16_t)(f_addr >> 16) & 0xffff;
+ entry->selector = selector;
+ entry->__unused = 0;
+ entry->type = Intr;
+}
+
+static struct Gate_t interrupt_table[256] __attribute((aligned(4096)));
+
+void
+idt_install()
+{
+ int i;
+ const struct Pointer ptr = {sizeof(interrupt_table) - 1, (unsigned)&interrupt_table};
+
+ /* exceptions 0x00~0x13 */
+ for (i = 0; i <= 0x13; ++i) Gate(&interrupt_table[i], &abort_handler, 0x10);
+
+ /* irq 0x20~0x2f */
+ for (i = 0x22; i <= 0x2f; ++i) Gate(&interrupt_table[i], &abort_handler, 0x10);
+ Gate(&interrupt_table[0x20], &irq0x00, 0x10);
+ Gate(&interrupt_table[0x21], &irq0x01, 0x10);
+ Gate(&interrupt_table[0x2c], &irq0x0c, 0x10);
+
+ /* syscall 0x80 */
+ Gate(&interrupt_table[0x80], &syscall_handler, 0x10);
+
+ __asm__("lidt (%0)" : : "a"(&ptr));
+}
diff --git a/i686/linker.ld b/arch/i386/linker.ld
index 61a3be9..61a3be9 100644
--- a/i686/linker.ld
+++ b/arch/i386/linker.ld
diff --git a/arch/i386/paging.h b/arch/i386/paging.h
new file mode 100644
index 0000000..f5bfa78
--- /dev/null
+++ b/arch/i386/paging.h
@@ -0,0 +1,59 @@
+#pragma once
+
+/* DirectoryEntry
+ * |31| | | | | | | | | | | | | | | | | | | |11| | 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+ * | page table 4-kb aligned address | avail | G| S| | A| C| W| U| R| P| */
+struct __attribute__((packed)) DirectoryEntry {
+ unsigned present : 1; /* 0: if set, the page is actually in physical memory */
+ unsigned writeable : 1; /* 1: if set, the page is read/write; otherwise the page is read-only */
+ unsigned user : 1; /* 2: if set, then page can be access by all; otherwise only the supervisor can access it */
+ unsigned writethrough : 1; /* 3: if set, write-through caching is enabled; otherwise write-back is enabled instead */
+ unsigned cachedisable : 1; /* 4: if set, the page will not be cached */
+ unsigned accessed : 1; /* 5: set by the CPU when the page is read from or written to */
+ unsigned dirty : 1; /* 6: used to determine whether a page has been written to */
+ unsigned pagesize : 1; /* 7: page size == 0 */
+ unsigned global : 1;
+ unsigned int __available__ : 3; /* available to the OS */
+ unsigned int address : 20;
+};
+/* TODO _Static_assert(sizeof(struct DirectoryEntry) == 4, "DirectoryEntry size"); */
+
+/* DirectoryEntry4MB
+ * |31| | | | | | | | |22|21|20| | | | | | |13|12|11| | 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+ * | bits 31-22 of address |RS| bits 39-22 of |AT| avail | G|PS| D| A|CD|WT|US|RW| P|
+ * | |VD| address */
+struct __attribute__((packed)) DirectoryEntry4MB {
+ unsigned present : 1; /* 0: if set, the page is actually in physical memory */
+ unsigned writeable : 1; /* 1: if set, the page is read/write; otherwise the page is read-only */
+ unsigned useraccess : 1; /* 2: if set, then page can be access by all; otherwise only the supervisor can access it */
+ unsigned writethrough : 1; /* 3: if set, write-through caching is enabled; otherwise write-back is enabled instead */
+ unsigned cachedisable : 1; /* 4: if set, the page will not be cached */
+ unsigned accessed : 1; /* 5: set by the CPU when the page is read from or written to */
+ unsigned dirty : 1; /* 6: used to determine whether a page has been written to */
+ unsigned pagesize : 1; /* 7: page size == 1 */
+ unsigned global : 1; /* 8: */
+ unsigned __available__ : 3; /* 11..9 available to the OS */
+ unsigned pat : 1; /* 12: page attribute table */
+ unsigned int address_high : 8;
+ unsigned rsvd : 1; /* 21 */
+ unsigned int address_low : 10;
+};
+/* TODO _Static_assert(sizeof(struct DirectoryEntry4MB) == 4, "DirectoryEntry4M size"); */
+
+/* TableEntry
+ * |31| | | | | | | | | | | | | | | | | | | |11| | 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+ * | page table 4-kb aligned address | avail | G| | D| A| C| W|US|RW| P| */
+struct __attribute__((packed)) TableEntry {
+ unsigned present : 1; /* if set, the page is actually in physical memory */
+ unsigned writeable : 1; /* if set, the page is read/write; otherwise the page is read-only */
+ unsigned user : 1; /* if set, then page can be access by all; otherwise only the supervisor can access it */
+ unsigned writethrough : 1; /* if set, write-through caching is enabled; otherwise write-back is enabled instead */
+ unsigned cachedisable : 1; /* if set, the page will not be cached */
+ unsigned accessed : 1; /* set by the CPU when the page is read from or written to */
+ unsigned dirty : 1; /* used to determine whether a page has been written to */
+ unsigned pat : 1; /* page attribute table? */
+ unsigned global : 1;
+ unsigned int __available__ : 3; /* available to the OS */
+ unsigned int address : 20;
+};
+/* TODO _Static_assert(sizeof(struct TableEntry) == 4, "TableEntry size"); */
diff --git a/arch/i386/sys/control.h b/arch/i386/sys/control.h
new file mode 100644
index 0000000..89ab067
--- /dev/null
+++ b/arch/i386/sys/control.h
@@ -0,0 +1,24 @@
+#pragma once
+
+static __inline__ void
+abort()
+{
+ /* Symbol h is already defined?
+__asm__(R"(cli
+h: hlt
+jmp h)");
+*/
+ __asm__("cli; hlt");
+}
+
+static __inline__ void
+enable_interrupts()
+{
+ __asm__("sti");
+}
+
+static __inline__ void
+disable_interrupts()
+{
+ __asm__("cli");
+}
diff --git a/i686/sys/cpuid.h b/arch/i386/sys/cpuid.h
index 65b43c6..6613967 100644
--- a/i686/sys/cpuid.h
+++ b/arch/i386/sys/cpuid.h
@@ -12,7 +12,7 @@ struct CPUVersion {
unsigned int family_ex : 8;
unsigned int __unused_2 : 4;
} __attribute__((packed, aligned(__alignof__(unsigned int))));
-// FIXME _Static_assert(sizeof(struct CPUVersion) == sizeof(unsigned int), "cpuid version struct size");
+/* FIXME _Static_assert(sizeof(struct CPUVersion) == sizeof(unsigned int), "cpuid version struct size"); */
unsigned int
family(const struct CPUVersion v)
diff --git a/arch/i386/sys/io.h b/arch/i386/sys/io.h
new file mode 100644
index 0000000..4ff5d85
--- /dev/null
+++ b/arch/i386/sys/io.h
@@ -0,0 +1,92 @@
+#pragma once
+
+/* port listings */
+enum UART {
+ COM1 = 0x3f8,
+ COM2 = 0x2f8,
+ COM3 = 0x3e8,
+ COM4 = 0x2e8,
+ COM5 = 0x5f8,
+ COM6 = 0x4f8,
+ COM7 = 0x5e8,
+ COM8 = 0x4e8
+};
+
+static __inline__ void
+outb(unsigned char val, unsigned short port)
+{
+ __asm__("outb %0,%1" : : "a"(val), "dN"(port));
+}
+
+static __inline__ void
+outw(unsigned short val, unsigned short port)
+{
+ __asm__("outw %0,%1" : : "a"(val), "dN"(port));
+}
+
+static __inline__ void
+outl(unsigned int val, unsigned short port)
+{
+ __asm__("outl %0,%1" : : "a"(val), "dN"(port));
+}
+
+static __inline__ unsigned char
+inb(unsigned short port)
+{
+ unsigned char val;
+ __asm__("inb %1,%0" : "=a"(val) : "dN"(port));
+ return val;
+}
+
+static __inline__ unsigned short
+inw(unsigned short port)
+{
+ unsigned short val;
+ __asm__("inw %1,%0" : "=a"(val) : "dN"(port));
+ return val;
+}
+
+static __inline__ unsigned int
+inl(unsigned short port)
+{
+ unsigned int val;
+ __asm__("inl %1,%0" : "=a"(val) : "dN"(port));
+ return val;
+}
+
+static __inline__ void
+outsb(unsigned short port, const void *__buf, unsigned long __n)
+{
+ __asm__("cld; rep; outsb" : "+S"(__buf), "+c"(__n) : "d"(port));
+}
+
+static __inline__ void
+outsw(unsigned short port, const void *__buf, unsigned long __n)
+{
+ __asm__("cld; rep; outsw" : "+S"(__buf), "+c"(__n) : "d"(port));
+}
+
+static __inline__ void
+outsl(unsigned short port, const void *__buf, unsigned long __n)
+{
+ __asm__("cld; rep; outsl" : "+S"(__buf), "+c"(__n) : "d"(port));
+}
+
+static __inline__ void
+insb(unsigned short port, void *__buf, unsigned long __n)
+{
+ __asm__("cld; rep; insb" : "+D"(__buf), "+c"(__n) : "d"(port));
+}
+
+static __inline__ void
+insw(unsigned short port, void *__buf, unsigned long __n)
+{
+ __asm__("cld; rep; insw" : "+D"(__buf), "+c"(__n) : "d"(port));
+}
+
+static __inline__ void
+insl(unsigned short port, void *__buf, unsigned long __n)
+{
+ __asm__("cld; rep; insl" : "+D"(__buf), "+c"(__n) : "d"(port));
+}
+
diff --git a/i686/sys/syscall.h b/arch/i386/sys/syscall.h
index 9e62c89..9e62c89 100644
--- a/i686/sys/syscall.h
+++ b/arch/i386/sys/syscall.h
diff --git a/arch/i386/test_gdt.cc b/arch/i386/test_gdt.cc
new file mode 100644
index 0000000..3501ae9
--- /dev/null
+++ b/arch/i386/test_gdt.cc
@@ -0,0 +1,25 @@
+#include <gtest/gtest.h>
+
+extern "C" {
+#include "gdt.h"
+}
+
+TEST(i686GDT, KnownAccessByteValues)
+{
+ EXPECT_EQ(*(uint8_t *)&null_access, 0x00);
+ EXPECT_EQ(*(uint8_t *)&ktext_access, 0x9a);
+ EXPECT_EQ(*(uint8_t *)&kdata_access, 0x92);
+}
+
+TEST(i686GDT, NullSegmentDescriptor)
+{
+ struct SegmentDescriptor_t d;
+ SegmentDescriptor(&d, 0, 0, 0);
+ EXPECT_EQ(*(uint64_t *)&d, 0);
+}
+
+TEST(i686GDT, SegmentIndex)
+{
+ EXPECT_EQ(ktextDescriptor, 0x10);
+ EXPECT_EQ(kdataDescriptor, 0x18);
+}
diff --git a/devices/BUILD.bazel b/devices/BUILD.bazel
new file mode 100644
index 0000000..0c58d48
--- /dev/null
+++ b/devices/BUILD.bazel
@@ -0,0 +1,22 @@
+cc_library(
+ name = "drivers",
+ srcs = [
+ "i8042.c",
+ "mouse.c",
+ "pckbd.c",
+ "pic_8259.c",
+ "uart/uart_16550.c",
+ "uart/uart_16550.h",
+ "vga.c",
+ ],
+ hdrs = glob(["include/*.h"]),
+ defines = [
+ "__ARCH__=i386",
+ ],
+ includes = ["include"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//arch/i386:arch",
+ "//lib/libk:k",
+ ],
+)
diff --git a/devices/Makefile b/devices/Makefile
deleted file mode 100644
index 3c61f6d..0000000
--- a/devices/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-include ../Makefile.config
-
-INCLUDES := -I../${ARCH}
-${ARCH}_CFLAGS += ${INCLUDES}
-${ARCH}_CXXFLAGS += ${INCLUDES}
-
-TARGETLIB += devs
-devs.SRCS = pic_8259.c uart_16550.cpp vga.cpp i8042.c pckbd.c mouse.c
-
-include ../rules.mk
-
diff --git a/devices/i8042.c b/devices/i8042.c
index c612e6d..cfd96a8 100644
--- a/devices/i8042.c
+++ b/devices/i8042.c
@@ -8,8 +8,8 @@
#include <stdio.h>
#include <sys/io.h>
-// r status register
-// w command register
+/* r status register */
+/* w command register */
#define comm_port 0x64
#define comm_enable_first_ps2 0xae
#define comm_enable_second_ps2 0xa8
@@ -19,16 +19,18 @@
#define data_port 0x60
#define data_enable_scanning 0xf4
-// TODO: All output to port 0x60 or 0x64 must be preceded by waiting for bit 1 (value=2) of port 0x64 to become clear.
-// TODO: Similarly, bytes cannot be read from port 0x60 until bit 0 (value=1) of port 0x64 is set.
+/* TODO: All output to port 0x60 or 0x64 must be preceded by waiting for bit 1 (value=2) of port 0x64 to become clear.
+ * TODO: Similarly, bytes cannot be read from port 0x60 until bit 0 (value=1) of port 0x64 is set. */
void
ps2_ctrl_init()
{
- // eat all previous keystrikes
+ int i;
+ uint8_t test, conf;
+
+ /* eat all previous keystrikes */
while (inb(comm_port) & 0x1) inb(data_port);
- uint8_t test;
outb(0xaa, comm_port);
test = inb(data_port);
printf("i8042: self test 0xaa:%x %s\n", test, test == 0x55 ? "ok" : "failed");
@@ -39,30 +41,30 @@ ps2_ctrl_init()
test = inb(data_port);
printf("i8042: port2 test 0xa9:%x %s\n", test, test == 0x00 ? "ok" : "failed");
- // printf("8042: init keyboard\n");
+ /* printf("8042: init keyboard\n"); */
outb(comm_enable_first_ps2, comm_port);
outb(comm_enable_second_ps2, comm_port);
- // resets the cpu
- // outb(0xfe, 0x64);
+ /* resets the cpu */
+ /* outb(0xfe, 0x64); */
outb(0xf2, 0x60);
printf("i8042: id port1: ");
while ((inb(0x64) & 0x01) == 0) {}
- for (int i = 0; i < 3; ++i) printf("%x ", inb(0x60));
+ for (i = 0; i < 3; ++i) printf("%x ", inb(0x60));
printf("\n");
outb(0xd4, 0x64);
outb(0xf2, 0x60);
printf("i8042: id port2: ");
while ((inb(0x64) & 0x01) == 0) {}
- for (int i = 0; i < 3; ++i) printf("%x ", inb(0x60));
+ for (i = 0; i < 3; ++i) printf("%x ", inb(0x60));
printf("\n");
outb(comm_read_ctrl_config, comm_port);
- uint8_t conf = (inb(data_port) | 1) & ~0x10;
- conf |= 0x22; // mouse
+ conf = (uint8_t)((inb(data_port) | 1) & ~0x10);
+ conf |= 0x22; /* mouse */
outb(comm_write_ctrl_config, comm_port);
outb(conf, data_port);
@@ -81,7 +83,6 @@ ps2_read_port1()
unsigned char
ps2_read_port2()
{
-
outb(0xd4, 0x64);
return inb(0x60);
}
diff --git a/devices/keyboard.h b/devices/include/keyboard.h
index 5f4fcc2..5f4fcc2 100644
--- a/devices/keyboard.h
+++ b/devices/include/keyboard.h
diff --git a/devices/mouse.h b/devices/include/mouse.h
index a34ecb4..a34ecb4 100644
--- a/devices/mouse.h
+++ b/devices/include/mouse.h
diff --git a/devices/pic.h b/devices/include/pic.h
index c545c60..c545c60 100644
--- a/devices/pic.h
+++ b/devices/include/pic.h
diff --git a/devices/ps2_controller.h b/devices/include/ps2_controller.h
index d2f7e80..d2f7e80 100644
--- a/devices/ps2_controller.h
+++ b/devices/include/ps2_controller.h
diff --git a/devices/include/uart.h b/devices/include/uart.h
new file mode 100644
index 0000000..8b44519
--- /dev/null
+++ b/devices/include/uart.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#ifdef __ARCH__
+#include <stdio.h>
+#include <sys/io.h>
+
+#else
+/* from stdio */
+typedef struct FILE {
+ int id;
+ void (*putc)(const struct FILE *, char);
+ int (*puts)(const struct FILE *, const char *, int);
+ void (*flush)(const struct FILE *);
+} FILE;
+
+/* from sys/io */
+unsigned char inb(unsigned short);
+void outb(unsigned char, unsigned short);
+
+enum UART {
+ COM1 = 0x3f8,
+ COM2 = 0x2f8,
+ COM3 = 0x3e8,
+ COM4 = 0x2e8,
+ COM5 = 0x5f8,
+ COM6 = 0x4f8,
+ COM7 = 0x5e8,
+ COM8 = 0x4e8,
+};
+#endif
+
+FILE *uart_init(unsigned short port);
diff --git a/devices/include/vga.h b/devices/include/vga.h
new file mode 100644
index 0000000..df0d921
--- /dev/null
+++ b/devices/include/vga.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <stdio.h>
+
+/** Hardware text mode color constants. */
+enum vga_color {
+ VGA_COLOR_BLACK = 0,
+ VGA_COLOR_BLUE = 1,
+ VGA_COLOR_GREEN = 2,
+ VGA_COLOR_CYAN = 3,
+ VGA_COLOR_RED = 4,
+ VGA_COLOR_MAGENTA = 5,
+ VGA_COLOR_BROWN = 6,
+ VGA_COLOR_LIGHT_GREY = 7,
+ VGA_COLOR_DARK_GREY = 8,
+ VGA_COLOR_LIGHT_BLUE = 9,
+ VGA_COLOR_LIGHT_GREEN = 10,
+ VGA_COLOR_LIGHT_CYAN = 11,
+ VGA_COLOR_LIGHT_RED = 12,
+ VGA_COLOR_LIGHT_MAGENTA = 13,
+ VGA_COLOR_LIGHT_BROWN = 14,
+ VGA_COLOR_WHITE = 15
+};
+
+FILE *vga_init(void *addr);
+void vga_clear(enum vga_color foreground, enum vga_color background);
+
+/* void vga_putc(char a); */
+/* void vga_puts(const char *string, int len); */
+
+/* void vga_enable_cursor(unsigned char start, unsigned char end); */
+/* void vga_disable_cursor(); */
+void vga_update_cursor(void);
diff --git a/devices/mouse.c b/devices/mouse.c
index a950e8c..a03388a 100644
--- a/devices/mouse.c
+++ b/devices/mouse.c
@@ -7,29 +7,33 @@
void
mouse_init()
{
- // Sending a command or data byte to the mouse (to port 0x60) must be preceded by sending a 0xD4 byte to port 0x64
- // (with appropriate waits on port 0x64, bit 1, before sending each output byte). Note: this 0xD4 byte does not
- // generate any ACK, from either the keyboard or mouse.
+ int i;
- // enable second ps/2
- // outb(0xa8, 0x64);
+ /* Sending a command or data byte to the mouse (to port 0x60) must be preceded by sending a 0xD4 byte to port 0x64
+ * (with appropriate waits on port 0x64, bit 1, before sending each output byte). Note: this 0xD4 byte does not
+ * generate any ACK, from either the keyboard or mouse. */
- // outb(0x64, 0xd4);
- // outb(0x60, 0xf4);
- // printf("mouse_init: enable streaming(0xf4): %x\n", inb(0x60));
+ /* enable second ps/2 */
+ /* outb(0xa8, 0x64); */
+
+ /* outb(0x64, 0xd4); */
+ /* outb(0x60, 0xf4); */
+ /* printf("mouse_init: enable streaming(0xf4): %x\n", inb(0x60)); */
outb(0xd4, 0x64);
- outb(0xeb, 0x60); // single packet
+ outb(0xeb, 0x60); /* single packet */
printf("mouse_init: single packet 0xeb\n");
while ((inb(0x64) & 0x01) == 0) {}
- for (int i = 0; i < 10; ++i) printf("%x ", inb(0x60));
+ for (i = 0; i < 10; ++i) printf("%x ", inb(0x60));
printf("\n");
}
void
mouse_packet()
{
+ int i;
+
printf("mouse packet: ");
- for (int i = 0; i < 4; ++i) printf("%x ", ps2_read_port2());
+ for (i = 0; i < 4; ++i) printf("%x ", ps2_read_port2());
printf("\n");
}
diff --git a/devices/pckbd.c b/devices/pckbd.c
index d550f91..0e99fe6 100644
--- a/devices/pckbd.c
+++ b/devices/pckbd.c
@@ -26,22 +26,22 @@ ps2_keyboard_irq_handler()
const uint8_t key = ps2_read_port1();
switch (key) {
- case 0x2a: // left shift down
- case 0x36: // right shift down
+ case 0x2a: /* left shift down */
+ case 0x36: /* right shift down */
shift_case = 1;
return;
- case 0xaa: // left shift up
- case 0xb6: // right shift up
+ case 0xaa: /* left shift up */
+ case 0xb6: /* right shift up */
shift_case = 0;
return;
- case 0x5b: // left meta
- case 0x5c: // right meta
+ case 0x5b: /* left meta */
+ case 0x5c: /* right meta */
return;
- case 0x58: // F12
- // vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY);
+ case 0x58: /* F12 */
+ /* vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY); */
return;
}
diff --git a/devices/pic_8259.c b/devices/pic_8259.c
index 75a2d0e..75aaf6d 100644
--- a/devices/pic_8259.c
+++ b/devices/pic_8259.c
@@ -6,11 +6,11 @@
#define PIC2 0xa0
#define DATA 1
-// initialization
+/* initialization */
#define ICW1_INIT 0x10
-// TODO
+/* TODO */
#define ICW1_ICW4 0x01
-// 8086/88 mode
+/* 8086/88 mode */
#define ICW4_8086 0x01
void
@@ -19,31 +19,39 @@ pic_init()
outb(ICW1_INIT | ICW1_ICW4, PIC1);
outb(ICW1_INIT | ICW1_ICW4, PIC2);
- outb(0x20, PIC1 + DATA); // offset 0x20
- outb(0x28, PIC2 + DATA); // offset 0x28
+ outb(0x20, PIC1 + DATA); /* offset 0x20 */
+ outb(0x28, PIC2 + DATA); /* offset 0x28 */
- outb(0x04, PIC1 + DATA); // tell master pic there is a slave pic
- outb(0x02, PIC2 + DATA); // tell slave pic its cascade identity
+ outb(0x04, PIC1 + DATA); /* tell master pic there is a slave pic */
+ outb(0x02, PIC2 + DATA); /* tell slave pic its cascade identity */
outb(ICW4_8086, PIC1 + DATA);
outb(ICW4_8086, PIC2 + DATA);
- // PIC masks
+ /* PIC masks */
outb(0xff, PIC1 + DATA);
outb(0xff, PIC2 + DATA);
}
+static unsigned char
+irq_mask(unsigned char irq)
+{
+ unsigned char mask = (unsigned char)~(1u << irq);
+ return 0xff & mask;
+}
+
void
pic_enable()
{
unsigned char mask1 = 0xff;
- mask1 &= ~(1 << 0); // irq0 timer
- mask1 &= ~(1 << 1); // irq1 keyboard
- mask1 &= ~(1 << 2); // irq1 cascade
+ unsigned char mask2 = 0xff;
+
+ mask1 &= irq_mask(0); /* irq0 timer */
+ mask1 &= irq_mask(1); /* irq1 keyboard */
+ mask1 &= irq_mask(2); /* irq2 cascade */
outb(mask1, PIC1 + DATA);
- unsigned char mask2 = 0xff;
- mask2 &= ~(1 << 4); // irq12 mouse
+ mask2 &= irq_mask(12 - 8); /* irq12 mouse */
outb(mask2, PIC2 + DATA);
enable_interrupts();
diff --git a/devices/uart.hpp b/devices/uart.hpp
deleted file mode 100644
index c86557c..0000000
--- a/devices/uart.hpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#pragma once
-
-#include <stdio.h>
-#include <sys/io.h>
-
-template <UART port> FILE *uart_init();
-template <> FILE *uart_init<COM1>();
diff --git a/devices/uart/sys_io.hh b/devices/uart/sys_io.hh
new file mode 100644
index 0000000..142c9c1
--- /dev/null
+++ b/devices/uart/sys_io.hh
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <gmock/gmock.h>
+
+class IPort {
+public:
+ virtual unsigned char inb(unsigned short) const = 0;
+ virtual void outb(unsigned char, unsigned short) const = 0;
+};
+
+class MockPort : public IPort {
+public:
+ MOCK_METHOD(unsigned char, inb, (unsigned short), (const, override));
+ MOCK_METHOD(void, outb, (unsigned char, unsigned short), (const, override));
+};
+
+static std::unique_ptr<MockPort> mockPort;
+
+// mock free functions
+extern "C" {
+unsigned char
+inb(unsigned short v)
+{
+ EXPECT_TRUE(mockPort) << "MockPort was not set up by the test fixture";
+ return mockPort->inb(v);
+}
+
+void
+outb(unsigned char p, unsigned short v)
+{
+ EXPECT_TRUE(mockPort) << "MockPort was not set up by the test fixture";
+ return mockPort->outb(p, v);
+}
+}
diff --git a/devices/uart/uart_16550.c b/devices/uart/uart_16550.c
new file mode 100644
index 0000000..4697cf3
--- /dev/null
+++ b/devices/uart/uart_16550.c
@@ -0,0 +1,78 @@
+#include "uart_16550.h"
+#include <stddef.h>
+
+int
+uart_thre(unsigned short port)
+{
+ return inb(port + LineStatus) & THRE;
+}
+
+void
+uart_putc(const FILE *self, char a)
+{
+ const unsigned short port = (unsigned short)self->id;
+
+ while (uart_thre(port) == 0) {}
+ outb((unsigned char)a, port);
+
+ if (a == '\n') {
+ while (uart_thre(port) == 0) {}
+ outb('\r', port);
+ }
+}
+
+int
+uart_puts(const FILE *self, const char *string, int length)
+{
+ int i;
+ int written = 0;
+
+ if (length == -1)
+ while (*string != '\0') {
+ uart_putc(self, *string);
+ ++string;
+ ++written;
+ }
+
+ else
+ for (i = 0; i < length; ++i) {
+ uart_putc(self, string[i]);
+ ++written;
+ }
+
+ return written;
+}
+
+void
+uart_flush(__attribute__((unused)) const FILE *self)
+{
+}
+
+FILE uart_stream;
+
+FILE *
+uart_init(unsigned short port)
+{
+ outb(0x00, port + 1); /* Disable all interrupts */
+ outb(0x80, port + 3); /* Enable DLAB (set baud rate divisor) */
+ outb(0x03, port + 0); /* Set divisor to 3 (lo byte) 38400 baud */
+ outb(0x00, port + 1); /* (hi byte) */
+ outb(0x03, port + 3); /* 8 bits, no parity, one stop bit */
+ outb(0xc7, port + 2); /* Enable FIFO, clear them, with 14-byte threshold */
+ outb(0x0b, port + 4); /* IRQs enabled, RTS/DSR set */
+ outb(0x1e, port + 4); /* Set in loopback mode, test the serial chip */
+ outb(0xae, port + 0); /* Test serial chip (send byte 0xAE and check if serial */
+ /* returns same byte) */
+
+ /* Check if serial is faulty (i.e: not same byte as sent) */
+ if (inb(port + 0) != 0xae) { return NULL; }
+
+ /* If serial is not faulty set it in normal operation mode */
+ /* (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled) */
+ outb(0x0f, port + 4);
+ uart_stream.id = port;
+ uart_stream.putc = &uart_putc;
+ uart_stream.puts = &uart_puts;
+ uart_stream.flush = &uart_flush;
+ return &uart_stream;
+}
diff --git a/devices/uart/uart_16550.h b/devices/uart/uart_16550.h
new file mode 100644
index 0000000..bbeb9b7
--- /dev/null
+++ b/devices/uart/uart_16550.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include "uart.h"
+
+int uart_thre(unsigned short port);
+void uart_putc(const FILE *self, char a);
+int uart_puts(const FILE *self, const char *string, int length);
+void uart_flush(__attribute__((unused)) const FILE *self);
+
+enum uart_16550_offset {
+ Data = 0, /* read from receive buffer / write to transmit buffer | BaudDiv_l */
+ InterruptControl = 1, /* interrupt enable | BaudDiv_h */
+ FifoControl = 2, /* interrupt ID and FIFO control */
+ LineControl = 3, /* most significant bit is the DLAB */
+ ModemControl = 4,
+ LineStatus = 5,
+ ModemStatus = 6,
+ Scratch = 7
+};
+
+/* Line Control
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ * |dla| | parity | s | data | */
+enum LineControl {
+ d5bit = 0x00, /* 0000 0000 data bits */
+ d6bit = 0x01, /* 0000 0001 */
+ d7bit = 0x02, /* 0000 0010 */
+ d8bit = 0x03, /* 0000 0011 */
+ /* none = 0b00000000, // parity bits */
+ odd = 0x08, /* 0000 1000 */
+ even = 0x18, /* 0001 1000 */
+ mark = 0x28, /* 0010 1000 */
+ space = 0x38, /* 0011 1000 */
+ /* s1bit = 0b00000000, // stop bits */
+ s2bit = 0x04, /* 0000 0100 1.5 for 5bit data; 2 otherwise */
+ dlab = 0x80 /* 1000 0000 divisor latch access bit */
+};
+
+/* Line Status Register */
+enum LineStatus {
+ DR = (1 << 0), /* data ready: see if there is data to read */
+ OE = (1 << 1), /* overrun error: see if there has been data lost */
+ PE = (1 << 2), /* parity error: see if there was error in transmission */
+ FE = (1 << 3), /* framing error: see if a stop bit was missing */
+ BI = (1 << 4), /* break indicator: see if there is a break in data input */
+ THRE = (1 << 5), /* transmitter holding register empty: see if transmission buffer is empty */
+ TEMT = (1 << 6), /* transmitter empty: see if transmitter is not doing anything */
+ ERRO = (1 << 7) /* impending error: see if there is an error with a word in the input buffer */
+};
diff --git a/devices/uart/unittest_uart_16550.cc b/devices/uart/unittest_uart_16550.cc
new file mode 100644
index 0000000..f8124bb
--- /dev/null
+++ b/devices/uart/unittest_uart_16550.cc
@@ -0,0 +1,116 @@
+#include "sys_io.hh"
+#include <gtest/gtest.h>
+
+using ::testing::_;
+using ::testing::MockFunction;
+using ::testing::Return;
+
+namespace k {
+extern "C" {
+#include "uart.h"
+#include "uart_16550.h"
+}
+} // namespace k
+
+class Uart16550 : public ::testing::Test {
+protected:
+ void
+ SetUp()
+ {
+ ASSERT_FALSE(mockPort);
+ mockPort.reset(new MockPort);
+ }
+ void
+ TearDown()
+ {
+ ASSERT_TRUE(mockPort);
+ mockPort.reset();
+ }
+};
+
+TEST_F(Uart16550, uart_thre)
+{
+ // set up expectations
+ EXPECT_CALL(*mockPort, inb(k::COM1 + k::LineStatus)).Times(1).WillOnce(Return(k::THRE));
+
+ const auto result = uart_thre(k::COM1);
+ EXPECT_TRUE(result);
+}
+
+TEST_F(Uart16550, uart_putc)
+{
+ k::FILE f{k::COM1, nullptr, nullptr, nullptr};
+
+ // set up expectations
+ EXPECT_CALL(*mockPort, inb(k::COM1 + k::LineStatus)).Times(1).WillRepeatedly(Return(k::THRE));
+ EXPECT_CALL(*mockPort, outb('a', k::COM1)).Times(1);
+
+ uart_putc(&f, 'a');
+}
+
+TEST_F(Uart16550, uart_putc_newline)
+{
+ k::FILE f{k::COM1, nullptr, nullptr, nullptr};
+
+ // set up expectations
+ EXPECT_CALL(*mockPort, inb(k::COM1 + k::LineStatus)).Times(2).WillRepeatedly(Return(k::THRE));
+ EXPECT_CALL(*mockPort, outb('\n', k::COM1)).Times(1);
+ EXPECT_CALL(*mockPort, outb('\r', k::COM1)).Times(1);
+
+ uart_putc(&f, '\n');
+}
+
+TEST_F(Uart16550, uart_puts)
+{
+ k::FILE f{k::COM1, nullptr, nullptr, nullptr};
+ const char *string{"This is a test string to write over uart"};
+ const int length = (int)strlen(string);
+
+ // set up expectations
+ EXPECT_CALL(*mockPort, inb(k::COM1 + k::LineStatus)).Times(length).WillRepeatedly(Return(k::THRE));
+ EXPECT_CALL(*mockPort, outb(_, k::COM1)).Times(length);
+
+ const auto result = uart_puts(&f, string, length);
+ ASSERT_EQ(result, length);
+}
+
+TEST_F(Uart16550, uart_puts_WithUnknownLength)
+{
+ k::FILE f{k::COM1, nullptr, nullptr, nullptr};
+ const char *string{"This is a test string to write over uart"};
+ const int length = (int)strlen(string);
+
+ // set up expectations
+ EXPECT_CALL(*mockPort, inb(k::COM1 + k::LineStatus)).Times(length).WillRepeatedly(Return(k::THRE));
+ EXPECT_CALL(*mockPort, outb(_, k::COM1)).Times(length);
+
+ const auto result = uart_puts(&f, string, -1);
+ ASSERT_EQ(result, length);
+}
+
+TEST_F(Uart16550, uart_puts_WithPartialLength)
+{
+ k::FILE f{k::COM1, nullptr, nullptr, nullptr};
+ const char *string{"This is a test string to write over uart"};
+ const int length = (int)strlen(string);
+ const int partial = 10;
+
+ ASSERT_LT(partial, length);
+
+ // set up expectations
+ EXPECT_CALL(*mockPort, inb(k::COM1 + k::LineStatus)).Times(partial).WillRepeatedly(Return(k::THRE));
+ EXPECT_CALL(*mockPort, outb(_, k::COM1)).Times(partial);
+
+ const auto result = uart_puts(&f, string, partial);
+ ASSERT_EQ(result, partial);
+}
+
+TEST_F(Uart16550, uart_flush)
+{
+ k::FILE f{k::COM1, nullptr, nullptr, nullptr};
+
+ // set up expectations
+ // no mock calls are expected
+
+ uart_flush(&f);
+}
diff --git a/devices/uart_16550.cpp b/devices/uart_16550.cpp
deleted file mode 100644
index 9620981..0000000
--- a/devices/uart_16550.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-#include "uart.hpp"
-#include <sys/io.hpp>
-
-template <UART port> struct Uart16550 : public kIoDevice, private Port<unsigned short, port> {
- using Base = Port<unsigned short, port>;
- using Ports = UART;
- using PortOffset = UARTPortOffset;
-
- // Line Control
- // | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- // |dla| | parity | s | data |
- enum LineControl : unsigned char {
- d5bit = 0x00, // 0000 0000 data bits
- d6bit = 0x01, // 0000 0001
- d7bit = 0x02, // 0000 0010
- d8bit = 0x03, // 0000 0011
- none = 0x00, // 0000 0000 parity bits
- odd = 0x08, // 0000 1000
- even = 0x18, // 0001 1000
- mark = 0x28, // 0010 1000
- space = 0x38, // 0011 1000
- s1bit = 0x00, // 0000 0000 stop bits
- s2bit = 0x04, // 0000 0100 1.5 for 5bit data; 2 otherwise
- dlab = 0x80 // 1000 0000 divisor latch access bit
- };
-
- // Line Status Register
- enum LineStatus : unsigned char {
- DR = (1 << 0), // data ready: see if there is data to read
- OE = (1 << 1), // overrun error: see if there has been data lost
- PE = (1 << 2), // parity error: see if there was error in transmission
- FE = (1 << 3), // framing error: see if a stop bit was missing
- BI = (1 << 4), // break indicator: see if there is a break in data input
- THRE = (1 << 5), // transmitter holding register empty: see if transmission buffer is empty
- TEMT = (1 << 6), // transmitter empty: see if transmitter is not doing anything
- ERRO = (1 << 7), // impending error: see if there is an error with a word in the input buffer
- };
-
- [[nodiscard]] static bool
- test()
- {
- Base::out(0x00, 1); // Disable all interrupts
- Base::out(0x80, 3); // Enable DLAB (set baud rate divisor)
- Base::out(0x03, 0); // Set divisor to 3 (lo byte) 38400 baud
- Base::out(0x00, 1); // (hi byte)
- Base::out(0x03, 3); // 8 bits, no parity, one stop bit
- Base::out(0xc7, 2); // Enable FIFO, clear them, with 14-byte threshold
- Base::out(0x0b, 4); // IRQs enabled, RTS/DSR set
- Base::out(0x1e, 4); // Set in loopback mode, test the serial chip
- Base::out(0xae, 0); // Test serial chip (send byte 0xAE and check if serial
- // returns same byte)
-
- // Check if serial is faulty (i.e: not same byte as sent)
- if (Base::in() != 0xae) { return false; }
-
- // If serial is not faulty set it in normal operation mode
- // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
- Base::out(0x0f, 4);
- return true;
- }
-
- [[nodiscard]] static bool
- thre()
- {
- return Base::in(PortOffset::LineStatus)&THRE;
- }
-
- void
- putc(char a) override
- {
- while (!thre()) {}
- Base::out(a);
- if (a == '\n') putc('\r');
- }
-
- int
- puts(const char *string, int length) override
- {
- int written = 0;
-
- if (length == -1)
- while (*string != '\0') {
- putc(*string);
- ++string;
- ++written;
- }
-
- else {
- for (int i = 0; i < length; ++i) putc(string[i]);
- written += length;
- }
-
- return written;
- }
-
- void
- flush() override
- {
- }
-};
-
-static_assert(sizeof(Uart16550<COM1>) == sizeof(void *));
-
-template <>
-FILE *
-uart_init<COM1>()
-{
- static Uart16550<COM1> device;
- return &device;
-}
diff --git a/devices/vga.cpp b/devices/vga.c
index 3f83a5f..51f860f 100644
--- a/devices/vga.cpp
+++ b/devices/vga.c
@@ -1,26 +1,31 @@
-#include "vga.hpp"
+#include "vga.h"
#include <stdint.h>
#include <sys/io.h>
-// FIXME user a Port
#define cga_idx_port 0x3d4
#define cga_dat_port 0x3d5
-// FIXME make constexpr
#define cursor_start 0x0a
#define cursor_end 0x0b
#define cursor_addr_h 0x0e
#define cursor_addr_l 0x0f
#define cursor_hide 0x20
-static_assert(sizeof(struct VGA::VGAEntry) == 2, "sizeof VGAEntry");
+struct __attribute__((packed)) VGAEntry {
+ char text;
+ unsigned foreground : 4;
+ unsigned background : 4;
+};
+/* TODO _Static_assert(sizeof(struct VGAEntry) == 2, "sizeof VGAEntry"); */
-// FIXME make constexpr
const int width = 80;
const int height = 25;
-// *** Cursor ***
-// FIXME make VGA members
+struct VGAEntry *buffer;
+int col = 0;
+int row = 0;
+
+/* *** Cursor *** */
void
vga_enable_cursor(unsigned char start, unsigned char end)
{
@@ -39,21 +44,23 @@ vga_disable_cursor()
}
void
-VGA::update_cursor()
+vga_update_cursor(void)
{
- const uint16_t pos = row * width + col;
+ const uint16_t pos = (uint16_t)(row * width + col);
outb(cursor_addr_l, cga_idx_port);
- outb(pos & 0xff, cga_dat_port);
+ outb((unsigned char)pos & 0xff, cga_dat_port);
outb(cursor_addr_h, cga_idx_port);
- outb((pos >> 8) & 0xff, cga_dat_port);
+ outb((unsigned char)(pos >> 8) & 0xff, cga_dat_port);
}
-// *** Text Mode Output ***
+/* *** Text Mode Output *** */
void
-VGA::putc(char a)
+vga_putc(__attribute__((unused)) const FILE *self, char a)
{
+ int i, x, y;
+
switch (a) {
case '\n':
col = 0;
@@ -77,62 +84,75 @@ VGA::putc(char a)
}
if (row == height) {
- // scroll up
- for (int y = 1; y < height; ++y)
- for (int x = 0; x < width; ++x) {
+ /* scroll up */
+ for (y = 1; y < height; ++y)
+ for (x = 0; x < width; ++x) {
const int prev = (y - 1) * width + x;
const int curr = y * width + x;
buffer[prev] = buffer[curr];
}
- // blank out last row
- for (int i = (height - 1) * width; i < height * width; ++i) buffer[i].text = ' ';
+ /* blank out last row */
+ for (i = (height - 1) * width; i < height * width; ++i) buffer[i].text = ' ';
--row;
}
}
int
-VGA::puts(const char *string, int len)
+vga_puts(const FILE *self, const char *string, int len)
{
+ int i;
+
int written = 0;
if (len == -1)
while (*string != '\0') {
- putc(*string);
+ vga_putc(self, *string);
++string;
++written;
}
else
- for (int i = 0; i < len; ++i) {
- putc(string[i]);
+ for (i = 0; i < len; ++i) {
+ vga_putc(self, string[i]);
++written;
}
return written;
}
-// *** Text Mode ***
-VGA::VGA(void *addr)
+void
+vga_flush(__attribute__((unused)) const FILE *self)
{
- buffer = (struct VGAEntry *)addr;
- vga_enable_cursor(14, 15);
- clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY);
+ vga_update_cursor();
}
+
+/* *** Text Mode *** */
+FILE vga_stream;
+
FILE *
-vga_init(void *buffer)
+vga_init(void *addr)
{
- static VGA device(buffer);
- return &device;
+ buffer = (struct VGAEntry *)addr;
+ vga_enable_cursor(14, 15);
+ vga_clear(VGA_COLOR_LIGHT_BLUE, VGA_COLOR_LIGHT_GREY);
+
+ vga_stream.id = 0;
+ vga_stream.putc = &vga_putc;
+ vga_stream.puts = &vga_puts;
+ vga_stream.flush = &vga_flush;
+ return &vga_stream;
}
void
-VGA::clear(enum vga_color foreground, enum vga_color background)
+vga_clear(enum vga_color foreground, enum vga_color background)
{
- for (int y = 0; y < height; ++y)
- for (int x = 0; x < width; ++x) {
+ int x, y;
+
+ for (y = 0; y < height; ++y)
+ for (x = 0; x < width; ++x) {
const int index = y * width + x;
buffer[index].text = ' ';
buffer[index].foreground = foreground;
buffer[index].background = background;
}
col = row = 0;
- update_cursor();
+ vga_update_cursor();
}
diff --git a/devices/vga.hpp b/devices/vga.hpp
deleted file mode 100644
index 5287d73..0000000
--- a/devices/vga.hpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-
-#include <stdio.h>
-
-/** Hardware text mode color constants. */
-enum vga_color {
- VGA_COLOR_BLACK = 0,
- VGA_COLOR_BLUE = 1,
- VGA_COLOR_GREEN = 2,
- VGA_COLOR_CYAN = 3,
- VGA_COLOR_RED = 4,
- VGA_COLOR_MAGENTA = 5,
- VGA_COLOR_BROWN = 6,
- VGA_COLOR_LIGHT_GREY = 7,
- VGA_COLOR_DARK_GREY = 8,
- VGA_COLOR_LIGHT_BLUE = 9,
- VGA_COLOR_LIGHT_GREEN = 10,
- VGA_COLOR_LIGHT_CYAN = 11,
- VGA_COLOR_LIGHT_RED = 12,
- VGA_COLOR_LIGHT_MAGENTA = 13,
- VGA_COLOR_LIGHT_BROWN = 14,
- VGA_COLOR_WHITE = 15,
-};
-
-FILE *vga_init(void *buffer);
-
-struct VGA : public kIoDevice {
- VGA(void *addr);
-
- void putc(char a) override;
- int puts(const char *string, int length) override;
- void
- flush() override
- {
- update_cursor();
- }
-
- struct __attribute__((packed)) VGAEntry {
- unsigned char text;
- unsigned char foreground : 4;
- unsigned char background : 4;
- };
-
-private:
- void clear(enum vga_color foreground, enum vga_color background);
- void update_cursor();
-
- struct VGAEntry *buffer;
- int col = 0;
- int row = 0;
-};
diff --git a/grub/BUILD.bazel b/grub/BUILD.bazel
new file mode 100644
index 0000000..2d12cc1
--- /dev/null
+++ b/grub/BUILD.bazel
@@ -0,0 +1,9 @@
+package(default_visibility = ["//visibility:public"])
+
+exports_files(["grub.cfg"])
+
+cc_library(
+ name = "multiboot2",
+ hdrs = ["include/multiboot2.h"],
+ includes = ["include"],
+)
diff --git a/grub/multiboot2.h b/grub/include/multiboot2.h
index 5a3db5a..5a3db5a 100644
--- a/grub/multiboot2.h
+++ b/grub/include/multiboot2.h
diff --git a/i686-elf-gcc.txt b/i686-elf-gcc.txt
new file mode 100644
index 0000000..b5f3bd0
--- /dev/null
+++ b/i686-elf-gcc.txt
@@ -0,0 +1,9 @@
+[binaries]
+c = 'i686-elf-gcc'
+cpp = 'i686-elf-g++'
+ld = 'i686-elf-ld'
+ar = 'i686-elf-ar'
+strip = 'i686-elf-strip'
+
+[built-in options]
+c_args = ['-ffreestanding', '-mgeneral-regs-only']
diff --git a/i686/Makefile b/i686/Makefile
deleted file mode 100644
index ba780a9..0000000
--- a/i686/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-include ../Makefile.config
-
-INCLUDES := -isystem../grub
-${ARCH}_CFLAGS += ${INCLUDES}
-${ARCH}_CXXFLAGS += ${INCLUDES}
-
-TARGETLIB += arch
-arch.SRCS = boot.S init.s \
- gdt.c lgdt.c \
- lidt.c isr.c
-
-include ../rules.mk
-
diff --git a/i686/gdt.h b/i686/gdt.h
deleted file mode 100644
index f00ff7f..0000000
--- a/i686/gdt.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#pragma once
-
-#include <stdbool.h>
-#include <stdint.h>
-
-enum Ring { Ring0 = 0x0, Ring1 = 0x1, Ring2 = 0x2, Ring3 = 0x3 };
-
-struct __attribute__((packed)) Access {
- bool accessed : 1; // if 0, is set by processor when accessed
- bool readwrite : 1; // code seg: read toggle; data seg: write toggle
- bool direction : 1; // code seg: conforming bit; data seg: direction bit
- bool executable : 1; // executable bit
- bool segment : 1; // true for code/data; false for gates/tss
- enum Ring privilege : 2; // descriptor privilege level
- bool present : 1; // true for every active segment
-};
-_Static_assert(sizeof(struct Access) == 1, "access byte size");
-
-static const struct Access null_access = {false, false, false, false, false, false, false};
-static const struct Access ktext_access = {.readwrite = true, .executable = true, .segment = true, .present = true};
-static const struct Access kdata_access = {.readwrite = true, .segment = true, .present = true};
-
-// Segment Descriptor
-// A memory structure (part of a table) that tells the CPU the attributes of a given segment
-// |31| | | | | | |24|23|22|21|20|19| | |16|15| | | | | | | 8| 7| | | | | | | 0|
-// | base_31_24 | G|DB| | A| lim_19_16 | access | base_23_16 |
-// | base_15_0 | limit_15_0 |
-// |31| | | | | | | | | | | | | | |16|15| | | | | | | | | | | | | | | 0|
-// limit size of segment - 1, either in bytes or in 4KiB chunks (check flags)
-// base address of segment
-// access
-// flags defines the segment chunks and 16/32 bit
-struct __attribute__((packed)) SegmentDescriptor_t {
- uint16_t limit_15_0; // low bits of segment limit
- uint16_t base_15_0; // low bits of segment base address
- uint8_t base_23_16; // middle bits of segment base address
- uint8_t access; // access byte
- uint8_t limit_19_16 : 4; // high bits of segment limit
- // flags
- bool a : 1; // unused, available for software use
- bool rsv : 1; // reserved
- bool db : 1; // false => 16-bit seg; true => 32-bit seg
- bool granularity : 1; // limit scaled by 4k when set
- uint8_t base_31_24; // high bits of segment address
-};
-_Static_assert(sizeof(struct SegmentDescriptor_t) == 8, "segment descriptor size");
-
-void SegmentDescriptor(struct SegmentDescriptor_t *self, unsigned base, unsigned limit, uint8_t access);
-
-void gdt_install();
-
-enum SegmentIndex {
- ktextDescriptor = 2 * sizeof(struct SegmentDescriptor_t),
- kdataDescriptor = 3 * sizeof(struct SegmentDescriptor_t),
-};
diff --git a/i686/lgdt.c b/i686/lgdt.c
deleted file mode 100644
index 10781db..0000000
--- a/i686/lgdt.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "gdt.h"
-
-struct __attribute__((packed)) Pointer {
- uint16_t limit;
- uint32_t base;
-};
-
-static struct SegmentDescriptor_t segments[8] __attribute__((aligned(32)));
-
-void
-gdt_install()
-{
- SegmentDescriptor(&segments[0], 0, 0, 0); // null segment
- SegmentDescriptor(&segments[2], 0, 0xffffffff, 0x9a); // ktext
- SegmentDescriptor(&segments[3], 0, 0xffffffff, 0x92); // kdata
-
- const struct Pointer ptr = {.limit = sizeof(segments) - 1, .base = (unsigned)&segments};
- asm volatile("lgdt (%0)" : : "a"(&ptr));
-
- // load the kernel data segment
- asm volatile(R"(mov %0, %%ds
- mov %0, %%es
- mov %0, %%fs
- mov %0, %%gs
- mov %0, %%ss
-)"
- :
- : "ax"(kdataDescriptor));
-
- // load the kernel code segment
- asm volatile(R"(ljmp %0, $1f
- 1:)"
- :
- : "i"(ktextDescriptor));
-}
diff --git a/i686/lidt.c b/i686/lidt.c
deleted file mode 100644
index cf8084e..0000000
--- a/i686/lidt.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "idt.h"
-#include <stdint.h>
-
-struct __attribute__((packed)) Pointer {
- uint16_t limit;
- uint32_t base;
-};
-
-enum Type {
- Null = 0,
- Intr = 0x8e, // 1000 1110 32-bit interrupt
-};
-
-struct __attribute__((packed)) Gate_t {
- uint16_t offset_15_0; // segment offset low
- uint16_t selector; // code segment selector
- uint8_t __unused; // unused in protected mode
- uint8_t type; // interrupt type
- uint16_t offset_31_16; // segment offset high
-};
-_Static_assert(sizeof(struct Gate_t) == 8, "interrupt gate size");
-
-void
-Gate(struct Gate_t *entry, void (*f)(struct interrupt_frame *), uint16_t selector)
-{
- uint32_t f_addr = (uint32_t)f;
- entry->offset_15_0 = f_addr & 0xffff;
- entry->offset_31_16 = (f_addr >> 16) & 0xffff;
- entry->selector = selector;
- entry->__unused = 0;
- entry->type = Intr;
-}
-
-static struct Gate_t interrupt_table[256] __attribute((aligned(4096)));
-
-void
-idt_install()
-{
- // exceptions 0x00~0x13
- for (int i = 0; i <= 0x13; ++i) Gate(&interrupt_table[i], &abort_handler, 0x10);
-
- // irq 0x20~0x2f
- for (int i = 0x22; i <= 0x2f; ++i) Gate(&interrupt_table[i], &abort_handler, 0x10);
- Gate(&interrupt_table[0x20], &irq0x00, 0x10);
- Gate(&interrupt_table[0x21], &irq0x01, 0x10);
- Gate(&interrupt_table[0x2c], &irq0x0c, 0x10);
-
- // syscall 0x80
- Gate(&interrupt_table[0x80], &syscall_handler, 0x10);
-
- const struct Pointer ptr = {.limit = sizeof(interrupt_table) - 1, .base = (unsigned)&interrupt_table};
- asm volatile("lidt (%0)" : : "a"(&ptr));
-}
diff --git a/i686/macros.s b/i686/macros.s
deleted file mode 100644
index a9b8b4d..0000000
--- a/i686/macros.s
+++ /dev/null
@@ -1,25 +0,0 @@
-.set PAGE_RO, 0x001
-.set PAGE_RW, 0x003
-/* write section to page table macro
- *
- * Registers used:
- * %ecx: loop counter [ set to $1024 ]
- * %edx: temporary
- * %esi: current page being mapped
- * %edi: page entry [ set to $page_addr ]
- */
-.macro mmap_section begin, end, access
- mov $\begin, %esi # from $begin
-1: cmpl $\end, %esi # until $end
- jge 2f
-
- movl %esi, %edx
- orl $\access, %edx
- movl %edx, (%edi)
-
- addl $4096, %esi # move to next page
- addl $4, %edi # size of page entry is 4 bytes
- loop 1b # loop according to %ecx
-2:
-.endm
-
diff --git a/i686/paging.h b/i686/paging.h
deleted file mode 100644
index f9c04a8..0000000
--- a/i686/paging.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#pragma once
-
-// DirectoryEntry
-// |31| | | | | | | | | | | | | | | | | | | |11| | 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
-// | page table 4-kb aligned address | avail | G| S| | A| C| W| U| R| P|
-struct __attribute__((packed)) DirectoryEntry {
- unsigned present : 1; // 0: if set, the page is actually in physical memory
- unsigned writeable : 1; // 1: if set, the page is read/write; otherwise the page is read-only
- unsigned user : 1; // 2: if set, then page can be access by all; otherwise only the supervisor can access it
- unsigned writethrough : 1; // 3: if set, write-through caching is enabled; otherwise write-back is enabled instead
- unsigned cachedisable : 1; // 4: if set, the page will not be cached
- unsigned accessed : 1; // 5: set by the CPU when the page is read from or written to
- unsigned dirty : 1; // 6: used to determine whether a page has been written to
- unsigned pagesize : 1; // 7: page size == 0
- unsigned global : 1;
- unsigned int __available__ : 3; // available to the OS
- unsigned int address : 20;
-};
-_Static_assert(sizeof(struct DirectoryEntry) == 4, "DirectoryEntry size");
-
-// DirectoryEntry4MB
-// |31| | | | | | | | |22|21|20| | | | | | |13|12|11| | 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
-// | bits 31-22 of address |RS| bits 39-22 of |AT| avail | G|PS| D| A|CD|WT|US|RW| P|
-// | |VD| address
-struct __attribute__((packed)) DirectoryEntry4MB {
- unsigned present : 1; // 0: if set, the page is actually in physical memory
- unsigned writeable : 1; // 1: if set, the page is read/write; otherwise the page is read-only
- unsigned useraccess : 1; // 2: if set, then page can be access by all; otherwise only the supervisor can access it
- unsigned writethrough : 1; // 3: if set, write-through caching is enabled; otherwise write-back is enabled instead
- unsigned cachedisable : 1; // 4: if set, the page will not be cached
- unsigned accessed : 1; // 5: set by the CPU when the page is read from or written to
- unsigned dirty : 1; // 6: used to determine whether a page has been written to
- unsigned pagesize : 1; // 7: page size == 1
- unsigned global : 1; // 8:
- unsigned __available__ : 3; // 11..9 available to the OS
- unsigned pat : 1; // 12: page attribute table
- unsigned int address_high : 8;
- unsigned rsvd : 1; // 21
- unsigned int address_low : 10;
-};
-_Static_assert(sizeof(struct DirectoryEntry4MB) == 4, "DirectoryEntry4M size");
-
-// TableEntry
-// |31| | | | | | | | | | | | | | | | | | | |11| | 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
-// | page table 4-kb aligned address | avail | G| | D| A| C| W|US|RW| P|
-struct __attribute__((packed)) TableEntry {
- unsigned present : 1; // if set, the page is actually in physical memory
- unsigned writeable : 1; // if set, the page is read/write; otherwise the page is read-only
- unsigned user : 1; // if set, then page can be access by all; otherwise only the supervisor can access it
- unsigned writethrough : 1; // if set, write-through caching is enabled; otherwise write-back is enabled instead
- unsigned cachedisable : 1; // if set, the page will not be cached
- unsigned accessed : 1; // set by the CPU when the page is read from or written to
- unsigned dirty : 1; // used to determine whether a page has been written to
- unsigned pat : 1; // page attribute table?
- unsigned global : 1;
- unsigned int __available__ : 3; // available to the OS
- unsigned int address : 20;
-};
-_Static_assert(sizeof(struct TableEntry) == 4, "TableEntry size");
diff --git a/i686/sys/control.h b/i686/sys/control.h
deleted file mode 100644
index 7dde3c8..0000000
--- a/i686/sys/control.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-static inline void
-abort()
-{
- /* Symbol h is already defined?
-asm volatile(R"(cli
-h: hlt
-jmp h)");
-*/
- asm volatile(R"(cli
-hlt)");
-}
-
-static inline void
-enable_interrupts()
-{
- asm volatile("sti");
-}
-
-static inline void
-disable_interrupts()
-{
- asm volatile("cli");
-}
diff --git a/i686/sys/io.h b/i686/sys/io.h
deleted file mode 100644
index b6c24c5..0000000
--- a/i686/sys/io.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#pragma once
-
-// port listings
-enum UART {
- COM1 = 0x3f8,
- COM2 = 0x2f8,
- COM3 = 0x3e8,
- COM4 = 0x2e8,
- COM5 = 0x5f8,
- COM6 = 0x4f8,
- COM7 = 0x5e8,
- COM8 = 0x4e8,
-};
-enum UARTPortOffset {
- Data = 0, // read from receive buffer / write to transmit buffer | BaudDiv_l
- InterruptControl = 1, // interrupt enable | BaudDiv_h
- FifoControl = 2, // interrupt ID and FIFO control
- LineControl = 3, // most significant bit is the DLAB
- ModemControl = 4,
- LineStatus = 5,
- ModemStatus = 6,
- Scratch = 7,
-};
-
-static inline void
-outb(unsigned char val, unsigned short port)
-{
- asm volatile("outb %0,%1" : : "a"(val), "dN"(port));
-}
-
-static inline void
-outw(unsigned short val, unsigned short port)
-{
- asm volatile("outw %0,%1" : : "a"(val), "dN"(port));
-}
-
-static inline void
-outl(unsigned int val, unsigned short port)
-{
- asm volatile("outl %0,%1" : : "a"(val), "dN"(port));
-}
-
-static inline unsigned char
-inb(unsigned short port)
-{
- unsigned char val;
- asm volatile("inb %1,%0" : "=a"(val) : "dN"(port));
- return val;
-}
-
-static inline unsigned short
-inw(unsigned short port)
-{
- unsigned short val;
- asm volatile("inw %1,%0" : "=a"(val) : "dN"(port));
- return val;
-}
-
-static inline unsigned int
-inl(unsigned short port)
-{
- unsigned int val;
- asm volatile("inl %1,%0" : "=a"(val) : "dN"(port));
- return val;
-}
-
-static inline void
-outsb(unsigned short port, const void *__buf, unsigned long __n)
-{
- asm volatile("cld; rep; outsb" : "+S"(__buf), "+c"(__n) : "d"(port));
-}
-
-static inline void
-outsw(unsigned short port, const void *__buf, unsigned long __n)
-{
- asm volatile("cld; rep; outsw" : "+S"(__buf), "+c"(__n) : "d"(port));
-}
-
-static inline void
-outsl(unsigned short port, const void *__buf, unsigned long __n)
-{
- asm volatile("cld; rep; outsl" : "+S"(__buf), "+c"(__n) : "d"(port));
-}
-
-static inline void
-insb(unsigned short port, void *__buf, unsigned long __n)
-{
- asm volatile("cld; rep; insb" : "+D"(__buf), "+c"(__n) : "d"(port));
-}
-
-static inline void
-insw(unsigned short port, void *__buf, unsigned long __n)
-{
- asm volatile("cld; rep; insw" : "+D"(__buf), "+c"(__n) : "d"(port));
-}
-
-static inline void
-insl(unsigned short port, void *__buf, unsigned long __n)
-{
- asm volatile("cld; rep; insl" : "+D"(__buf), "+c"(__n) : "d"(port));
-}
-
diff --git a/i686/sys/io.hpp b/i686/sys/io.hpp
deleted file mode 100644
index 9759a3a..0000000
--- a/i686/sys/io.hpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-/**
- * Ports provide communication with devices on the x86 IO bus.
- */
-template <typename T, unsigned short port> struct Port {
- /**
- * Read value from port
- */
- static T
- in(unsigned short offset = 0)
- {
- if constexpr (sizeof(T) == sizeof(unsigned char)) return inb(port + offset);
- else if constexpr (sizeof(T) == sizeof(unsigned short))
- return inw(port + offset);
- else if constexpr (sizeof(T) == sizeof(unsigned int))
- return inl(port + offset);
- }
-
- /**
- * Write value to port
- */
- static void
- out(T val, unsigned short offset = 0)
- {
- if constexpr (sizeof(T) == sizeof(unsigned char)) outb(val, port + offset);
- else if constexpr (sizeof(T) == sizeof(unsigned short))
- outw(val, port + offset);
- else if constexpr (sizeof(T) == sizeof(unsigned int))
- outl(val, port + offset);
- }
-
-};
diff --git a/i686/test/gdt.c b/i686/test/gdt.c
deleted file mode 100644
index 2947b42..0000000
--- a/i686/test/gdt.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include "gdt.h"
-#include <assert.h>
-#include <stdlib.h>
-
-int
-main()
-{
- assert(*(uint8_t *)&null_access == 0x00);
- assert(*(uint8_t *)&ktext_access == 0x9a);
- assert(*(uint8_t *)&kdata_access == 0x92);
-
- struct SegmentDescriptor_t d;
- SegmentDescriptor(&d, 0, 0, 0);
- assert(*(uint64_t *)&d == 0);
-
- assert(ktextDescriptor == 0x10);
- assert(kdataDescriptor == 0x18);
-
- return EXIT_SUCCESS;
-}
diff --git a/i686/toolchain.mk b/i686/toolchain.mk
deleted file mode 100644
index 791966b..0000000
--- a/i686/toolchain.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-ARCH=i686
-
-# define compiler, linker, archiver and strip and their flags
-# FIXME: cpp threadsafe statics
-${ARCH}_AS := i686-elf-as
-
-${ARCH}_CC := i686-elf-gcc
-${ARCH}_CCID := $(shell ${${ARCH}_CC} --version | head -n1)
-${ARCH}_CFLAGS := -Wall -Wextra -Wpedantic -Werror=shadow -Wconversion -fanalyzer -ffreestanding -std=gnu11 \
- -mgeneral-regs-only \
- $(shell echo ${CONFIG_CFLAGS})
-
-${ARCH}_CXX := i686-elf-g++
-${ARCH}_CXXID := $(shell ${${ARCH}_CXX} --version | head -n1)
-${ARCH}_CXXFLAGS := -Wall -Wextra -Wpedantic -Werror=shadow -Wconversion -ffreestanding -std=c++17 \
- -mgeneral-regs-only -fno-use-cxa-atexit -fno-threadsafe-statics -fno-exceptions -fno-rtti \
- $(shell echo ${CONFIG_CXXFLAGS})
-
-${ARCH}_LD := i686-elf-ld
-${ARCH}_LDID := $(shell ${${ARCH}_LD} --version | head -n1)
-${ARCH}_LDFLAGS := -static -nostdlib \
- $(shell echo ${CONFIG_LDFLAGS})
-
-${ARCH}_AR := i686-elf-ar
-${ARCH}_ARFLAGS := -crus
-
-${ARCH}_STRIP := i686-elf-strip
-
-# define compiler and flags for test targets
-HOST_CC := gcc
-HOST_CFLAGS := -Wall -Wextra -Wpedantic -Werror=shadow -Wconversion \
- ${CFLAGS}
-HOST_CXX := g++
-HOST_CXXFLAGS := -Wall -Wextra -Wpedantic -Werror=shadow -Wconversion -g -Og \
- $(shell pkg-config --cflags --libs gtest gtest_main gmock) \
- ${CXXFLAGS}
-
-# emulator name and flags
-QEMU := qemu-system-i386 -accel kvm -machine pc
-
diff --git a/kernel/BUILD.bazel b/kernel/BUILD.bazel
new file mode 100644
index 0000000..e7ed087
--- /dev/null
+++ b/kernel/BUILD.bazel
@@ -0,0 +1,37 @@
+load("//tools:configure_file.bzl", "configure_file")
+
+configure_file(
+ name = "conf",
+ template = "conf.h.in",
+)
+
+cc_binary(
+ name = "glitch.elf",
+ srcs = [
+ "boot.h",
+ "kernel.c",
+ "mem.h",
+ "mem/vmm.c",
+ "mmap.c",
+ "mmap.h",
+ "multiboot2.c",
+ "task.h",
+ ":conf.h",
+ ],
+ includes = ["."],
+ linkopts = [
+ "-T",
+ "$(location //arch/i386:linker.ld)",
+ ],
+ target_compatible_with = [
+ "@platforms//os:none",
+ ],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//arch/i386:arch",
+ "//arch/i386:linker.ld",
+ "//devices:drivers",
+ "//grub:multiboot2",
+ "//lib/libk:k",
+ ],
+)
diff --git a/kernel/boot.h b/kernel/boot.h
new file mode 100644
index 0000000..646fb4c
--- /dev/null
+++ b/kernel/boot.h
@@ -0,0 +1,21 @@
+/* *** glitch kernel ***
+ * spdx-license-identifier: ISC
+ * description: kernel boot information
+ * */
+
+#pragma once
+
+typedef struct {
+ /* kernel command line */
+ char cmdline[64];
+
+ /* memory map */
+ unsigned bitmap[1024 * 32];
+
+ /* module */
+ unsigned module_start;
+ unsigned module_end;
+ char module_cmdline[64];
+} boot_info_t;
+
+/* TODO _Static_assert((1024 * 32 * sizeof(unsigned) * 8) == (1024 * 1024), "bitmap size check"); */
diff --git a/kernel/conf.h.in b/kernel/conf.h.in
new file mode 100644
index 0000000..61352d7
--- /dev/null
+++ b/kernel/conf.h.in
@@ -0,0 +1,4 @@
+#pragma once
+
+#define VERSION {VERSION}
+#define CC {CC}
diff --git a/src/kernel.cpp b/kernel/kernel.c
index 063fe11..98269c1 100644
--- a/src/kernel.cpp
+++ b/kernel/kernel.c
@@ -1,10 +1,8 @@
-//=====================================================================
-// glitch kernel
-// spdx-license-identifier: ISC
-// description: kernel entry point
-//=====================================================================
+/* *** glitch kernel ***
+ * spdx-license-identifier: ISC
+ * description: kernel entry point
+ * */
-extern "C" {
#include "conf.h"
#include "mem.h"
#include <keyboard.h>
@@ -13,31 +11,31 @@ extern "C" {
#include <ps2_controller.h>
#include <stdio.h>
#include <sys/cpuid.h>
-}
-#include <uart.hpp>
-#include <vga.hpp>
+#include <uart.h>
+#include <vga.h>
FILE *stdin;
FILE *stdout;
FILE *stderr;
-extern "C" void
-kmain()
+void
+kmain(void)
{
- stderr = uart_init<COM1>();
+ stderr = uart_init(COM1);
vmm_map(0xb8000, 0xc03ff000);
stdout = vga_init((void *)0xc03ff000);
printf("glitch [version " VERSION "] [" CC "]\n");
fprintf(stderr, "glitch [version " VERSION "] [" CC "]\n");
{
+ struct CPUVersion v;
+
char vendor[13] = {'\0'};
unsigned int eax;
__get_cpuid(0, &eax, (unsigned int *)vendor, (unsigned int *)(vendor + 8), (unsigned int *)(vendor + 4));
- struct CPUVersion v;
__get_cpuid(1, (unsigned int *)&v, &eax, &eax, &eax);
- printf("CPU: %s family %u model %u stepping %u\n", vendor, family(v), model(v), v.stepping);
- fprintf(stderr, "CPU: %s family %u model %u stepping %u\n", vendor, family(v), model(v), v.stepping);
+ printf("cpuid: %s family %u model %u stepping %u\n", vendor, family(v), model(v), v.stepping);
+ fprintf(stderr, "cpuid: %s family %u model %u stepping %u\n", vendor, family(v), model(v), v.stepping);
}
pic_init();
diff --git a/src/mem.h b/kernel/mem.h
index e06dd21..e06dd21 100644
--- a/src/mem.h
+++ b/kernel/mem.h
diff --git a/src/mem/vmm.c b/kernel/mem/vmm.c
index 77b06a8..a07dd72 100644
--- a/src/mem/vmm.c
+++ b/kernel/mem/vmm.c
@@ -16,15 +16,15 @@ to_vaddr(unsigned paddr)
unsigned int
vmm_map(unsigned int paddr, unsigned int vaddr)
{
- if (paddr & 0xfff || vaddr & 0xfff) return 0;
+ struct TableEntry *table;
+ const unsigned table_idx = vaddr >> 22; /* high 10 bits */
+ const unsigned entry_idx = (vaddr >> 12) & 0x3ff; /* low 10 bits */
- const unsigned table_idx = vaddr >> 22; // high 10 bits
- const unsigned entry_idx = (vaddr >> 12) & 0x3ff; // low 10 bits
+ if (paddr & 0xfff || vaddr & 0xfff) return 0;
if (k_pagedir[table_idx].present == 0) return 0;
- struct TableEntry *table = (struct TableEntry *)to_vaddr(k_pagedir[table_idx].address << 12);
-
- table[entry_idx].address = paddr >> 12;
+ table = (struct TableEntry *)to_vaddr(k_pagedir[table_idx].address << 12);
+ table[entry_idx].address = (paddr >> 12) & 0xfffff;
table[entry_idx].present = 1;
table[entry_idx].writeable = 1;
@@ -34,14 +34,12 @@ vmm_map(unsigned int paddr, unsigned int vaddr)
void
alloc4M()
{
- // enable pse in cr4
- asm volatile(R"(
- movl %cr4, %eax
- orl $0x10, %eax
- movl %eax, %cr4
-)");
-
- struct DirectoryEntry4MB *directory = (struct DirectoryEntry4MB *)&k_pagedir[0x301];
+ struct DirectoryEntry4MB *directory;
+
+ /* enable pse in cr4 */
+ __asm__("movl %cr4, %eax; orl $0x10, %eax; movl %eax, %cr4");
+
+ directory = (struct DirectoryEntry4MB *)&k_pagedir[0x301];
directory->address_low = 0x1;
directory->present = 1;
directory->writeable = 1;
diff --git a/src/mmap.c b/kernel/mmap.c
index 3fe35b5..e5d4be6 100644
--- a/src/mmap.c
+++ b/kernel/mmap.c
@@ -1,4 +1,6 @@
#include "mmap.h"
+#include <multiboot2.h>
+
#ifdef DEBUG
#include <stdio.h>
#endif
@@ -6,16 +8,20 @@
__attribute__((section(".multiboot.text"))) unsigned
multiboot2_mmap(const struct multiboot_mmap_entry entries[], unsigned entry_count, unsigned bitmap[1024 * 32])
{
- // clear out the bitmap
- for (unsigned i = 0; i < 1024 * 32; ++i) bitmap[i] = 0;
- unsigned avail_frames = 0;
+ unsigned i, l;
+ multiboot_uint64_t avail_frames = 0;
+ multiboot_uint64_t n_frames;
+ multiboot_uint64_t table_idx;
+
+ /* clear out the bitmap */
+ for (i = 0; i < 1024 * 32; ++i) bitmap[i] = 0;
- // loop through all the mmap_entry structures where type is MULTIBOOT_MEMORY_AVAILABLE
- for (unsigned i = 0; i < entry_count; ++i) {
+ /* loop through all the mmap_entry structures where type is MULTIBOOT_MEMORY_AVAILABLE */
+ for (i = 0; i < entry_count; ++i) {
if (entries[i].type != MULTIBOOT_MEMORY_AVAILABLE) continue;
- // number of frames in this entry
- unsigned n_frames = entries[i].len / 4096;
+ /* number of frames in this entry */
+ n_frames = entries[i].len / 4096;
avail_frames += n_frames;
#ifdef DEBUG
@@ -23,8 +29,8 @@ multiboot2_mmap(const struct multiboot_mmap_entry entries[], unsigned entry_coun
n_frames / 32, n_frames % 32);
#endif
- // the bitmap is an array of blocks, each holding 32 (2^5) values
- unsigned table_idx = (entries[i].addr >> 17); // get the upper 15 bits
+ /* the bitmap is an array of blocks, each holding 32 (2^5) values */
+ table_idx = (entries[i].addr >> 17); /* get the upper 15 bits */
while (n_frames != 0) {
if (n_frames >= 32) {
@@ -34,7 +40,7 @@ multiboot2_mmap(const struct multiboot_mmap_entry entries[], unsigned entry_coun
}
else {
unsigned block = bitmap[table_idx];
- for (unsigned l = 0; l < n_frames; ++l) block |= (1 << l);
+ for (l = 0; l < n_frames; ++l) block |= (1 << l);
bitmap[table_idx] = block;
n_frames = 0;
}
diff --git a/src/mmap.h b/kernel/mmap.h
index 13f40f2..13f40f2 100644
--- a/src/mmap.h
+++ b/kernel/mmap.h
diff --git a/src/multiboot2.c b/kernel/multiboot2.c
index ea06e96..bd6250f 100644
--- a/src/multiboot2.c
+++ b/kernel/multiboot2.c
@@ -7,7 +7,8 @@ boot_info_t info __attribute__((section(".init")));
__attribute__((section(".multiboot.text"))) void
multiboot_strncpy(char *dest, const char *src, unsigned n)
{
- for (unsigned i = 0; i < n && src[i] != '\0'; ++i) dest[i] = src[i];
+ unsigned i;
+ for (i = 0; i < n && src[i] != '\0'; ++i) dest[i] = src[i];
}
__attribute__((section(".multiboot.text"))) void
@@ -44,6 +45,6 @@ __multiboot2(multiboot_uint32_t addr)
break;
default:
break;
- } // switch
- } // for
+ }
+ }
}
diff --git a/src/sched.hpp b/kernel/sched.hpp
index cfa3ff0..cfa3ff0 100644
--- a/src/sched.hpp
+++ b/kernel/sched.hpp
diff --git a/src/sched/roundrobin.cpp b/kernel/sched/roundrobin.cpp
index c3d6cb6..c3d6cb6 100644
--- a/src/sched/roundrobin.cpp
+++ b/kernel/sched/roundrobin.cpp
diff --git a/src/tst/roundrobin.cc b/kernel/sched/test_roundrobin.cc
index 1431788..89f60bf 100644
--- a/src/tst/roundrobin.cc
+++ b/kernel/sched/test_roundrobin.cc
@@ -43,7 +43,7 @@ TEST(roundrobin, RoundRobinQueue)
std::cout << "Completed in (us): " << duration << std::endl;
// test should complete in 250us unless running on valgrind
- if (!RUNNING_ON_VALGRIND) EXPECT_LE(duration, 250);
+ if (!RUNNING_ON_VALGRIND) { EXPECT_LE(duration, 250); }
EXPECT_EQ(queue.head, nullptr);
EXPECT_EQ(queue.tail, nullptr);
diff --git a/src/tst/taskqueue.cc b/kernel/sched/test_taskqueue.cc
index 217c44d..217c44d 100644
--- a/src/tst/taskqueue.cc
+++ b/kernel/sched/test_taskqueue.cc
diff --git a/src/task.h b/kernel/task.h
index 0d59bb1..0d59bb1 100644
--- a/src/task.h
+++ b/kernel/task.h
diff --git a/lib/Makefile b/lib/Makefile
deleted file mode 100644
index f5eeded..0000000
--- a/lib/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-include ../Makefile.config
-
-TARGETLIB += libk
-libk.SRCS = \
- libk/endian/little.c \
- libk/stdio/printf.c libk/stdio/fprintf.c libk/stdio/vfprintf.cpp \
- libk/stdlib/memcpy.c libk/stdlib/memset.c libk/stdlib/linked_list_allocator.c \
- libk/string/itoa.c
-
-TESTS += tst/endian_little tst/mem tst/string tst/linked_list_allocator
-
-TARGETLIB += blake2
-blake2.SRCS = blake2/blake2s.c
-TESTS += tst/blake2s_selftest
-
-include ../rules.mk
-
diff --git a/lib/blake2/BUILD.bazel b/lib/blake2/BUILD.bazel
new file mode 100644
index 0000000..4723ae6
--- /dev/null
+++ b/lib/blake2/BUILD.bazel
@@ -0,0 +1,28 @@
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+ name = "blake2s",
+ srcs = ["blake2s.c"],
+ hdrs = ["include/blake2s.h"],
+ includes = ["include"],
+ deps = select({
+ "@platforms//os:none": ["//lib/libk:k"],
+ "//conditions:default": [],
+ }),
+)
+
+cc_test(
+ name = "test_blake2s",
+ srcs = [
+ "blake2s_kat.h",
+ "blake2s_selftest.cc",
+ ],
+ target_compatible_with = select({
+ "@platforms//os:none": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ }),
+ deps = [
+ "//lib/blake2:blake2s",
+ "@googletest//:gtest_main",
+ ],
+)
diff --git a/lib/blake2/blake2s.c b/lib/blake2/blake2s.c
index b924a1e..9206c89 100644
--- a/lib/blake2/blake2s.c
+++ b/lib/blake2/blake2s.c
@@ -34,14 +34,16 @@ G(uint32_t v[16], unsigned a, unsigned b, unsigned c, unsigned d, uint32_t x, ui
void
F(struct BLAKE2s_ctx *ctx, uint32_t m[16], uint32_t f)
{
- // Initialize local work vector v
+ unsigned i;
+
+ /* Initialize local work vector v */
uint32_t v[16] = {ctx->h[0], ctx->h[1], ctx->h[2], ctx->h[3], ctx->h[4], ctx->h[5],
ctx->h[6], ctx->h[7], IV[0], IV[1], IV[2], IV[3],
IV[4] ^ ctx->t[0], IV[5] ^ ctx->t[1], IV[6], IV[7]};
- if (f) v[14] = ~v[14]; // if last block flag, invert all bits
+ if (f) v[14] = ~v[14]; /* if last block flag, invert all bits */
- // cryptographic mixing
- for (unsigned i = 0; i < 10; ++i) {
+ /* cryptographic mixing */
+ for (i = 0; i < 10; ++i) {
G(v, 0, 4, 8, 12, m[SIGMA[i][0]], m[SIGMA[i][1]]);
G(v, 1, 5, 9, 13, m[SIGMA[i][2]], m[SIGMA[i][3]]);
G(v, 2, 6, 10, 14, m[SIGMA[i][4]], m[SIGMA[i][5]]);
@@ -53,8 +55,8 @@ F(struct BLAKE2s_ctx *ctx, uint32_t m[16], uint32_t f)
G(v, 3, 4, 9, 14, m[SIGMA[i][14]], m[SIGMA[i][15]]);
}
- // xor the two halves
- for (unsigned i = 0; i < 8; ++i) ctx->h[i] ^= (v[i] ^ v[i + 8]);
+ /* xor the two halves */
+ for (i = 0; i < 8; ++i) ctx->h[i] ^= (v[i] ^ v[i + 8]);
}
int
@@ -70,14 +72,14 @@ BLAKE2s_init(struct BLAKE2s_ctx *ctx, uint8_t outlen, const void *key, uint8_t k
ctx->param.fanout = 1;
ctx->param.depth = 1;
- // copy IV into state vector h
+ /* copy IV into state vector h */
memcpy(ctx->h, IV, 32);
- // copy param block 0 onto h[0]
+ /* copy param block 0 onto h[0] */
ctx->h[0] ^= (ctx->param.depth << 24) ^ (ctx->param.fanout << 16) ^ (keylen << 8) ^ outlen;
if (keylen > 0) {
BLAKE2s_update(ctx, key, keylen);
- ctx->c = 64; // at the end
+ ctx->c = 64; /* at the end */
}
return 0;
@@ -88,15 +90,16 @@ BLAKE2s_init(struct BLAKE2s_ctx *ctx, uint8_t outlen, const void *key, uint8_t k
void
BLAKE2s_update(struct BLAKE2s_ctx *ctx, const void *d, size_t dd)
{
- for (unsigned i = 0; i < dd;) {
+ unsigned i, j;
+ for (i = 0; i < dd;) {
- if (ctx->c == 64) { // if block is full, consume block
+ if (ctx->c == 64) { /* if block is full, consume block */
ctx->t[0] += ctx->c;
if (ctx->t[0] < ctx->c) ctx->t[1] += 1;
- ctx->c = 0; // reset counter
+ ctx->c = 0; /* reset counter */
uint32_t *m = (uint32_t *)ctx->b;
- for (unsigned j = 0; j < 16; ++j) m[j] = htole32(m[j]);
+ for (j = 0; j < 16; ++j) m[j] = htole32(m[j]);
F(ctx, m, 0);
}
@@ -110,14 +113,16 @@ BLAKE2s_update(struct BLAKE2s_ctx *ctx, const void *d, size_t dd)
void
BLAKE2s_final(struct BLAKE2s_ctx *ctx, void *out)
{
+ unsigned i;
+
ctx->t[0] += ctx->c;
if (ctx->t[0] < ctx->c) ctx->t[1] += 1;
- for (; ctx->c < 64; ++(ctx->c)) ctx->b[ctx->c] = 0; // fill up block with zeroes
+ for (; ctx->c < 64; ++(ctx->c)) ctx->b[ctx->c] = 0; /* fill up block with zeroes */
uint32_t *m = (uint32_t *)ctx->b;
- for (unsigned i = 0; i < 16; ++i) m[i] = htole32(m[i]);
+ for (i = 0; i < 16; ++i) m[i] = htole32(m[i]);
F(ctx, m, 1);
- for (unsigned i = 0; i < ctx->param.outlen; ++i) ((uint8_t *)out)[i] = (ctx->h[i >> 2] >> (8 * (i & 3))) & 0xff;
+ for (i = 0; i < ctx->param.outlen; ++i) ((uint8_t *)out)[i] = (ctx->h[i >> 2] >> (8 * (i & 3))) & 0xff;
}
diff --git a/lib/tst/blake2s_genkat.py b/lib/blake2/blake2s_genkat.py
index 2dd5370..2dd5370 100755
--- a/lib/tst/blake2s_genkat.py
+++ b/lib/blake2/blake2s_genkat.py
diff --git a/lib/tst/blake2s_kat.h b/lib/blake2/blake2s_kat.h
index aa42ef5..dec250a 100644
--- a/lib/tst/blake2s_kat.h
+++ b/lib/blake2/blake2s_kat.h
@@ -1,5 +1,7 @@
#pragma once
+#include <cstdint>
+
static const unsigned KATs_len = 256;
static const uint8_t KAT_secret[32] = { 0xba, 0x80, 0xfb, 0x8f, 0x1b, 0x7b, 0xa1, 0x49, 0x3c, 0x6a, 0xe8, 0x8f, 0xd, 0x66, 0xa1, 0xae, 0xff, 0xa2, 0x5c, 0x8a, 0x7d, 0x4c, 0x1f, 0xb6, 0x81, 0x1, 0xb5, 0xe4, 0xc2, 0x8e, 0x37, 0x3 };
static const uint8_t KATs[256][32] = {
diff --git a/lib/tst/blake2s_selftest.cc b/lib/blake2/blake2s_selftest.cc
index 58199f6..420544d 100644
--- a/lib/tst/blake2s_selftest.cc
+++ b/lib/blake2/blake2s_selftest.cc
@@ -1,8 +1,10 @@
// Self test Modules for BLAKE2s
+#include "blake2s_kat.h"
#include <gtest/gtest.h>
-#include "../blake2/blake2s.c"
-#include "blake2s_kat.h"
+extern "C" {
+#include "blake2s.h"
+}
static_assert(sizeof(BLAKE2s_param) == (8 * sizeof(uint32_t)), "sizeof struct BLAKE2s_param");
@@ -67,12 +69,6 @@ blake2s_selftest()
return 0;
}
-TEST(blake2s, rotr_u32)
-{
- EXPECT_EQ(rotr_u32(0xdecafade, 16), 0xfadedeca);
- EXPECT_EQ(rotr_u32(0xdecafade, 8), 0xdedecafa);
-}
-
TEST(blake2s, selftest) { EXPECT_EQ(blake2s_selftest(), 0); }
TEST(blake2s, selftestAllInOne)
diff --git a/lib/blake2/blake2s.h b/lib/blake2/include/blake2s.h
index 64b4156..ede170c 100644
--- a/lib/blake2/blake2s.h
+++ b/lib/blake2/include/blake2s.h
@@ -4,8 +4,8 @@
#include <stdint.h>
struct BLAKE2s_param {
- uint8_t outlen; // digest length
- uint8_t keylen; // key length
+ uint8_t outlen; /* digest length */
+ uint8_t keylen; /* key length */
uint8_t fanout;
uint8_t depth;
uint32_t leaf_length;
@@ -18,11 +18,11 @@ struct BLAKE2s_param {
};
struct BLAKE2s_ctx {
- uint8_t b[64]; // input buffer
- size_t c; // pointer for b[]
- uint32_t h[8]; // chained state vector h
- uint32_t t[2]; // total number of bytes
- struct BLAKE2s_param param; // parameter block
+ uint8_t b[64]; /* input buffer */
+ size_t c; /* pointer for b[] */
+ uint32_t h[8]; /* chained state vector h */
+ uint32_t t[2]; /* total number of bytes */
+ struct BLAKE2s_param param; /* parameter block */
};
/**
@@ -41,11 +41,11 @@ int BLAKE2s_init(struct BLAKE2s_ctx *ctx, uint8_t outlen, const void *key, uint8
void BLAKE2s_update(struct BLAKE2s_ctx *ctx, const void *d, size_t dd);
void BLAKE2s_final(struct BLAKE2s_ctx *ctx, void *out);
-// All-in-one convenience function.
-static inline int
-BLAKE2s(void *out, uint8_t outlen, // return buffer for digest
- const void *key, uint8_t keylen, // optional secret key
- const void *in, size_t inlen) // data to be hashed
+/* All-in-one convenience function. */
+static __inline__ int
+BLAKE2s(void *out, uint8_t outlen, /* return buffer for digest */
+ const void *key, uint8_t keylen, /* optional secret key */
+ const void *in, size_t inlen) /* data to be hashed */
{
struct BLAKE2s_ctx ctx;
if (BLAKE2s_init(&ctx, outlen, key, keylen)) return -1;
diff --git a/lib/libk/BUILD.bazel b/lib/libk/BUILD.bazel
new file mode 100644
index 0000000..51b4c1b
--- /dev/null
+++ b/lib/libk/BUILD.bazel
@@ -0,0 +1,80 @@
+filegroup(
+ name = "k_srcs",
+ srcs = [
+ "endian/little.c",
+ "stdio/fprintf.c",
+ "stdio/printf.c",
+ "stdio/vfprintf.c",
+ "stdlib/linked_list_allocator.c",
+ "stdlib/memcpy.c",
+ "stdlib/memset.c",
+ "string/itoa.c",
+ ],
+)
+
+cc_library(
+ name = "k",
+ srcs = [":k_srcs"],
+ hdrs = glob(["include/*.h"]),
+ includes = ["include"],
+ target_compatible_with = [
+ "@platforms//os:none",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+# tests
+cc_library(
+ name = "k_sut",
+ includes = ["."],
+ target_compatible_with = select({
+ "@platforms//os:none": ["@platforms//:incompatible"],
+ "//conditions:default": [],
+ }),
+ textual_hdrs = [":k_srcs"],
+)
+
+cc_test(
+ name = "test_endian_little",
+ srcs = [
+ "endian/test_endian_little.cc",
+ ],
+ deps = [
+ ":k_sut",
+ "@googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "test_linked_list_allocator",
+ srcs = [
+ "stdlib/test_allocator.hh",
+ "stdlib/test_linked_list_allocator.cc",
+ ],
+ deps = [
+ ":k_sut",
+ "@googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "test_mem",
+ srcs = [
+ "stdlib/test_mem.cc",
+ ],
+ deps = [
+ ":k_sut",
+ "@googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "test_string",
+ srcs = [
+ "string/test_string.cc",
+ ],
+ deps = [
+ ":k_sut",
+ "@googletest//:gtest_main",
+ ],
+)
diff --git a/lib/libk/endian/little.c b/lib/libk/endian/little.c
index 042bb55..56a20ad 100644
--- a/lib/libk/endian/little.c
+++ b/lib/libk/endian/little.c
@@ -1,6 +1,4 @@
-//=====================================================================
-// spdx-license-identifier: ISC
-//=====================================================================
+/* spdx-license-identifier: ISC */
#include "endian.h"
diff --git a/lib/tst/endian_little.cc b/lib/libk/endian/test_endian_little.cc
index 9c8c73b..97ee286 100644
--- a/lib/tst/endian_little.cc
+++ b/lib/libk/endian/test_endian_little.cc
@@ -2,7 +2,7 @@
#include <gtest/gtest.h>
namespace libk {
-#include "../libk/endian/little.c"
+#include "little.c"
} // namespace libk
TEST(endian_little, htole16)
diff --git a/lib/libk/endian.h b/lib/libk/include/endian.h
index 70bc5f7..6aa2669 100644
--- a/lib/libk/endian.h
+++ b/lib/libk/include/endian.h
@@ -1,13 +1,11 @@
-//=====================================================================
-// spdx-license-identifier: ISC
-//=====================================================================
+/* spdx-license-identifier: ISC */
#pragma once
#include <stdint.h>
-// These functions convert the byte encoding of integer values from host byte order to and from little-endian and
-// big-endian byte order
+/* These functions convert the byte encoding of integer values from host byte order to and from little-endian and
+ * big-endian byte order */
uint16_t htole16(uint16_t host_16b);
uint32_t htole32(uint32_t host_32b);
uint64_t htole64(uint64_t host_64b);
diff --git a/lib/libk/stdio.h b/lib/libk/include/stdio.h
index 5ef68f1..7a6e663 100644
--- a/lib/libk/stdio.h
+++ b/lib/libk/include/stdio.h
@@ -2,27 +2,19 @@
#include <stdarg.h>
-///@defgroup libk libk
-///@{
-///@defgroup stdio stdio
-///@{
+/** An object type used for streams */
+typedef struct FILE {
+ int id;
-#ifdef __cplusplus
-/**
- * An object type used for streams
- */
-struct kIoDevice {
/** Function that prints a character to the stream */
- virtual void putc(char) = 0;
+ void (*putc)(const struct FILE *, char);
+
/** Function that prints a string to the stream */
- virtual int puts(const char *, int) = 0;
+ int (*puts)(const struct FILE *, const char *, int);
+
/** Flush write buffers */
- virtual void flush() = 0;
-};
-typedef kIoDevice FILE;
-#else
-typedef void FILE;
-#endif
+ void (*flush)(const struct FILE *);
+} FILE;
/** A FILE value corresponding to stdin, the keyboard buffer */
extern FILE *stdin;
@@ -31,28 +23,19 @@ extern FILE *stdout;
/** A FILE value corresponding to stderr, the uart */
extern FILE *stderr;
-#ifdef __cplusplus
-extern "C" {
-#endif
/**
* Write the formatted string to stdout
* Supports ``%s`` (string), ``%d`` (decimal), ``%u`` (unsigned), ``%x`` (hexadecimal)
* @return number of bytes written
*/
-int printf(const char *restrict format, ...);
+int printf(const char *__restrict__ format, ...);
/**
* Write the formatted string to stream; see printf
*/
-int fprintf(FILE *restrict stream, const char *restrict format, ...);
+int fprintf(FILE *__restrict__ stream, const char *__restrict__ format, ...);
/**
* Write the formatted string to stream; see printf
*/
-int vfprintf(FILE *restrict stream, const char *restrict format, va_list ap);
-#ifdef __cplusplus
-}
-#endif
-
-///@}
-///@}
+int vfprintf(FILE *__restrict__ stream, const char *__restrict__ format, va_list ap);
diff --git a/lib/libk/stdlib.h b/lib/libk/include/stdlib.h
index 84d9b2d..143c931 100644
--- a/lib/libk/stdlib.h
+++ b/lib/libk/include/stdlib.h
@@ -2,11 +2,6 @@
#include <stddef.h>
-///@defgroup libk libk
-///@{
-///@defgroup stdlib stdlib
-///@{
-
/**
* Allocate size bytes and return a pointer to the allocated memory
*/
@@ -25,7 +20,4 @@ void *memset(void *s, int c, long unsigned n);
/**
* Copy n bytes from memory area src to memory area dest. The memory areas must not overlap.
*/
-void *memcpy(void *restrict dest, const void *restrict src, long unsigned n);
-
-///@}
-///@}
+void *memcpy(void *__restrict__ dest, const void *__restrict__ src, long unsigned n);
diff --git a/lib/libk/include/string.h b/lib/libk/include/string.h
new file mode 100644
index 0000000..45b05a5
--- /dev/null
+++ b/lib/libk/include/string.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#define OCTAL 8
+#define DECIMAL 10
+#define HEX 16
+
+/**
+ * Convert int into a string
+ */
+char *itoa(char *p, int x, unsigned base);
+/**
+ * Convert unsigned int into a string
+ */
+char *utoa(char *p, unsigned x, unsigned base);
diff --git a/lib/libk/stdio/fprintf.c b/lib/libk/stdio/fprintf.c
index 9a96dc6..c088f54 100644
--- a/lib/libk/stdio/fprintf.c
+++ b/lib/libk/stdio/fprintf.c
@@ -1,11 +1,12 @@
#include <stdio.h>
int
-fprintf(FILE *restrict stream, const char *restrict format, ...)
+fprintf(FILE *__restrict__ stream, const char *__restrict__ format, ...)
{
+ int c = 0;
va_list ap;
va_start(ap, format);
- int c = vfprintf(stream, format, ap);
+ c += vfprintf(stream, format, ap);
va_end(ap);
return c;
}
diff --git a/lib/libk/stdio/printf.c b/lib/libk/stdio/printf.c
index 4efc1ac..4c45593 100644
--- a/lib/libk/stdio/printf.c
+++ b/lib/libk/stdio/printf.c
@@ -1,11 +1,12 @@
#include <stdio.h>
int
-printf(const char *restrict format, ...)
+printf(const char *__restrict__ format, ...)
{
+ int c = 0;
va_list ap;
va_start(ap, format);
- int c = vfprintf(stdout, format, ap);
+ c += vfprintf(stdout, format, ap);
va_end(ap);
return c;
}
diff --git a/lib/libk/stdio/vfprintf.cpp b/lib/libk/stdio/vfprintf.c
index aa9256d..807c26a 100644
--- a/lib/libk/stdio/vfprintf.cpp
+++ b/lib/libk/stdio/vfprintf.c
@@ -3,40 +3,41 @@
static char buffer[3 * sizeof(int) + 2];
-extern "C" int
-vfprintf(FILE *restrict stream, const char *restrict format, va_list params)
+int
+vfprintf(FILE *__restrict__ stream, const char *__restrict__ format, va_list params)
{
int written = 0;
+ int i;
int s = 0;
int l = 0;
- for (int i = 0; format[i] != '\0'; ++i) {
+ for (i = 0; format[i] != '\0'; ++i) {
if (format[i] == '%') {
- written += stream->puts(&format[s], l);
+ written += stream->puts(stream, &format[s], l);
s = i + 2;
++i;
switch (format[i]) {
case 's': {
const char *arg = va_arg(params, const char *);
- written += stream->puts(arg, -1);
+ written += stream->puts(stream, arg, -1);
} break;
case 'c': {
- const int arg = va_arg(params, int);
- stream->putc(arg);
+ const char arg = (char)va_arg(params, int);
+ stream->putc(stream, arg);
++written;
} break;
case 'd': {
const char *arg = itoa(buffer, va_arg(params, int), 10);
- written += stream->puts(arg, -1);
+ written += stream->puts(stream, arg, -1);
} break;
case 'u': {
const char *arg = utoa(buffer, va_arg(params, unsigned int), 10);
- written += stream->puts(arg, -1);
+ written += stream->puts(stream, arg, -1);
} break;
case 'x': {
const char *arg = utoa(buffer, va_arg(params, unsigned int), 16);
- written += stream->puts(arg, -1);
+ written += stream->puts(stream, arg, -1);
} break;
}
@@ -47,8 +48,8 @@ vfprintf(FILE *restrict stream, const char *restrict format, va_list params)
++l;
}
- if (l > 0) { written += stream->puts(&format[s], l); }
+ if (l > 0) { written += stream->puts(stream, &format[s], l); }
- stream->flush();
+ stream->flush(stream);
return written;
}
diff --git a/lib/libk/stdlib/linked_list_allocator.c b/lib/libk/stdlib/linked_list_allocator.c
index 66c63d1..bcec580 100644
--- a/lib/libk/stdlib/linked_list_allocator.c
+++ b/lib/libk/stdlib/linked_list_allocator.c
@@ -31,13 +31,14 @@ alloc_init(void *mem, size_t size)
void *
malloc(size_t size)
{
+ struct Chunk *iter;
if (begin == NULL) return NULL;
- // find free chunk that is at least (size + sizeof(struct Chunk))
- for (struct Chunk *iter = begin; iter != NULL; iter = iter->next) {
+ /* find free chunk that is at least (size + sizeof(struct Chunk)) */
+ for (iter = begin; iter != NULL; iter = iter->next) {
if (iter->used != 0 || iter->size < size) continue;
- // if there's at least sizeof(struct Chunk) bytes left over, create a new Chunk
+ /* if there's at least sizeof(struct Chunk) bytes left over, create a new Chunk */
if (iter->size >= (size + 2 * sizeof(struct Chunk))) {
struct Chunk *next = (struct Chunk *)((uintptr_t)iter + sizeof(struct Chunk) + size);
Chunk_ctor(next, iter->size - size - sizeof(struct Chunk));
@@ -57,18 +58,20 @@ malloc(size_t size)
void
free(void *ptr)
{
+ struct Chunk *chunk;
if (ptr == NULL) return;
- struct Chunk *chunk = (struct Chunk *)((uintptr_t)ptr - sizeof(struct Chunk));
+
+ chunk = (struct Chunk *)((uintptr_t)ptr - sizeof(struct Chunk));
chunk->used = 0;
- // merge next chunk
+ /* merge next chunk */
if (chunk->next != NULL && chunk->next->used == 0) {
chunk->size += chunk->next->size + sizeof(struct Chunk);
chunk->next = chunk->next->next;
if (chunk->next != NULL) chunk->next->prev = chunk;
}
- // merge into prev chunk
+ /* merge into prev chunk */
if (chunk->prev != NULL && chunk->prev->used == 0) {
chunk->prev->size += chunk->size + sizeof(struct Chunk);
chunk->prev->next = chunk->next;
diff --git a/lib/libk/stdlib/memcpy.c b/lib/libk/stdlib/memcpy.c
index 90470d5..db7d21e 100644
--- a/lib/libk/stdlib/memcpy.c
+++ b/lib/libk/stdlib/memcpy.c
@@ -1,5 +1,5 @@
void *
-memcpy(void *restrict dest, const void *restrict src, long unsigned n)
+memcpy(void *__restrict__ dest, const void *__restrict__ src, long unsigned n)
{
char *pDest = (char *)dest;
const char *pSrc = (const char *)src;
diff --git a/lib/libk/stdlib/memset.c b/lib/libk/stdlib/memset.c
index a16bd05..2a86f8e 100644
--- a/lib/libk/stdlib/memset.c
+++ b/lib/libk/stdlib/memset.c
@@ -1,7 +1,8 @@
void *
memset(void *s, int c, long unsigned n)
{
+ unsigned i;
char *pDest = (char *)s;
- for (unsigned i = 0; i < n; ++i) pDest[i] = (char)c;
+ for (i = 0; i < n; ++i) pDest[i] = (char)c;
return s;
}
diff --git a/lib/tst/allocator.hh b/lib/libk/stdlib/test_allocator.hh
index 3bc1715..3bc1715 100644
--- a/lib/tst/allocator.hh
+++ b/lib/libk/stdlib/test_allocator.hh
diff --git a/lib/tst/linked_list_allocator.cc b/lib/libk/stdlib/test_linked_list_allocator.cc
index a2575d5..5963ce1 100644
--- a/lib/tst/linked_list_allocator.cc
+++ b/lib/libk/stdlib/test_linked_list_allocator.cc
@@ -3,7 +3,7 @@
#include <iostream>
namespace libk {
-#include "../libk/stdlib/linked_list_allocator.c"
+#include "linked_list_allocator.c"
std::ostream &
operator<<(std::ostream &os, const Chunk &b)
@@ -16,7 +16,7 @@ operator<<(std::ostream &os, const Chunk &b)
}
}; // namespace libk
-#include "allocator.hh"
+#include "test_allocator.hh"
TEST(UninitializedAllocator, malloc) { EXPECT_EQ(libk::malloc(1024), nullptr); }
diff --git a/lib/tst/mem.cc b/lib/libk/stdlib/test_mem.cc
index 1ad266c..f8a5e18 100644
--- a/lib/tst/mem.cc
+++ b/lib/libk/stdlib/test_mem.cc
@@ -3,8 +3,8 @@
#define restrict __restrict__
namespace libk {
-#include "../libk/stdlib/memcpy.c"
-#include "../libk/stdlib/memset.c"
+#include "memcpy.c"
+#include "memset.c"
} // namespace libk
TEST(mem, memset)
diff --git a/lib/libk/string.h b/lib/libk/string.h
deleted file mode 100644
index c8196c8..0000000
--- a/lib/libk/string.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#pragma once
-
-///@defgroup libk libk
-///@{
-///@defgroup string string
-///@{
-
-#define OCTAL 8
-#define DECIMAL 10
-#define HEX 16
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-/**
- * Convert int into a string
- */
-char *itoa(char *p, int x, int base);
-/**
- * Convert unsigned int into a string
- */
-char *utoa(char *p, unsigned x, int base);
-#ifdef __cplusplus
-}
-#endif
-
-///@}
-///@}
diff --git a/lib/libk/string/itoa.c b/lib/libk/string/itoa.c
index 2db9768..0997345 100644
--- a/lib/libk/string/itoa.c
+++ b/lib/libk/string/itoa.c
@@ -4,7 +4,7 @@
static const char *numbers = "0123456789abcdef";
char *
-utoa(char *p, unsigned x, int base)
+utoa(char *p, unsigned x, unsigned base)
{
p += 3 * sizeof(unsigned);
*--p = '\0';
@@ -18,12 +18,12 @@ utoa(char *p, unsigned x, int base)
}
char *
-itoa(char *p, int x, int base)
+itoa(char *p, int x, unsigned base)
{
const bool is_negative = (x < 0);
if (is_negative) x = -x;
- p = utoa(p, x, base);
+ p = utoa(p, (unsigned)x, base);
if (is_negative) *--p = '-';
return p;
diff --git a/lib/tst/string.cc b/lib/libk/string/test_string.cc
index f22c123..d12b318 100644
--- a/lib/tst/string.cc
+++ b/lib/libk/string/test_string.cc
@@ -1,7 +1,7 @@
#include <gtest/gtest.h>
namespace libk {
-#include "../libk/string/itoa.c"
+#include "itoa.c"
}
char buffer[64];
diff --git a/platforms/BUILD.bazel b/platforms/BUILD.bazel
new file mode 100644
index 0000000..1f13594
--- /dev/null
+++ b/platforms/BUILD.bazel
@@ -0,0 +1,7 @@
+platform(
+ name = "i386",
+ constraint_values = [
+ "@platforms//cpu:i386",
+ "@platforms//os:none",
+ ],
+)
diff --git a/project_config.bzl b/project_config.bzl
new file mode 100644
index 0000000..a4c58fb
--- /dev/null
+++ b/project_config.bzl
@@ -0,0 +1,2 @@
+def version():
+ return "0.1.0"
diff --git a/rules.mk b/rules.mk
deleted file mode 100644
index 833664d..0000000
--- a/rules.mk
+++ /dev/null
@@ -1,142 +0,0 @@
-# generate objects from sources
-# arg 1: target.SRCS
-# arg 2: object suffix prefix
-# returns: target.OBJS
-objects = $(foreach f,$($1),$(addsuffix $2.o,$(basename $f)))
-
-# generate depends from .S .c .cpp sources
-# arg 1: target.SRCS
-# arg 2: dependency suffix prefix
-# returns: target.DEPS
-depends = $(foreach f,$(filter %.S %.c %.cpp,$($1)),$(addsuffix $2.d,$(basename $f)))
-
-# default target
-all: targets
-
-
-# TARGETBIN: binaries using the target architecture
-$(foreach T,${TARGETBIN},\
- $(eval $T.OBJS += $(call objects,$T.SRCS,_${ARCH}) ) \
- $(eval $T.DEPS += $(call depends,$T.SRCS,_${ARCH}) ) \
- $(eval include $($T.DEPS) ) \
- $(eval $T.elf: ${$T.OBJS} ) \
- $(eval DEFAULT_TARGETS += $T.elf) \
-)
-
-# TARGETLIB: static libraries using the target architecture
-$(foreach T,${TARGETLIB},\
- $(eval $T.OBJS += $(call objects,$T.SRCS,_${ARCH}) ) \
- $(eval $T.DEPS += $(call depends,$T.SRCS,_${ARCH}) ) \
- $(eval include $($T.DEPS) ) \
- $(eval $T.a: ${$T.OBJS} ) \
- $(eval DEFAULT_TARGETS += $T.a) \
-)
-
-# HOSTTARGETBIN: binaries using the host compiler
-$(foreach T,${HOSTTARGETBIN},\
- $(eval $T.OBJS += $(call objects,$T.SRCS,) ) \
- $(eval $T.DEPS += $(call depends,$T.SRCS,) ) \
- $(eval include $($T.DEPS) ) \
- $(eval $T: ${$T.OBJS}; @echo ' LD HOST $T'; ${HOST_CC} ${HOST_LDFLAGS} -o $T ${$T.OBJS} ) \
- $(eval DEFAULT_TARGETS += $T) \
-)
-
-TESTS.DEPS = $(foreach F,${TESTS},$(addsuffix .d,$F))
-include ${TESTS.DEPS}
-
-debug:
- @echo "TARGETBIN ${TARGETBIN}"
- @echo "TARGETLIB ${TARGETLIB}"
- @echo "HOSTTARGETBIN ${HOSTTARGETBIN}"
- @echo "HOSTTARGETLIB ${HOSTTARGETLIB}"
- @echo "DEFAULT_TARGETS ${DEFAULT_TARGETS}"
- @echo "TESTS ${TESTS}"
- @echo " DEPS ${TESTS.DEPS}"
-
-%.info:
- @echo "Target: $(basename $@)"
- @echo " SRCS: ${$(basename $@).SRCS}"
- @echo " OBJS: ${$(basename $@).OBJS}"
- @echo " DEPS: ${$(basename $@).DEPS}"
-
-targets: ${DEFAULT_TARGETS}
- @echo " -> Built ${DEFAULT_TARGETS}"
-
-# extra flags
-${ARCH}_CFLAGS += -I../lib/libk \
- -Werror=implicit-function-declaration
-${ARCH}_CXXFLAGS += -I../lib/libk -Drestrict=__restrict__
-
-# Target depndency rules
-%_${ARCH}.d: %.S
- @${${ARCH}_CC} ${${ARCH}_CFLAGS} -M -MT $(<:.S=_${ARCH}.o) $< -MF $@
-
-%_${ARCH}.d: %.c
- @${${ARCH}_CC} ${${ARCH}_CFLAGS} -M -MT $(<:.c=_${ARCH}.o) $< -MF $@
-
-%_${ARCH}.d: %.cpp
- @${${ARCH}_CXX} ${${ARCH}_CXXFLAGS} -M -MT $(<:.cpp=_${ARCH}.o) $< -MF $@
-
-# Host dependency rules
-%.d: %.c
- @${HOST_CC} ${HOST_CFLAGS} -M -MT $(<:.c=.o) $< -MF $@
-
-%.d: %.cc
- @${HOST_CXX} ${HOST_CXXFLAGS} -M -MT $(<:.cc=) $< -MF $@
-
-# Target suffix rules
-%.a:
- @echo ' AR $@'
- @${${ARCH}_AR} ${${ARCH}_ARFLAGS} $@ $(filter %.o,$^)
-
-%_${ARCH}.o: %.s
- @echo ' AS $<'
- @${${ARCH}_AS} ${${ARCH}_ASFLAGS} -c -o $@ $<
-
-%_${ARCH}.o: %.S
- @echo ' CC $<'
- @${${ARCH}_CC} ${${ARCH}_CFLAGS} -c -o $@ $<
-
-%_${ARCH}.o: %.c
- @echo ' CC $<'
- @${${ARCH}_CC} ${${ARCH}_CFLAGS} -c -o $@ $<
-
-%_${ARCH}.o: %.cpp
- @echo ' CXX $<'
- @${${ARCH}_CXX} ${${ARCH}_CXXFLAGS} -c -o $@ $<
-
-%.elf:
- @echo ' LD $@'
- @${${ARCH}_LD} ${${ARCH}_LDFLAGS} -o $@ $^
- @echo -n ' B2b '
- @b2sum $@ | cut -d' ' -f1
-
-# Host suffix rules
-%.o: %.c
- @echo ' CC HOST $<'
- @${HOST_CC} ${HOST_CFLAGS} -c -o $@ $<
-
-# test rules
-tst/%: tst/%.cc
- @echo ' CXX TEST $@'
- @${HOST_CXX} ${HOST_CXXFLAGS} $< -o $@
-
-.PHONY: test.base valgrind.base clean.base FORCE
-test.base: ${TESTS}
- @echo " -> Running tests in $(shell pwd | xargs basename)"
- @$(foreach f,$^,echo " -> $f"; ./$f &&) echo "Done"
-
-valgrind.base: ${TESTS}
- @echo " -> Running valgrind on tests in $(shell pwd | xargs basename)"
- @$(foreach f,$^,echo " -> $f"; valgrind --leak-check=full ./$f;)
-
-clean.base: FORCE
- @echo " -> Cleaning $(shell pwd | xargs basename)"
- @$(foreach V,$(filter %.OBJS, ${.VARIABLES}), rm -rf $($(V)))
- @$(foreach V,$(filter %.DEPS, ${.VARIABLES}), rm -rf $($(V)))
- @rm -rf *.a
- @rm -rf ${TESTS}
-
-%: %.base ;
-
-FORCE: ;
diff --git a/scripts/test_runner.py b/scripts/test_runner.py
new file mode 100755
index 0000000..53bebd3
--- /dev/null
+++ b/scripts/test_runner.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+
+""" Test runner """
+
+import argparse
+import os
+import subprocess
+
+def main():
+ """ Main function"""
+
+ parser = argparse.ArgumentParser(description='Run test executables')
+ parser.add_argument('-v', '--verbose', action='store_true', help='Show test stdout/stderr')
+ parser.add_argument('--valgrind', action='store_true', help='Run tests under valgrind')
+ parser.add_argument('test', type=str, nargs='+', help='test executable to run')
+ args = parser.parse_args()
+
+ cwd = os.getcwd()
+ fail_count = 0
+
+ for test in args.test:
+ cmd = []
+ if args.valgrind:
+ cmd += [ 'valgrind', '--leak-check=full', '--error-exitcode=128' ]
+ cmd.append(os.path.join(cwd, test))
+ #print(cmd)
+
+ if not args.verbose:
+ print(f' {test:.<48}', end='')
+ result = subprocess.run(cmd, capture_output=not args.verbose, check=False)
+ if not args.verbose:
+ print('ok' if result.returncode == 0 else 'failed')
+ if result.returncode != 0:
+ fail_count += 1
+
+ print(f' Ran {len(args.test)} tests, {fail_count} failed')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/Makefile b/src/Makefile
deleted file mode 100644
index f9ab6fe..0000000
--- a/src/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-include ../Makefile.config
-
-INCLUDES := -isystem../grub -I../${ARCH} -I../devices
-${ARCH}_CFLAGS += ${INCLUDES}
-${ARCH}_CXXFLAGS += ${INCLUDES}
-
-TARGETLIB += kernel
-kernel.SRCS := multiboot2.c mmap.c kernel.cpp mem/vmm.c
-kernel.OBJS := conf.h
-
-TESTS += tst/taskqueue tst/roundrobin
-
-include ../rules.mk
-
-conf.h: conf.h.in
- @echo ' GEN $@'
- @cp conf.h.in conf.h
- @sed -i 's/@VERSION@/$(shell git describe)/' conf.h
- @sed -i 's/@CC@/${${ARCH}_CCID}/' conf.h
-
diff --git a/src/boot.h b/src/boot.h
deleted file mode 100644
index 8d62bdc..0000000
--- a/src/boot.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct {
- // kernel command line
- char cmdline[64];
-
- // memory map
- unsigned bitmap[1024 * 32];
-
- // module
- unsigned module_start;
- unsigned module_end;
- char module_cmdline[64];
-} boot_info_t;
-
-_Static_assert((1024 * 32 * sizeof(unsigned) * 8) == (1024 * 1024), "bitmap size check");
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/src/conf.h.in b/src/conf.h.in
deleted file mode 100644
index 52093a8..0000000
--- a/src/conf.h.in
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-
-#define VERSION "@VERSION@"
-#define CC "@CC@"
diff --git a/toolchains/BUILD.bazel b/toolchains/BUILD.bazel
new file mode 100644
index 0000000..d46f812
--- /dev/null
+++ b/toolchains/BUILD.bazel
@@ -0,0 +1,34 @@
+load(":i386_elf_gcc.bzl", "cc_toolchain_config")
+
+package(default_visibility = ["//visibility:public"])
+
+filegroup(name = "empty")
+
+cc_toolchain_config(name = "i386_elf_gcc_toolchain_config")
+
+cc_toolchain(
+ name = "i386_elf_gcc_toolchain",
+ all_files = ":empty",
+ compiler_files = ":empty",
+ dwp_files = ":empty",
+ linker_files = ":empty",
+ objcopy_files = ":empty",
+ strip_files = ":empty",
+ supports_param_files = 0,
+ toolchain_config = ":i386_elf_gcc_toolchain_config",
+ toolchain_identifier = "none_i386-toolchain",
+)
+
+toolchain(
+ name = "i386_elf_gcc",
+ exec_compatible_with = [
+ "@platforms//cpu:x86_64",
+ "@platforms//os:linux",
+ ],
+ target_compatible_with = [
+ "@platforms//cpu:i386",
+ "@platforms//os:none",
+ ],
+ toolchain = ":i386_elf_gcc_toolchain",
+ toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
+)
diff --git a/toolchains/i386_elf_gcc.bzl b/toolchains/i386_elf_gcc.bzl
new file mode 100644
index 0000000..ad933d2
--- /dev/null
+++ b/toolchains/i386_elf_gcc.bzl
@@ -0,0 +1,123 @@
+load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
+load(
+ "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
+ "feature",
+ "flag_group",
+ "flag_set",
+ "tool_path",
+)
+
+all_link_actions = [
+ ACTION_NAMES.cpp_link_executable,
+ ACTION_NAMES.cpp_link_dynamic_library,
+ ACTION_NAMES.cpp_link_nodeps_dynamic_library,
+]
+
+all_compile_actions = [
+ ACTION_NAMES.assemble,
+ ACTION_NAMES.c_compile,
+ ACTION_NAMES.clif_match,
+ ACTION_NAMES.cpp_compile,
+ ACTION_NAMES.cpp_header_parsing,
+ ACTION_NAMES.cpp_module_codegen,
+ ACTION_NAMES.cpp_module_compile,
+ ACTION_NAMES.linkstamp_compile,
+ ACTION_NAMES.lto_backend,
+ ACTION_NAMES.preprocess_assemble,
+]
+
+def _impl(ctx):
+ tool_paths = [
+ tool_path(
+ name = "gcc",
+ path = "/usr/bin/i686-elf-gcc",
+ ),
+ tool_path(
+ name = "ld",
+ path = "/usr/bin/i686-elf-ld",
+ ),
+ tool_path(
+ name = "ar",
+ path = "/usr/bin/i686-elf-ar",
+ ),
+ tool_path(
+ name = "cpp",
+ path = "/usr/bin/i686-elf-cpp",
+ ),
+ tool_path(
+ name = "gcov",
+ path = "/bin/false",
+ ),
+ tool_path(
+ name = "nm",
+ path = "/usr/bin/i686-elf-nm",
+ ),
+ tool_path(
+ name = "objdump",
+ path = "/usr/bin/i686-elf-objdump",
+ ),
+ tool_path(
+ name = "strip",
+ path = "/usr/bin/i686-elf-strip",
+ ),
+ ]
+
+ features = [
+ feature(
+ name = "default_compiler_flags",
+ enabled = True,
+ flag_sets = [
+ flag_set(
+ actions = all_compile_actions,
+ flag_groups = [
+ flag_group(
+ flags = [
+ "-fanalyzer",
+ "-ffreestanding",
+ "-mgeneral-regs-only",
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ feature(
+ name = "default_linker_flags",
+ enabled = True,
+ flag_sets = [
+ flag_set(
+ actions = all_link_actions,
+ flag_groups = ([
+ flag_group(
+ flags = [
+ "-nostdlib",
+ ],
+ ),
+ ]),
+ ),
+ ],
+ ),
+ ]
+
+ return cc_common.create_cc_toolchain_config_info(
+ ctx = ctx,
+ features = features,
+ cxx_builtin_include_directories = [
+ "/usr/lib/gcc/i686-elf",
+ ],
+ toolchain_identifier = "local",
+ host_system_name = "local",
+ target_system_name = "local",
+ target_cpu = "i686",
+ target_libc = "unknown",
+ compiler = "gcc",
+ abi_version = "unknown",
+ abi_libc_version = "unknown",
+ tool_paths = tool_paths,
+ )
+
+cc_toolchain_config = rule(
+ implementation = _impl,
+ attrs = {},
+ provides = [CcToolchainConfigInfo],
+)
diff --git a/toolchains/i386_qemu.bzl b/toolchains/i386_qemu.bzl
new file mode 100644
index 0000000..c9f8535
--- /dev/null
+++ b/toolchains/i386_qemu.bzl
@@ -0,0 +1,8 @@
+_wrapper_template = """\
+#!/bin/bash
+qemu-system-i386 -accel kvm -machine pc -d cpu_reset -display gtk,zoom-to-fit=on -cdrom {cdrom}
+"""
+
+def qemu_wrapper():
+ return _wrapper_template
+
diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel
new file mode 100644
index 0000000..fddb974
--- /dev/null
+++ b/tools/BUILD.bazel
@@ -0,0 +1,6 @@
+package(default_visibility = ["//visibility:public"])
+
+py_binary(
+ name = "make_iso",
+ srcs = ["make_iso.py"],
+)
diff --git a/tools/configure_file.bzl b/tools/configure_file.bzl
new file mode 100644
index 0000000..8fdd75c
--- /dev/null
+++ b/tools/configure_file.bzl
@@ -0,0 +1,29 @@
+load("//:project_config.bzl", "version")
+load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain", "use_cc_toolchain")
+
+def configure_file(**kwargs):
+ _configure_file(
+ source_file = "{name}.h".format(**kwargs),
+ **kwargs
+ )
+
+def _configure_file_impl(ctx):
+ cc_toolchain = find_cc_toolchain(ctx)
+
+ ctx.actions.expand_template(
+ template = ctx.file.template,
+ output = ctx.outputs.source_file,
+ substitutions = {
+ "{VERSION}": '"{}"'.format(version()),
+ "{CC}": '"{} " __VERSION__'.format(cc_toolchain.compiler),
+ },
+ )
+
+_configure_file = rule(
+ attrs = {
+ "template": attr.label(allow_single_file = True),
+ "source_file": attr.output(mandatory = True),
+ },
+ toolchains = use_cc_toolchain(),
+ implementation = _configure_file_impl,
+)
diff --git a/tools/interface_generator/.bazelrc b/tools/interface_generator/.bazelrc
new file mode 100644
index 0000000..71d2e60
--- /dev/null
+++ b/tools/interface_generator/.bazelrc
@@ -0,0 +1,2 @@
+build --cxxopt=-std=c++20
+
diff --git a/tools/interface_generator/BUILD.bazel b/tools/interface_generator/BUILD.bazel
new file mode 100644
index 0000000..8c4bde6
--- /dev/null
+++ b/tools/interface_generator/BUILD.bazel
@@ -0,0 +1,13 @@
+load("@rules_python//python:pip.bzl", "compile_pip_requirements")
+
+package(default_visibility = ["//visibility:public"])
+
+# This rule adds a convenient way to update the requirements file.
+compile_pip_requirements(
+ name = "requirements",
+ src = "requirements.txt",
+ requirements_txt = "requirements_lock.txt",
+)
+
+# make license available to test package
+exports_files(["LICENSE.md"])
diff --git a/tools/interface_generator/LICENSE.md b/tools/interface_generator/LICENSE.md
new file mode 100644
index 0000000..ddb4966
--- /dev/null
+++ b/tools/interface_generator/LICENSE.md
@@ -0,0 +1,16 @@
+Copyright (c) 2024 aqua@iserlohn-fortress.net
+
+Permission to use, copy, modify, and 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.
+
+SPDX License Identifier: [ISC](https://spdx.org/licenses/ISC.html)
diff --git a/tools/interface_generator/MODULE.bazel b/tools/interface_generator/MODULE.bazel
new file mode 100644
index 0000000..53b2ba4
--- /dev/null
+++ b/tools/interface_generator/MODULE.bazel
@@ -0,0 +1,20 @@
+###############################################################################
+# Bazel now uses Bzlmod by default to manage external dependencies.
+# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel.
+#
+# For more details, please check https://github.com/bazelbuild/bazel/issues/18958
+###############################################################################
+
+module(name = "interface_generator", version = "0.1.0")
+
+# external dependencies
+bazel_dep(name = "googletest", version = "1.15.2")
+bazel_dep(name = "rules_python", version = "0.34.0")
+
+pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
+pip.parse(
+ hub_name = "pip",
+ python_version = "3.11",
+ requirements_lock = "//:requirements_lock.txt",
+)
+use_repo(pip, "pip")
diff --git a/tools/interface_generator/bin/BUILD.bazel b/tools/interface_generator/bin/BUILD.bazel
new file mode 100644
index 0000000..04843b9
--- /dev/null
+++ b/tools/interface_generator/bin/BUILD.bazel
@@ -0,0 +1,45 @@
+load("@pip//:requirements.bzl", "requirement")
+load("//private:defs.bzl", "py_pytest")
+
+""" interface declaration """
+
+py_library(
+ name = "interface_declaration",
+ srcs = ["interface_declaration.py"],
+)
+
+""" templates """
+
+py_library(
+ name = "templates",
+ srcs = ["templates.py"],
+ data = glob(["templates/*"]),
+)
+
+""" interface_generator """
+
+py_binary(
+ name = "interface_generator",
+ srcs = [
+ "interface_generator.py",
+ "templates.py",
+ ],
+ imports = ["."],
+ visibility = ["//visibility:public"],
+ deps = [
+ ":interface_declaration",
+ ":templates",
+ requirement("mako"),
+ ],
+)
+
+""" pytest """
+
+py_pytest(
+ name = "pytest",
+ srcs = glob(["*.py"]),
+ data = glob(["templates/*"]),
+ deps = [
+ requirement("mako"),
+ ],
+)
diff --git a/tools/interface_generator/bin/interface_declaration.py b/tools/interface_generator/bin/interface_declaration.py
new file mode 100644
index 0000000..4560bbd
--- /dev/null
+++ b/tools/interface_generator/bin/interface_declaration.py
@@ -0,0 +1,58 @@
+"""
+interface_declaration.py
+"""
+
+from dataclasses import dataclass, asdict
+from pathlib import Path
+
+
+@dataclass
+class InterfaceDeclaration:
+ """interface declaration class"""
+
+ name: str
+ license_hdr: str
+ system_includes: list[str]
+ types: list[dict]
+ functions: list[dict]
+
+ def read_license(self, path: Path):
+ """read and starrify a license"""
+ if path is None:
+ self.license_hdr = ""
+ return
+
+ with open(path, encoding="utf-8") as license_file:
+ self.license_hdr = "".join(
+ [
+ f" * { line.rstrip().ljust(72)[:72] } * \n"
+ for line in license_file.readlines()
+ ]
+ ).rstrip()
+
+ def __init__(self, name: str, license_path: Path):
+ self.name = name if name is not None else "kstdio"
+ self.read_license(license_path)
+ self.system_includes = ["stdarg.h"]
+ self.types = [
+ {
+ "name": "File",
+ "members": [
+ "int fd",
+ "int (*putc)(const struct kstdio_File*, const char)",
+ "int (*puts)(const struct kstdio_File*, const char*)",
+ ],
+ },
+ ]
+ self.functions = [
+ {
+ "name": "printf",
+ "return": "int",
+ "arguments": ["const char* format"],
+ "argument_names": ["format"],
+ },
+ ]
+
+ def into_dict(self) -> dict:
+ """create a dictionary for use in mako"""
+ return asdict(self)
diff --git a/tools/interface_generator/bin/interface_declaration_unittest.py b/tools/interface_generator/bin/interface_declaration_unittest.py
new file mode 100644
index 0000000..b2ad80c
--- /dev/null
+++ b/tools/interface_generator/bin/interface_declaration_unittest.py
@@ -0,0 +1,19 @@
+"""
+interface declaration unit tests
+"""
+
+import unittest
+from interface_declaration import InterfaceDeclaration
+
+
+class InterfaceDeclarationUnittest(unittest.TestCase):
+ """interface_declaration unit tests"""
+
+ def test_interfacedeclaration_class_asdict(self):
+ """test mock interface"""
+ interface = InterfaceDeclaration("kstdio", None)
+ interface_dict = interface.into_dict()
+
+ self.assertEqual(interface.name, "kstdio")
+ self.assertEqual(len(interface.license_hdr), 0)
+ self.assertEqual(interface_dict["name"], "kstdio")
diff --git a/tools/interface_generator/bin/interface_generator.py b/tools/interface_generator/bin/interface_generator.py
new file mode 100755
index 0000000..eab93d7
--- /dev/null
+++ b/tools/interface_generator/bin/interface_generator.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+
+"""
+interface_generator.py
+"""
+
+from argparse import ArgumentParser
+from pathlib import Path
+import sys
+from mako.lookup import TemplateLookup
+from interface_declaration import InterfaceDeclaration
+from templates import get_templates, get_templates_dir
+
+PROG = {
+ "name": "interface_generator",
+ "version": "0.1",
+}
+
+
+def generate_file(
+ template: Path, templates: Path, output, interface: InterfaceDeclaration
+):
+ """generate file using a tempalte and write it to the output location"""
+ lookup = TemplateLookup(directories=[".", templates.absolute()])
+ mako_template = lookup.get_template(str(template.relative_to(templates)))
+ output_name = template.stem.replace("interface", interface.name)
+ print(f"{interface.name} via {template.name} => {output_name}")
+
+ result = mako_template.render(**interface.into_dict(), PROG=PROG)
+
+ if isinstance(output, Path):
+ # print(f"writing to {(output / output_name).absolute()}")
+ with open(output / output_name, "w", encoding="utf-8") as output_file:
+ print(result, file=output_file)
+ else:
+ print(result, file=output)
+
+
+def main():
+ """main function"""
+ parser = ArgumentParser(
+ prog="interface_generator",
+ description="Generate C header and mock files from an interface declaration",
+ )
+ parser.add_argument(
+ "-i",
+ "--interface",
+ type=Path,
+ # required=True,
+ help="path to interface file",
+ )
+ parser.add_argument(
+ "-t",
+ "--templates",
+ type=Path,
+ default=get_templates_dir(),
+ help="templates location",
+ )
+ parser.add_argument(
+ "-l",
+ "--license",
+ type=Path,
+ required=True,
+ help="path to license file",
+ )
+ parser.add_argument(
+ "-o",
+ "--output",
+ type=Path,
+ default=sys.stdout,
+ help="path to output, stdout by default",
+ )
+
+ args = parser.parse_args()
+ # print(args)
+
+ interface = InterfaceDeclaration(args.interface, args.license)
+ # print(interface)
+
+ for template in get_templates(args.templates):
+ # print(template)
+ generate_file(template, args.templates, args.output, interface)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/interface_generator/bin/templates.py b/tools/interface_generator/bin/templates.py
new file mode 100644
index 0000000..9f7539e
--- /dev/null
+++ b/tools/interface_generator/bin/templates.py
@@ -0,0 +1,19 @@
+"""template helper functions"""
+
+from pathlib import Path
+import re
+
+
+TEMPLATE_PATTERN = re.compile(r"^[^_]\S+\.mako$")
+
+
+def get_templates_dir(name="templates") -> Path:
+ """get the templates directory"""
+ return Path(__file__).parent / name
+
+
+def get_templates(path: Path) -> list[Path]:
+ """list templates in given path"""
+ result = list(path.glob("*.mako"))
+ result = [item for item in result if TEMPLATE_PATTERN.match(item.name)]
+ return result
diff --git a/tools/interface_generator/bin/templates/__c_functions.mako b/tools/interface_generator/bin/templates/__c_functions.mako
new file mode 100644
index 0000000..2e40119
--- /dev/null
+++ b/tools/interface_generator/bin/templates/__c_functions.mako
@@ -0,0 +1,4 @@
+/* Functions */
+% for fn in functions:
+${fn['return']} ${name}_${fn['name']}(${ ", ".join(fn['arguments']) });
+% endfor
diff --git a/tools/interface_generator/bin/templates/__c_system_include.mako b/tools/interface_generator/bin/templates/__c_system_include.mako
new file mode 100644
index 0000000..d6a9d09
--- /dev/null
+++ b/tools/interface_generator/bin/templates/__c_system_include.mako
@@ -0,0 +1,4 @@
+/* System includes */
+% for path in system_includes:
+#include <${path}>
+% endfor
diff --git a/tools/interface_generator/bin/templates/__c_types.mako b/tools/interface_generator/bin/templates/__c_types.mako
new file mode 100644
index 0000000..ce6b6b5
--- /dev/null
+++ b/tools/interface_generator/bin/templates/__c_types.mako
@@ -0,0 +1,6 @@
+/* Types */
+% for type in types:
+typedef struct ${name}_${type['name']} {
+${ "\n".join([ " {};".format(member) for member in type['members'] ]) }
+} ${name}_${type['name']};
+% endfor
diff --git a/tools/interface_generator/bin/templates/__header.mako b/tools/interface_generator/bin/templates/__header.mako
new file mode 100644
index 0000000..43ce1e7
--- /dev/null
+++ b/tools/interface_generator/bin/templates/__header.mako
@@ -0,0 +1,5 @@
+/* This file is generated by ${PROG['name']} v${PROG['version']} */
+
+/******************************************************************************
+${ license_hdr }
+ ******************************************************************************/
diff --git a/tools/interface_generator/bin/templates/interface.h.mako b/tools/interface_generator/bin/templates/interface.h.mako
new file mode 100644
index 0000000..47ea940
--- /dev/null
+++ b/tools/interface_generator/bin/templates/interface.h.mako
@@ -0,0 +1,8 @@
+<%include file="__header.mako" />
+#ifndef ${ name.upper() }
+#define ${ name.upper() }
+
+<%include file="__c_system_include.mako" />
+<%include file="__c_types.mako" />
+<%include file="__c_functions.mako" />
+#endif /* ${ name.upper() } */
diff --git a/tools/interface_generator/bin/templates/interface_mock.cpp.mako b/tools/interface_generator/bin/templates/interface_mock.cpp.mako
new file mode 100644
index 0000000..721f2c4
--- /dev/null
+++ b/tools/interface_generator/bin/templates/interface_mock.cpp.mako
@@ -0,0 +1,32 @@
+<%include file="__header.mako" />
+
+#include <stdexcept>
+#include "${name}_mock.hpp"
+
+static I${name}_mock *s_instance = nullptr;
+
+I${name}_mock::I${name}_mock()
+{
+ if(s_instance != nullptr)
+ {
+ throw std::runtime_error("Creating a second instance of mock object");
+ }
+ s_instance = this;
+}
+
+I${name}_mock::~I${name}_mock()
+{
+ // destructors shouldn't throw exceptions
+ s_instance = nullptr;
+}
+
+% for fn in functions:
+${fn['return']} ${name}_${fn['name']}(${ ", ".join(fn['arguments']) })
+{
+ if(s_instance == nullptr)
+ {
+ throw std::runtime_error("No mock created to handle function ${name}_${fn['name']}");
+ }
+ return s_instance->${fn['name']}(${ ", ".join(fn['argument_names']) });
+}
+% endfor
diff --git a/tools/interface_generator/bin/templates/interface_mock.hpp.mako b/tools/interface_generator/bin/templates/interface_mock.hpp.mako
new file mode 100644
index 0000000..e33d50e
--- /dev/null
+++ b/tools/interface_generator/bin/templates/interface_mock.hpp.mako
@@ -0,0 +1,26 @@
+<%include file="__header.mako" />
+#ifndef ${ name.upper() }_MOCK
+#define ${ name.upper() }_MOCK
+
+extern "C" {
+#include "${ name }.h"
+}
+
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+class I${name}_mock
+{
+public:
+ I${name}_mock();
+ ~I${name}_mock();
+
+ /* Functions */
+% for fn in functions:
+ MOCK_METHOD(${fn['return']}, ${fn['name']}, (${ ", ".join(fn['arguments']) }));
+% endfor
+};
+
+using ${name}_mock = ::testing::NiceMock<I${name}_mock>;
+
+#endif /* ${ name.upper() }_MOCK */
diff --git a/tools/interface_generator/bin/templates_unittest.py b/tools/interface_generator/bin/templates_unittest.py
new file mode 100644
index 0000000..acb1685
--- /dev/null
+++ b/tools/interface_generator/bin/templates_unittest.py
@@ -0,0 +1,30 @@
+"""
+templates unit tests
+"""
+
+import unittest
+from pathlib import Path
+import templates
+
+
+class TemplatesUnittest(unittest.TestCase):
+ """templates unit tests"""
+
+ def test_get_templates_dir_is_valid(self):
+ """verify that default templates dir is valid"""
+ path = templates.get_templates_dir()
+
+ self.assertTrue(isinstance(path, Path))
+ self.assertTrue(path.exists())
+ self.assertTrue(path.is_dir())
+
+ def test_get_templates(self):
+ """verify that templates are available by default"""
+ path = templates.get_templates_dir()
+ result = templates.get_templates(path)
+
+ self.assertGreater(len(result), 0)
+ for template in result:
+ self.assertTrue(isinstance(template, Path))
+ self.assertTrue(template.exists())
+ self.assertTrue(template.is_file())
diff --git a/tools/interface_generator/defs.bzl b/tools/interface_generator/defs.bzl
new file mode 100644
index 0000000..238588f
--- /dev/null
+++ b/tools/interface_generator/defs.bzl
@@ -0,0 +1,53 @@
+def _generate_interface_impl(ctx):
+ out_hdrs = [
+ ctx.actions.declare_file(ctx.attr.interface + ".h"),
+ ctx.actions.declare_file(ctx.attr.interface + "_mock.hpp"),
+ ]
+ out_srcs = [
+ ctx.actions.declare_file(ctx.attr.interface + "_mock.cpp"),
+ ]
+ args = ["-l", ctx.file.license.path, "-o", out_hdrs[0].dirname]
+
+ ctx.actions.run(
+ tools = ctx.attr._interface_generator_tool[DefaultInfo].data_runfiles.files,
+ inputs = [ctx.file.license],
+ outputs = out_srcs + out_hdrs,
+ executable = ctx.executable._interface_generator_tool,
+ arguments = args,
+ mnemonic = "GenerateInterface",
+ )
+
+ compilation_ctx = cc_common.create_compilation_context(
+ headers = depset(out_hdrs),
+ includes = depset([out_hdrs[0].dirname]),
+ )
+
+ return [
+ DefaultInfo(files = depset(out_srcs)),
+ CcInfo(compilation_context = compilation_ctx),
+ ]
+
+generate_interface_rule = rule(
+ implementation = _generate_interface_impl,
+ attrs = {
+ "interface": attr.string(),
+ "license": attr.label(allow_single_file = True),
+ "_interface_generator_tool": attr.label(
+ executable = True,
+ cfg = "exec",
+ allow_files = True,
+ providers = [DefaultInfo],
+ default = Label("//bin:interface_generator"),
+ ),
+ "outs": attr.output_list(),
+ },
+)
+
+def generate_interface(name, interface, license, visibility = None):
+ generate_interface_rule(
+ name = name,
+ interface = interface,
+ outs = [name + "_mock.cpp"],
+ license = license,
+ visibility = visibility,
+ )
diff --git a/tools/interface_generator/private/BUILD.bazel b/tools/interface_generator/private/BUILD.bazel
new file mode 100644
index 0000000..3012bcb
--- /dev/null
+++ b/tools/interface_generator/private/BUILD.bazel
@@ -0,0 +1,9 @@
+""" targets internal to the tool and rule """
+
+package(default_visibility = ["//:__pkg__"])
+
+exports_files([
+ "mypyrc",
+ "pylintrc",
+ "pytest_wrapper.py",
+])
diff --git a/tools/interface_generator/private/defs.bzl b/tools/interface_generator/private/defs.bzl
new file mode 100644
index 0000000..8e2ae8d
--- /dev/null
+++ b/tools/interface_generator/private/defs.bzl
@@ -0,0 +1,29 @@
+load("@pip//:requirements.bzl", "requirement")
+
+def py_pytest(name, srcs, deps = [], data = [], **kwargs):
+ native.py_test(
+ name = name,
+ srcs = ["//private:pytest_wrapper.py"],
+ main = "//private:pytest_wrapper.py",
+ legacy_create_init = False,
+ imports = ["."],
+ args = [
+ "--capture=no",
+ "--black",
+ "--pylint",
+ "--pylint-rcfile=$(location //private:pylintrc)",
+ "--mypy",
+ "--mypy-config-file=$(location //private:mypyrc)",
+ ] + ["$(location :%s)" % x for x in srcs],
+ deps = [
+ requirement("pytest"),
+ requirement("pytest-black"),
+ requirement("pytest-pylint"),
+ requirement("pytest-mypy"),
+ ] + deps,
+ data = [
+ "//private:mypyrc",
+ "//private:pylintrc",
+ ] + srcs + data,
+ **kwargs
+ )
diff --git a/tools/interface_generator/private/mypyrc b/tools/interface_generator/private/mypyrc
new file mode 100644
index 0000000..d787271
--- /dev/null
+++ b/tools/interface_generator/private/mypyrc
@@ -0,0 +1,2 @@
+[mypy]
+disable_error_code = import-untyped
diff --git a/tools/interface_generator/private/pylintrc b/tools/interface_generator/private/pylintrc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/interface_generator/private/pylintrc
diff --git a/tools/interface_generator/private/pytest_wrapper.py b/tools/interface_generator/private/pytest_wrapper.py
new file mode 100755
index 0000000..b4def3b
--- /dev/null
+++ b/tools/interface_generator/private/pytest_wrapper.py
@@ -0,0 +1,7 @@
+#!/usr/bin/env python3
+
+import sys
+import pytest
+
+if __name__ == "__main__":
+ sys.exit(pytest.main(sys.argv[1:]))
diff --git a/tools/interface_generator/requirements.txt b/tools/interface_generator/requirements.txt
new file mode 100644
index 0000000..c285e04
--- /dev/null
+++ b/tools/interface_generator/requirements.txt
@@ -0,0 +1,6 @@
+Mako==1.3.3
+MarkupSafe==2.1.5
+pytest==8.3.2
+pytest-black==0.3.12
+pytest-pylint==0.21.0
+pytest-mypy==0.10.3
diff --git a/tools/interface_generator/requirements_lock.txt b/tools/interface_generator/requirements_lock.txt
new file mode 100644
index 0000000..62c9eb4
--- /dev/null
+++ b/tools/interface_generator/requirements_lock.txt
@@ -0,0 +1,220 @@
+#
+# This file is autogenerated by pip-compile with Python 3.11
+# by the following command:
+#
+# bazel run //:requirements.update
+#
+astroid==3.2.4 \
+ --hash=sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a \
+ --hash=sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25
+ # via pylint
+attrs==24.2.0 \
+ --hash=sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346 \
+ --hash=sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2
+ # via pytest-mypy
+black==24.8.0 \
+ --hash=sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6 \
+ --hash=sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e \
+ --hash=sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f \
+ --hash=sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018 \
+ --hash=sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e \
+ --hash=sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd \
+ --hash=sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4 \
+ --hash=sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed \
+ --hash=sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2 \
+ --hash=sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42 \
+ --hash=sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af \
+ --hash=sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb \
+ --hash=sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368 \
+ --hash=sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb \
+ --hash=sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af \
+ --hash=sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed \
+ --hash=sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47 \
+ --hash=sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2 \
+ --hash=sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a \
+ --hash=sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c \
+ --hash=sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920 \
+ --hash=sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1
+ # via pytest-black
+click==8.1.7 \
+ --hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \
+ --hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de
+ # via black
+dill==0.3.8 \
+ --hash=sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca \
+ --hash=sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7
+ # via pylint
+filelock==3.15.4 \
+ --hash=sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb \
+ --hash=sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7
+ # via pytest-mypy
+iniconfig==2.0.0 \
+ --hash=sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3 \
+ --hash=sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374
+ # via pytest
+isort==5.13.2 \
+ --hash=sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109 \
+ --hash=sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6
+ # via pylint
+mako==1.3.3 \
+ --hash=sha256:5324b88089a8978bf76d1629774fcc2f1c07b82acdf00f4c5dd8ceadfffc4b40 \
+ --hash=sha256:e16c01d9ab9c11f7290eef1cfefc093fb5a45ee4a3da09e2fec2e4d1bae54e73
+ # via -r requirements.txt
+markupsafe==2.1.5 \
+ --hash=sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf \
+ --hash=sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff \
+ --hash=sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f \
+ --hash=sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3 \
+ --hash=sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532 \
+ --hash=sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f \
+ --hash=sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 \
+ --hash=sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df \
+ --hash=sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4 \
+ --hash=sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906 \
+ --hash=sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f \
+ --hash=sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 \
+ --hash=sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8 \
+ --hash=sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371 \
+ --hash=sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2 \
+ --hash=sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465 \
+ --hash=sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52 \
+ --hash=sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6 \
+ --hash=sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169 \
+ --hash=sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad \
+ --hash=sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 \
+ --hash=sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0 \
+ --hash=sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029 \
+ --hash=sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f \
+ --hash=sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a \
+ --hash=sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced \
+ --hash=sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5 \
+ --hash=sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c \
+ --hash=sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf \
+ --hash=sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9 \
+ --hash=sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb \
+ --hash=sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad \
+ --hash=sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3 \
+ --hash=sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 \
+ --hash=sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46 \
+ --hash=sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc \
+ --hash=sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a \
+ --hash=sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee \
+ --hash=sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900 \
+ --hash=sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 \
+ --hash=sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea \
+ --hash=sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f \
+ --hash=sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5 \
+ --hash=sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e \
+ --hash=sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a \
+ --hash=sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f \
+ --hash=sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50 \
+ --hash=sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a \
+ --hash=sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b \
+ --hash=sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4 \
+ --hash=sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff \
+ --hash=sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2 \
+ --hash=sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46 \
+ --hash=sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b \
+ --hash=sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf \
+ --hash=sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5 \
+ --hash=sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5 \
+ --hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \
+ --hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \
+ --hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68
+ # via
+ # -r requirements.txt
+ # mako
+mccabe==0.7.0 \
+ --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \
+ --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e
+ # via pylint
+mypy==1.11.1 \
+ --hash=sha256:0624bdb940255d2dd24e829d99a13cfeb72e4e9031f9492148f410ed30bcab54 \
+ --hash=sha256:0bc71d1fb27a428139dd78621953effe0d208aed9857cb08d002280b0422003a \
+ --hash=sha256:0bd53faf56de9643336aeea1c925012837432b5faf1701ccca7fde70166ccf72 \
+ --hash=sha256:11965c2f571ded6239977b14deebd3f4c3abd9a92398712d6da3a772974fad69 \
+ --hash=sha256:1a81cf05975fd61aec5ae16501a091cfb9f605dc3e3c878c0da32f250b74760b \
+ --hash=sha256:2684d3f693073ab89d76da8e3921883019ea8a3ec20fa5d8ecca6a2db4c54bbe \
+ --hash=sha256:2c63350af88f43a66d3dfeeeb8d77af34a4f07d760b9eb3a8697f0386c7590b4 \
+ --hash=sha256:45df906e8b6804ef4b666af29a87ad9f5921aad091c79cc38e12198e220beabd \
+ --hash=sha256:4c956b49c5d865394d62941b109728c5c596a415e9c5b2be663dd26a1ff07bc0 \
+ --hash=sha256:64f4a90e3ea07f590c5bcf9029035cf0efeae5ba8be511a8caada1a4893f5525 \
+ --hash=sha256:749fd3213916f1751fff995fccf20c6195cae941dc968f3aaadf9bb4e430e5a2 \
+ --hash=sha256:79c07eb282cb457473add5052b63925e5cc97dfab9812ee65a7c7ab5e3cb551c \
+ --hash=sha256:7b6343d338390bb946d449677726edf60102a1c96079b4f002dedff375953fc5 \
+ --hash=sha256:886c9dbecc87b9516eff294541bf7f3655722bf22bb898ee06985cd7269898de \
+ --hash=sha256:a2b43895a0f8154df6519706d9bca8280cda52d3d9d1514b2d9c3e26792a0b74 \
+ --hash=sha256:a32fc80b63de4b5b3e65f4be82b4cfa362a46702672aa6a0f443b4689af7008c \
+ --hash=sha256:a707ec1527ffcdd1c784d0924bf5cb15cd7f22683b919668a04d2b9c34549d2e \
+ --hash=sha256:a831671bad47186603872a3abc19634f3011d7f83b083762c942442d51c58d58 \
+ --hash=sha256:b639dce63a0b19085213ec5fdd8cffd1d81988f47a2dec7100e93564f3e8fb3b \
+ --hash=sha256:b868d3bcff720dd7217c383474008ddabaf048fad8d78ed948bb4b624870a417 \
+ --hash=sha256:c1952f5ea8a5a959b05ed5f16452fddadbaae48b5d39235ab4c3fc444d5fd411 \
+ --hash=sha256:d44be7551689d9d47b7abc27c71257adfdb53f03880841a5db15ddb22dc63edb \
+ --hash=sha256:e1e30dc3bfa4e157e53c1d17a0dad20f89dc433393e7702b813c10e200843b03 \
+ --hash=sha256:e4fe9f4e5e521b458d8feb52547f4bade7ef8c93238dfb5bbc790d9ff2d770ca \
+ --hash=sha256:f39918a50f74dc5969807dcfaecafa804fa7f90c9d60506835036cc1bc891dc8 \
+ --hash=sha256:f404a0b069709f18bbdb702eb3dcfe51910602995de00bd39cea3050b5772d08 \
+ --hash=sha256:fca4a60e1dd9fd0193ae0067eaeeb962f2d79e0d9f0f66223a0682f26ffcc809
+ # via pytest-mypy
+mypy-extensions==1.0.0 \
+ --hash=sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d \
+ --hash=sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782
+ # via
+ # black
+ # mypy
+packaging==24.1 \
+ --hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
+ --hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
+ # via
+ # black
+ # pytest
+pathspec==0.12.1 \
+ --hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \
+ --hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712
+ # via black
+platformdirs==4.2.2 \
+ --hash=sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee \
+ --hash=sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3
+ # via
+ # black
+ # pylint
+pluggy==1.5.0 \
+ --hash=sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1 \
+ --hash=sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669
+ # via pytest
+pylint==3.2.6 \
+ --hash=sha256:03c8e3baa1d9fb995b12c1dbe00aa6c4bcef210c2a2634374aedeb22fb4a8f8f \
+ --hash=sha256:a5d01678349454806cff6d886fb072294f56a58c4761278c97fb557d708e1eb3
+ # via pytest-pylint
+pytest==8.3.2 \
+ --hash=sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5 \
+ --hash=sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce
+ # via
+ # -r requirements.txt
+ # pytest-black
+ # pytest-mypy
+ # pytest-pylint
+pytest-black==0.3.12 \
+ --hash=sha256:1d339b004f764d6cd0f06e690f6dd748df3d62e6fe1a692d6a5500ac2c5b75a5
+ # via -r requirements.txt
+pytest-mypy==0.10.3 \
+ --hash=sha256:7638d0d3906848fc1810cb2f5cc7fceb4cc5c98524aafcac58f28620e3102053 \
+ --hash=sha256:f8458f642323f13a2ca3e2e61509f7767966b527b4d8adccd5032c3e7b4fd3db
+ # via -r requirements.txt
+pytest-pylint==0.21.0 \
+ --hash=sha256:88764b8e1d5cfa18809248e0ccc2fc05035f08c35f0b0222ddcfea1c3c4e553e \
+ --hash=sha256:f10d9eaa72b9fbe624ee4b55da0481f56482eee0a467afc1ee3ae8b1fefbd0b4
+ # via -r requirements.txt
+toml==0.10.2 \
+ --hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \
+ --hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f
+ # via pytest-black
+tomlkit==0.13.0 \
+ --hash=sha256:08ad192699734149f5b97b45f1f18dad7eb1b6d16bc72ad0c2335772650d7b72 \
+ --hash=sha256:7075d3042d03b80f603482d69bf0c8f345c2b30e41699fd8883227f89972b264
+ # via pylint
+typing-extensions==4.12.2 \
+ --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \
+ --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8
+ # via mypy
diff --git a/tools/interface_generator/test/BUILD.bazel b/tools/interface_generator/test/BUILD.bazel
new file mode 100644
index 0000000..2166c4e
--- /dev/null
+++ b/tools/interface_generator/test/BUILD.bazel
@@ -0,0 +1,24 @@
+load("//:defs.bzl", "generate_interface")
+
+generate_interface(
+ name = "kstdio",
+ interface = "kstdio",
+ license = "//:LICENSE.md",
+ visibility = ["//visibility:private"],
+)
+
+cc_library(
+ name = "kstdio_mock",
+ srcs = ["kstdio_mock.cpp"],
+ deps = [
+ ":kstdio",
+ "@googletest//:gtest",
+ "@googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "test_kstdio",
+ srcs = ["test_kstdio.cpp"],
+ deps = [":kstdio_mock"],
+)
diff --git a/tools/interface_generator/test/test_kstdio.cpp b/tools/interface_generator/test/test_kstdio.cpp
new file mode 100644
index 0000000..95540a4
--- /dev/null
+++ b/tools/interface_generator/test/test_kstdio.cpp
@@ -0,0 +1,20 @@
+#include "kstdio_mock.hpp"
+
+using ::testing::StrEq;
+
+class kstdioFixture : public ::testing::Test {
+protected:
+ void
+ SetUp()
+ {
+ }
+
+ kstdio_mock m_kstdio_mock;
+};
+
+TEST_F(kstdioFixture, printfCallsMock)
+{
+ EXPECT_CALL(m_kstdio_mock, printf(StrEq("hello world")));
+
+ kstdio_printf("hello world");
+}
diff --git a/tools/kconfig/.gitignore b/tools/kconfig/.gitignore
deleted file mode 100644
index 22c5c61..0000000
--- a/tools/kconfig/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# generated files
-parser.tab.h
-parser.tab.c
-lex.yy.c
-
-# binaries
-conf
-mconf
diff --git a/tools/kconfig/Makefile b/tools/kconfig/Makefile
deleted file mode 100644
index b7dd104..0000000
--- a/tools/kconfig/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-include ../../Makefile.config
-
-HOSTTARGETBIN += conf mconf
-
-lxdiag_srcs := \
- lxdialog/checklist.c lxdialog/inputbox.c lxdialog/menubox.c lxdialog/textbox.c lxdialog/util.c lxdialog/yesno.c
-
-parser_srcs := \
- confdata.c expr.c menu.c preprocess.c symbol.c util.c \
- lex.yy.c parser.tab.c
-
-conf.SRCS := ${parser_srcs} conf.c
-
-mconf.SRCS := ${parser_srcs} ${lxdiag_srcs} mconf.c
-
-HOST_CFLAGS := -D_GNU_SOURCE $(shell pkg-config --cflags ncursesw)
-HOST_LDFLAGS := $(shell pkg-config --libs ncursesw)
-
-include ../../rules.mk
-
-%.tab.c: %.y
- bison --header --debug $<
-
-lex.yy.c: lexer.l parser.tab.c
- flex $<
-
-clean: clean.base
- @rm -f parser.tab.h parser.tab.c lex.yy.c
diff --git a/tools/kconfig/README.md b/tools/kconfig/README.md
deleted file mode 100644
index 0c3f693..0000000
--- a/tools/kconfig/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-## kconfig
-
-Description: extracted from the linux kernel
-
-source: https://kernel.org/
-
-commit: 0988a0ea791999ebbf95693f2676381825b05033
-
-path: scripts/kconfig
diff --git a/tools/kconfig/conf.c b/tools/kconfig/conf.c
deleted file mode 100644
index 33d19e4..0000000
--- a/tools/kconfig/conf.c
+++ /dev/null
@@ -1,921 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- */
-
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <sys/time.h>
-#include <errno.h>
-
-#include "lkc.h"
-
-static void conf(struct menu *menu);
-static void check_conf(struct menu *menu);
-
-enum input_mode {
- oldaskconfig,
- syncconfig,
- oldconfig,
- allnoconfig,
- allyesconfig,
- allmodconfig,
- alldefconfig,
- randconfig,
- defconfig,
- savedefconfig,
- listnewconfig,
- helpnewconfig,
- olddefconfig,
- yes2modconfig,
- mod2yesconfig,
- mod2noconfig,
-};
-static enum input_mode input_mode = oldaskconfig;
-static int input_mode_opt;
-static int indent = 1;
-static int tty_stdio;
-static int sync_kconfig;
-static int conf_cnt;
-static char line[PATH_MAX];
-static struct menu *rootEntry;
-
-static void print_help(struct menu *menu)
-{
- struct gstr help = str_new();
-
- menu_get_ext_help(menu, &help);
-
- printf("\n%s\n", str_get(&help));
- str_free(&help);
-}
-
-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;
-}
-
-/* Helper function to facilitate fgets() by Jean Sacren. */
-static void xfgets(char *str, int size, FILE *in)
-{
- if (!fgets(str, size, in))
- fprintf(stderr, "\nError in reading or end of file.\n");
-
- if (!tty_stdio)
- printf("%s", str);
-}
-
-static void set_randconfig_seed(void)
-{
- unsigned int seed;
- char *env;
- bool seed_set = false;
-
- env = getenv("KCONFIG_SEED");
- if (env && *env) {
- char *endp;
-
- seed = strtol(env, &endp, 0);
- if (*endp == '\0')
- seed_set = true;
- }
-
- if (!seed_set) {
- struct timeval now;
-
- /*
- * Use microseconds derived seed, compensate for systems where it may
- * be zero.
- */
- gettimeofday(&now, NULL);
- seed = (now.tv_sec + 1) * (now.tv_usec + 1);
- }
-
- printf("KCONFIG_SEED=0x%X\n", seed);
- srand(seed);
-}
-
-static bool randomize_choice_values(struct symbol *csym)
-{
- struct property *prop;
- struct symbol *sym;
- struct expr *e;
- int cnt, def;
-
- /*
- * If choice is mod then we may have more items selected
- * and if no then no-one.
- * In both cases stop.
- */
- if (csym->curr.tri != yes)
- return false;
-
- prop = sym_get_choice_prop(csym);
-
- /* count entries in choice block */
- cnt = 0;
- expr_list_for_each_sym(prop->expr, e, sym)
- cnt++;
-
- /*
- * find a random value and set it to yes,
- * set the rest to no so we have only one set
- */
- def = rand() % cnt;
-
- cnt = 0;
- expr_list_for_each_sym(prop->expr, e, sym) {
- if (def == cnt++) {
- sym->def[S_DEF_USER].tri = yes;
- csym->def[S_DEF_USER].val = sym;
- } else {
- sym->def[S_DEF_USER].tri = no;
- }
- sym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- sym->flags &= ~SYMBOL_VALID;
- }
- csym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- csym->flags &= ~SYMBOL_VALID;
-
- return true;
-}
-
-enum conf_def_mode {
- def_default,
- def_yes,
- def_mod,
- def_no,
- def_random
-};
-
-static bool conf_set_all_new_symbols(enum conf_def_mode mode)
-{
- struct symbol *sym, *csym;
- int i, cnt;
- /*
- * can't go as the default in switch-case below, otherwise gcc whines
- * about -Wmaybe-uninitialized
- */
- int pby = 50; /* probability of bool = y */
- int pty = 33; /* probability of tristate = y */
- int ptm = 33; /* probability of tristate = m */
- bool has_changed = false;
-
- if (mode == def_random) {
- int n, p[3];
- char *env = getenv("KCONFIG_PROBABILITY");
-
- n = 0;
- while (env && *env) {
- char *endp;
- int tmp = strtol(env, &endp, 10);
-
- if (tmp >= 0 && tmp <= 100) {
- p[n++] = tmp;
- } else {
- errno = ERANGE;
- perror("KCONFIG_PROBABILITY");
- exit(1);
- }
- env = (*endp == ':') ? endp + 1 : endp;
- if (n >= 3)
- break;
- }
- switch (n) {
- case 1:
- pby = p[0];
- ptm = pby / 2;
- pty = pby - ptm;
- break;
- case 2:
- pty = p[0];
- ptm = p[1];
- pby = pty + ptm;
- break;
- case 3:
- pby = p[0];
- pty = p[1];
- ptm = p[2];
- break;
- }
-
- if (pty + ptm > 100) {
- errno = ERANGE;
- perror("KCONFIG_PROBABILITY");
- exit(1);
- }
- }
-
- for_all_symbols(i, sym) {
- if (sym_has_value(sym) || sym->flags & SYMBOL_VALID)
- continue;
- switch (sym_get_type(sym)) {
- case S_BOOLEAN:
- case S_TRISTATE:
- has_changed = true;
- switch (mode) {
- case def_yes:
- sym->def[S_DEF_USER].tri = yes;
- break;
- case def_mod:
- sym->def[S_DEF_USER].tri = mod;
- break;
- case def_no:
- sym->def[S_DEF_USER].tri = no;
- break;
- case def_random:
- sym->def[S_DEF_USER].tri = no;
- cnt = rand() % 100;
- if (sym->type == S_TRISTATE) {
- if (cnt < pty)
- sym->def[S_DEF_USER].tri = yes;
- else if (cnt < pty + ptm)
- sym->def[S_DEF_USER].tri = mod;
- } else if (cnt < pby)
- sym->def[S_DEF_USER].tri = yes;
- break;
- default:
- continue;
- }
- if (!(sym_is_choice(sym) && mode == def_random))
- sym->flags |= SYMBOL_DEF_USER;
- break;
- default:
- break;
- }
-
- }
-
- sym_clear_all_valid();
-
- /*
- * We have different type of choice blocks.
- * If curr.tri equals to mod then we can select several
- * choice symbols in one block.
- * In this case we do nothing.
- * If curr.tri equals yes then only one symbol can be
- * selected in a choice block and we set it to yes,
- * and the rest to no.
- */
- if (mode != def_random) {
- for_all_symbols(i, csym) {
- if ((sym_is_choice(csym) && !sym_has_value(csym)) ||
- sym_is_choice_value(csym))
- csym->flags |= SYMBOL_NEED_SET_CHOICE_VALUES;
- }
- }
-
- for_all_symbols(i, csym) {
- if (sym_has_value(csym) || !sym_is_choice(csym))
- continue;
-
- sym_calc_value(csym);
- if (mode == def_random)
- has_changed |= randomize_choice_values(csym);
- else {
- set_all_choice_values(csym);
- has_changed = true;
- }
- }
-
- return has_changed;
-}
-
-static void conf_rewrite_tristates(tristate old_val, tristate new_val)
-{
- struct symbol *sym;
- int i;
-
- for_all_symbols(i, sym) {
- if (sym_get_type(sym) == S_TRISTATE &&
- sym->def[S_DEF_USER].tri == old_val)
- sym->def[S_DEF_USER].tri = new_val;
- }
- sym_clear_all_valid();
-}
-
-static int conf_askvalue(struct symbol *sym, const char *def)
-{
- if (!sym_has_value(sym))
- printf("(NEW) ");
-
- line[0] = '\n';
- line[1] = 0;
-
- if (!sym_is_changeable(sym)) {
- printf("%s\n", def);
- line[0] = '\n';
- line[1] = 0;
- return 0;
- }
-
- switch (input_mode) {
- case oldconfig:
- case syncconfig:
- if (sym_has_value(sym)) {
- printf("%s\n", def);
- return 0;
- }
- /* fall through */
- default:
- fflush(stdout);
- xfgets(line, sizeof(line), stdin);
- break;
- }
-
- return 1;
-}
-
-static int conf_string(struct menu *menu)
-{
- struct symbol *sym = menu->sym;
- const char *def;
-
- while (1) {
- printf("%*s%s ", indent - 1, "", menu->prompt->text);
- printf("(%s) ", sym->name);
- def = sym_get_string_value(sym);
- if (def)
- printf("[%s] ", def);
- if (!conf_askvalue(sym, def))
- return 0;
- switch (line[0]) {
- case '\n':
- break;
- case '?':
- /* print help */
- if (line[1] == '\n') {
- print_help(menu);
- def = NULL;
- break;
- }
- /* fall through */
- 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;
-
- while (1) {
- printf("%*s%s ", indent - 1, "", menu->prompt->text);
- if (sym->name)
- printf("(%s) ", sym->name);
- 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");
- printf("/?] ");
- if (!conf_askvalue(sym, sym_get_string_value(sym)))
- return 0;
- 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:
- print_help(menu);
- }
-}
-
-static int conf_choice(struct menu *menu)
-{
- struct symbol *sym, *def_sym;
- struct menu *child;
- bool is_new;
-
- sym = menu->sym;
- is_new = !sym_has_value(sym);
- if (sym_is_changeable(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;
- 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);
- switch (input_mode) {
- case oldconfig:
- case syncconfig:
- if (!is_new) {
- cnt = def;
- printf("%d\n", cnt);
- break;
- }
- /* fall through */
- case oldaskconfig:
- fflush(stdout);
- xfgets(line, sizeof(line), stdin);
- strip(line);
- if (line[0] == '?') {
- print_help(menu);
- continue;
- }
- if (!line[0])
- cnt = def;
- else if (isdigit(line[0]))
- cnt = atoi(line);
- else
- continue;
- break;
- default:
- 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[0] && line[strlen(line) - 1] == '?') {
- print_help(child);
- continue;
- }
- sym_set_tristate_value(child->sym, yes);
- for (child = child->list; child; child = child->next) {
- indent += 2;
- conf(child);
- 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:
- /*
- * Except in oldaskconfig mode, we show only menus that
- * contain new symbols.
- */
- if (input_mode != oldaskconfig && rootEntry != menu) {
- check_conf(menu);
- return;
- }
- /* fall through */
- 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 && !sym_has_value(sym) &&
- (sym_is_changeable(sym) ||
- (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes))) {
-
- switch (input_mode) {
- case listnewconfig:
- if (sym->name)
- print_symbol_for_listconfig(sym);
- break;
- case helpnewconfig:
- printf("-----\n");
- print_help(menu);
- printf("-----\n");
- break;
- default:
- if (!conf_cnt++)
- printf("*\n* Restart config...\n*\n");
- rootEntry = menu_get_parent_menu(menu);
- conf(rootEntry);
- break;
- }
- }
-
- for (child = menu->list; child; child = child->next)
- check_conf(child);
-}
-
-static const struct option long_opts[] = {
- {"help", no_argument, NULL, 'h'},
- {"silent", no_argument, NULL, 's'},
- {"oldaskconfig", no_argument, &input_mode_opt, oldaskconfig},
- {"oldconfig", no_argument, &input_mode_opt, oldconfig},
- {"syncconfig", no_argument, &input_mode_opt, syncconfig},
- {"defconfig", required_argument, &input_mode_opt, defconfig},
- {"savedefconfig", required_argument, &input_mode_opt, savedefconfig},
- {"allnoconfig", no_argument, &input_mode_opt, allnoconfig},
- {"allyesconfig", no_argument, &input_mode_opt, allyesconfig},
- {"allmodconfig", no_argument, &input_mode_opt, allmodconfig},
- {"alldefconfig", no_argument, &input_mode_opt, alldefconfig},
- {"randconfig", no_argument, &input_mode_opt, randconfig},
- {"listnewconfig", no_argument, &input_mode_opt, listnewconfig},
- {"helpnewconfig", no_argument, &input_mode_opt, helpnewconfig},
- {"olddefconfig", no_argument, &input_mode_opt, olddefconfig},
- {"yes2modconfig", no_argument, &input_mode_opt, yes2modconfig},
- {"mod2yesconfig", no_argument, &input_mode_opt, mod2yesconfig},
- {"mod2noconfig", no_argument, &input_mode_opt, mod2noconfig},
- {NULL, 0, NULL, 0}
-};
-
-static void conf_usage(const char *progname)
-{
- printf("Usage: %s [options] <kconfig-file>\n", progname);
- printf("\n");
- printf("Generic options:\n");
- printf(" -h, --help Print this message and exit.\n");
- printf(" -s, --silent Do not print log.\n");
- printf("\n");
- printf("Mode options:\n");
- printf(" --listnewconfig List new options\n");
- printf(" --helpnewconfig List new options and help text\n");
- printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
- printf(" --oldconfig Update a configuration using a provided .config as base\n");
- printf(" --syncconfig Similar to oldconfig but generates configuration in\n"
- " include/{generated/,config/}\n");
- printf(" --olddefconfig Same as oldconfig but sets new symbols to their default value\n");
- printf(" --defconfig <file> New config with default defined in <file>\n");
- printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
- printf(" --allnoconfig New config where all options are answered with no\n");
- printf(" --allyesconfig New config where all options are answered with yes\n");
- printf(" --allmodconfig New config where all options are answered with mod\n");
- printf(" --alldefconfig New config with all symbols set to default\n");
- printf(" --randconfig New config with random answer to all options\n");
- printf(" --yes2modconfig Change answers from yes to mod if possible\n");
- printf(" --mod2yesconfig Change answers from mod to yes if possible\n");
- printf(" --mod2noconfig Change answers from mod to no if possible\n");
- printf(" (If none of the above is given, --oldaskconfig is the default)\n");
-}
-
-int main(int ac, char **av)
-{
- const char *progname = av[0];
- int opt;
- const char *name, *defconfig_file = NULL /* gcc uninit */;
- int no_conf_write = 0;
-
- tty_stdio = isatty(0) && isatty(1);
-
- while ((opt = getopt_long(ac, av, "hs", long_opts, NULL)) != -1) {
- switch (opt) {
- case 'h':
- conf_usage(progname);
- exit(1);
- break;
- case 's':
- conf_set_message_callback(NULL);
- break;
- case 0:
- input_mode = input_mode_opt;
- switch (input_mode) {
- case syncconfig:
- /*
- * syncconfig is invoked during the build stage.
- * Suppress distracting
- * "configuration written to ..."
- */
- conf_set_message_callback(NULL);
- sync_kconfig = 1;
- break;
- case defconfig:
- case savedefconfig:
- defconfig_file = optarg;
- break;
- case randconfig:
- set_randconfig_seed();
- break;
- default:
- break;
- }
- default:
- break;
- }
- }
- if (ac == optind) {
- fprintf(stderr, "%s: Kconfig file missing\n", av[0]);
- conf_usage(progname);
- exit(1);
- }
- conf_parse(av[optind]);
- //zconfdump(stdout);
-
- switch (input_mode) {
- case defconfig:
- if (conf_read(defconfig_file)) {
- fprintf(stderr,
- "***\n"
- "*** Can't find default configuration \"%s\"!\n"
- "***\n",
- defconfig_file);
- exit(1);
- }
- break;
- case savedefconfig:
- case syncconfig:
- case oldaskconfig:
- case oldconfig:
- case listnewconfig:
- case helpnewconfig:
- case olddefconfig:
- case yes2modconfig:
- case mod2yesconfig:
- case mod2noconfig:
- conf_read(NULL);
- break;
- case allnoconfig:
- case allyesconfig:
- case allmodconfig:
- case alldefconfig:
- case randconfig:
- name = getenv("KCONFIG_ALLCONFIG");
- if (!name)
- break;
- if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
- if (conf_read_simple(name, S_DEF_USER)) {
- fprintf(stderr,
- "*** Can't read seed configuration \"%s\"!\n",
- name);
- exit(1);
- }
- break;
- }
- switch (input_mode) {
- case allnoconfig: name = "allno.config"; break;
- case allyesconfig: name = "allyes.config"; break;
- case allmodconfig: name = "allmod.config"; break;
- case alldefconfig: name = "alldef.config"; break;
- case randconfig: name = "allrandom.config"; break;
- default: break;
- }
- if (conf_read_simple(name, S_DEF_USER) &&
- conf_read_simple("all.config", S_DEF_USER)) {
- fprintf(stderr,
- "*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n",
- name);
- exit(1);
- }
- break;
- default:
- break;
- }
-
- if (sync_kconfig) {
- name = getenv("KCONFIG_NOSILENTUPDATE");
- if (name && *name) {
- if (conf_get_changed()) {
- fprintf(stderr,
- "\n*** The configuration requires explicit update.\n\n");
- return 1;
- }
- no_conf_write = 1;
- }
- }
-
- switch (input_mode) {
- case allnoconfig:
- conf_set_all_new_symbols(def_no);
- break;
- case allyesconfig:
- conf_set_all_new_symbols(def_yes);
- break;
- case allmodconfig:
- conf_set_all_new_symbols(def_mod);
- break;
- case alldefconfig:
- conf_set_all_new_symbols(def_default);
- break;
- case randconfig:
- /* Really nothing to do in this loop */
- while (conf_set_all_new_symbols(def_random)) ;
- break;
- case defconfig:
- conf_set_all_new_symbols(def_default);
- break;
- case savedefconfig:
- break;
- case yes2modconfig:
- conf_rewrite_tristates(yes, mod);
- break;
- case mod2yesconfig:
- conf_rewrite_tristates(mod, yes);
- break;
- case mod2noconfig:
- conf_rewrite_tristates(mod, no);
- break;
- case oldaskconfig:
- rootEntry = &rootmenu;
- conf(&rootmenu);
- input_mode = oldconfig;
- /* fall through */
- case oldconfig:
- case listnewconfig:
- case helpnewconfig:
- case syncconfig:
- /* Update until a loop caused no more changes */
- do {
- conf_cnt = 0;
- check_conf(&rootmenu);
- } while (conf_cnt);
- break;
- case olddefconfig:
- default:
- break;
- }
-
- if (input_mode == savedefconfig) {
- if (conf_write_defconfig(defconfig_file)) {
- fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
- defconfig_file);
- return 1;
- }
- } else if (input_mode != listnewconfig && input_mode != helpnewconfig) {
- if (!no_conf_write && conf_write(NULL)) {
- fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
- exit(1);
- }
-
- /*
- * Create auto.conf if it does not exist.
- * This prevents GNU Make 4.1 or older from emitting
- * "include/config/auto.conf: No such file or directory"
- * in the top-level Makefile
- *
- * syncconfig always creates or updates auto.conf because it is
- * used during the build.
- */
- if (conf_write_autoconf(sync_kconfig) && sync_kconfig) {
- fprintf(stderr,
- "\n*** Error during sync of the configuration.\n\n");
- return 1;
- }
- }
- return 0;
-}
diff --git a/tools/kconfig/confdata.c b/tools/kconfig/confdata.c
deleted file mode 100644
index b7c9f1d..0000000
--- a/tools/kconfig/confdata.c
+++ /dev/null
@@ -1,1263 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- */
-
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "lkc.h"
-
-/* return true if 'path' exists, false otherwise */
-static bool is_present(const char *path)
-{
- struct stat st;
-
- return !stat(path, &st);
-}
-
-/* return true if 'path' exists and it is a directory, false otherwise */
-static bool is_dir(const char *path)
-{
- struct stat st;
-
- if (stat(path, &st))
- return false;
-
- return S_ISDIR(st.st_mode);
-}
-
-/* return true if the given two files are the same, false otherwise */
-static bool is_same(const char *file1, const char *file2)
-{
- int fd1, fd2;
- struct stat st1, st2;
- void *map1, *map2;
- bool ret = false;
-
- fd1 = open(file1, O_RDONLY);
- if (fd1 < 0)
- return ret;
-
- fd2 = open(file2, O_RDONLY);
- if (fd2 < 0)
- goto close1;
-
- ret = fstat(fd1, &st1);
- if (ret)
- goto close2;
- ret = fstat(fd2, &st2);
- if (ret)
- goto close2;
-
- if (st1.st_size != st2.st_size)
- goto close2;
-
- map1 = mmap(NULL, st1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
- if (map1 == MAP_FAILED)
- goto close2;
-
- map2 = mmap(NULL, st2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);
- if (map2 == MAP_FAILED)
- goto close2;
-
- if (bcmp(map1, map2, st1.st_size))
- goto close2;
-
- ret = true;
-close2:
- close(fd2);
-close1:
- close(fd1);
-
- return ret;
-}
-
-/*
- * Create the parent directory of the given path.
- *
- * For example, if 'include/config/auto.conf' is given, create 'include/config'.
- */
-static int make_parent_dir(const char *path)
-{
- char tmp[PATH_MAX + 1];
- char *p;
-
- strncpy(tmp, path, sizeof(tmp));
- tmp[sizeof(tmp) - 1] = 0;
-
- /* Remove the base name. Just return if nothing is left */
- p = strrchr(tmp, '/');
- if (!p)
- return 0;
- *(p + 1) = 0;
-
- /* Just in case it is an absolute path */
- p = tmp;
- while (*p == '/')
- p++;
-
- while ((p = strchr(p, '/'))) {
- *p = 0;
-
- /* skip if the directory exists */
- if (!is_dir(tmp) && mkdir(tmp, 0755))
- return -1;
-
- *p = '/';
- while (*p == '/')
- p++;
- }
-
- return 0;
-}
-
-static char depfile_path[PATH_MAX];
-static size_t depfile_prefix_len;
-
-/* touch depfile for symbol 'name' */
-static int conf_touch_dep(const char *name)
-{
- int fd;
-
- /* check overflow: prefix + name + '\0' must fit in buffer. */
- if (depfile_prefix_len + strlen(name) + 1 > sizeof(depfile_path))
- return -1;
-
- strcpy(depfile_path + depfile_prefix_len, name);
-
- fd = open(depfile_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (fd == -1)
- return -1;
- close(fd);
-
- return 0;
-}
-
-static void conf_warning(const char *fmt, ...)
- __attribute__ ((format (printf, 1, 2)));
-
-static void conf_message(const char *fmt, ...)
- __attribute__ ((format (printf, 1, 2)));
-
-static const char *conf_filename;
-static int conf_lineno, conf_warnings;
-
-static void conf_warning(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- conf_warnings++;
-}
-
-static void conf_default_message_callback(const char *s)
-{
- printf("#\n# ");
- printf("%s", s);
- printf("\n#\n");
-}
-
-static void (*conf_message_callback)(const char *s) =
- conf_default_message_callback;
-void conf_set_message_callback(void (*fn)(const char *s))
-{
- conf_message_callback = fn;
-}
-
-static void conf_message(const char *fmt, ...)
-{
- va_list ap;
- char buf[4096];
-
- if (!conf_message_callback)
- return;
-
- va_start(ap, fmt);
-
- vsnprintf(buf, sizeof(buf), fmt, ap);
- conf_message_callback(buf);
- va_end(ap);
-}
-
-const char *conf_get_configname(void)
-{
- char *name = getenv("KCONFIG_CONFIG");
-
- return name ? name : ".config";
-}
-
-static const char *conf_get_autoconfig_name(void)
-{
- char *name = getenv("KCONFIG_AUTOCONFIG");
-
- return name ? name : "include/config/auto.conf";
-}
-
-static const char *conf_get_autoheader_name(void)
-{
- char *name = getenv("KCONFIG_AUTOHEADER");
-
- return name ? name : "include/generated/autoconf.h";
-}
-
-static const char *conf_get_rustccfg_name(void)
-{
- char *name = getenv("KCONFIG_RUSTCCFG");
-
- return name ? name : "include/generated/rustc_cfg";
-}
-
-static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
-{
- char *p2;
-
- switch (sym->type) {
- case S_TRISTATE:
- if (p[0] == 'm') {
- sym->def[def].tri = mod;
- sym->flags |= def_flags;
- break;
- }
- /* fall through */
- case S_BOOLEAN:
- if (p[0] == 'y') {
- sym->def[def].tri = yes;
- sym->flags |= def_flags;
- break;
- }
- if (p[0] == 'n') {
- sym->def[def].tri = no;
- sym->flags |= def_flags;
- break;
- }
- if (def != S_DEF_AUTO)
- conf_warning("symbol value '%s' invalid for %s",
- p, sym->name);
- return 1;
- case S_STRING:
- /* No escaping for S_DEF_AUTO (include/config/auto.conf) */
- if (def != S_DEF_AUTO) {
- if (*p++ != '"')
- break;
- for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
- if (*p2 == '"') {
- *p2 = 0;
- break;
- }
- memmove(p2, p2 + 1, strlen(p2));
- }
- if (!p2) {
- conf_warning("invalid string found");
- return 1;
- }
- }
- /* fall through */
- case S_INT:
- case S_HEX:
- if (sym_string_valid(sym, p)) {
- sym->def[def].val = xstrdup(p);
- sym->flags |= def_flags;
- } else {
- if (def != S_DEF_AUTO)
- conf_warning("symbol value '%s' invalid for %s",
- p, sym->name);
- return 1;
- }
- break;
- default:
- ;
- }
- return 0;
-}
-
-#define LINE_GROWTH 16
-static int add_byte(int c, char **lineptr, size_t slen, size_t *n)
-{
- char *nline;
- size_t new_size = slen + 1;
- if (new_size > *n) {
- new_size += LINE_GROWTH - 1;
- new_size *= 2;
- nline = xrealloc(*lineptr, new_size);
- if (!nline)
- return -1;
-
- *lineptr = nline;
- *n = new_size;
- }
-
- (*lineptr)[slen] = c;
-
- return 0;
-}
-
-static ssize_t compat_getline(char **lineptr, size_t *n, FILE *stream)
-{
- char *line = *lineptr;
- size_t slen = 0;
-
- for (;;) {
- int c = getc(stream);
-
- switch (c) {
- case '\n':
- if (add_byte(c, &line, slen, n) < 0)
- goto e_out;
- slen++;
- /* fall through */
- case EOF:
- if (add_byte('\0', &line, slen, n) < 0)
- goto e_out;
- *lineptr = line;
- if (slen == 0)
- return -1;
- return slen;
- default:
- if (add_byte(c, &line, slen, n) < 0)
- goto e_out;
- slen++;
- }
- }
-
-e_out:
- line[slen-1] = '\0';
- *lineptr = line;
- return -1;
-}
-
-int conf_read_simple(const char *name, int def)
-{
- FILE *in = NULL;
- char *line = NULL;
- size_t line_asize = 0;
- char *p, *p2;
- struct symbol *sym;
- int i, def_flags;
-
- if (name) {
- in = zconf_fopen(name);
- } else {
- char *env;
-
- name = conf_get_configname();
- in = zconf_fopen(name);
- if (in)
- goto load;
- conf_set_changed(true);
-
- env = getenv("KCONFIG_DEFCONFIG_LIST");
- if (!env)
- return 1;
-
- while (1) {
- bool is_last;
-
- while (isspace(*env))
- env++;
-
- if (!*env)
- break;
-
- p = env;
- while (*p && !isspace(*p))
- p++;
-
- is_last = (*p == '\0');
-
- *p = '\0';
-
- in = zconf_fopen(env);
- if (in) {
- conf_message("using defaults found in %s",
- env);
- goto load;
- }
-
- if (is_last)
- break;
-
- env = p + 1;
- }
- }
- if (!in)
- return 1;
-
-load:
- conf_filename = name;
- conf_lineno = 0;
- conf_warnings = 0;
-
- def_flags = SYMBOL_DEF << def;
- for_all_symbols(i, sym) {
- sym->flags |= SYMBOL_CHANGED;
- sym->flags &= ~(def_flags|SYMBOL_VALID);
- if (sym_is_choice(sym))
- sym->flags |= def_flags;
- switch (sym->type) {
- case S_INT:
- case S_HEX:
- case S_STRING:
- if (sym->def[def].val)
- free(sym->def[def].val);
- /* fall through */
- default:
- sym->def[def].val = NULL;
- sym->def[def].tri = no;
- }
- }
-
- while (compat_getline(&line, &line_asize, in) != -1) {
- conf_lineno++;
- sym = NULL;
- if (line[0] == '#') {
- if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
- continue;
- p = strchr(line + 2 + strlen(CONFIG_), ' ');
- if (!p)
- continue;
- *p++ = 0;
- if (strncmp(p, "is not set", 10))
- continue;
- if (def == S_DEF_USER) {
- sym = sym_find(line + 2 + strlen(CONFIG_));
- if (!sym) {
- conf_set_changed(true);
- continue;
- }
- } else {
- sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
- if (sym->type == S_UNKNOWN)
- sym->type = S_BOOLEAN;
- }
- if (sym->flags & def_flags) {
- conf_warning("override: reassigning to symbol %s", sym->name);
- }
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- sym->def[def].tri = no;
- sym->flags |= def_flags;
- break;
- default:
- ;
- }
- } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
- p = strchr(line + strlen(CONFIG_), '=');
- if (!p)
- continue;
- *p++ = 0;
- p2 = strchr(p, '\n');
- if (p2) {
- *p2-- = 0;
- if (*p2 == '\r')
- *p2 = 0;
- }
-
- sym = sym_find(line + strlen(CONFIG_));
- if (!sym) {
- if (def == S_DEF_AUTO)
- /*
- * Reading from include/config/auto.conf
- * If CONFIG_FOO previously existed in
- * auto.conf but it is missing now,
- * include/config/FOO must be touched.
- */
- conf_touch_dep(line + strlen(CONFIG_));
- else
- conf_set_changed(true);
- continue;
- }
-
- if (sym->flags & def_flags) {
- conf_warning("override: reassigning to symbol %s", sym->name);
- }
- if (conf_set_sym_val(sym, def, def_flags, p))
- continue;
- } else {
- if (line[0] != '\r' && line[0] != '\n')
- conf_warning("unexpected data: %.*s",
- (int)strcspn(line, "\r\n"), line);
-
- continue;
- }
-
- if (sym && sym_is_choice_value(sym)) {
- struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
- switch (sym->def[def].tri) {
- case no:
- break;
- case mod:
- if (cs->def[def].tri == yes) {
- conf_warning("%s creates inconsistent choice state", sym->name);
- cs->flags &= ~def_flags;
- }
- break;
- case yes:
- if (cs->def[def].tri != no)
- conf_warning("override: %s changes choice state", sym->name);
- cs->def[def].val = sym;
- break;
- }
- cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri);
- }
- }
- free(line);
- fclose(in);
- return 0;
-}
-
-int conf_read(const char *name)
-{
- struct symbol *sym;
- int conf_unsaved = 0;
- int i;
-
- conf_set_changed(false);
-
- if (conf_read_simple(name, S_DEF_USER)) {
- sym_calc_value(modules_sym);
- return 1;
- }
-
- sym_calc_value(modules_sym);
-
- for_all_symbols(i, sym) {
- sym_calc_value(sym);
- if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))
- continue;
- if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
- /* check that calculated value agrees with saved value */
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- if (sym->def[S_DEF_USER].tri == sym_get_tristate_value(sym))
- continue;
- break;
- default:
- if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
- continue;
- break;
- }
- } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE))
- /* no previous value and not saved */
- continue;
- conf_unsaved++;
- /* maybe print value in verbose mode... */
- }
-
- for_all_symbols(i, sym) {
- if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
- /* Reset values of generates values, so they'll appear
- * as new, if they should become visible, but that
- * doesn't quite work if the Kconfig and the saved
- * configuration disagree.
- */
- if (sym->visible == no && !conf_unsaved)
- sym->flags &= ~SYMBOL_DEF_USER;
- switch (sym->type) {
- case S_STRING:
- case S_INT:
- case S_HEX:
- /* Reset a string value if it's out of range */
- if (sym_string_within_range(sym, sym->def[S_DEF_USER].val))
- break;
- sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
- conf_unsaved++;
- break;
- default:
- break;
- }
- }
- }
-
- if (conf_warnings || conf_unsaved)
- conf_set_changed(true);
-
- return 0;
-}
-
-struct comment_style {
- const char *decoration;
- const char *prefix;
- const char *postfix;
-};
-
-static const struct comment_style comment_style_pound = {
- .decoration = "#",
- .prefix = "#",
- .postfix = "#",
-};
-
-static const struct comment_style comment_style_c = {
- .decoration = " *",
- .prefix = "/*",
- .postfix = " */",
-};
-
-static void conf_write_heading(FILE *fp, const struct comment_style *cs)
-{
- if (!cs)
- return;
-
- fprintf(fp, "%s\n", cs->prefix);
-
- fprintf(fp, "%s Automatically generated file; DO NOT EDIT.\n",
- cs->decoration);
-
- fprintf(fp, "%s %s\n", cs->decoration, rootmenu.prompt->text);
-
- fprintf(fp, "%s\n", cs->postfix);
-}
-
-/* The returned pointer must be freed on the caller side */
-static char *escape_string_value(const char *in)
-{
- const char *p;
- char *out;
- size_t len;
-
- len = strlen(in) + strlen("\"\"") + 1;
-
- p = in;
- while (1) {
- p += strcspn(p, "\"\\");
-
- if (p[0] == '\0')
- break;
-
- len++;
- p++;
- }
-
- out = xmalloc(len);
- out[0] = '\0';
-
- strcat(out, "\"");
-
- p = in;
- while (1) {
- len = strcspn(p, "\"\\");
- strncat(out, p, len);
- p += len;
-
- if (p[0] == '\0')
- break;
-
- strcat(out, "\\");
- strncat(out, p++, 1);
- }
-
- strcat(out, "\"");
-
- return out;
-}
-
-enum output_n { OUTPUT_N, OUTPUT_N_AS_UNSET, OUTPUT_N_NONE };
-
-static void __print_symbol(FILE *fp, struct symbol *sym, enum output_n output_n,
- bool escape_string)
-{
- const char *val;
- char *escaped = NULL;
-
- if (sym->type == S_UNKNOWN)
- return;
-
- val = sym_get_string_value(sym);
-
- if ((sym->type == S_BOOLEAN || sym->type == S_TRISTATE) &&
- output_n != OUTPUT_N && *val == 'n') {
- if (output_n == OUTPUT_N_AS_UNSET)
- fprintf(fp, "# %s%s is not set\n", CONFIG_, sym->name);
- return;
- }
-
- if (sym->type == S_STRING && escape_string) {
- escaped = escape_string_value(val);
- val = escaped;
- }
-
- fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, val);
-
- free(escaped);
-}
-
-static void print_symbol_for_dotconfig(FILE *fp, struct symbol *sym)
-{
- __print_symbol(fp, sym, OUTPUT_N_AS_UNSET, true);
-}
-
-static void print_symbol_for_autoconf(FILE *fp, struct symbol *sym)
-{
- __print_symbol(fp, sym, OUTPUT_N_NONE, false);
-}
-
-void print_symbol_for_listconfig(struct symbol *sym)
-{
- __print_symbol(stdout, sym, OUTPUT_N, true);
-}
-
-static void print_symbol_for_c(FILE *fp, struct symbol *sym)
-{
- const char *val;
- const char *sym_suffix = "";
- const char *val_prefix = "";
- char *escaped = NULL;
-
- if (sym->type == S_UNKNOWN)
- return;
-
- val = sym_get_string_value(sym);
-
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- switch (*val) {
- case 'n':
- return;
- case 'm':
- sym_suffix = "_MODULE";
- /* fall through */
- default:
- val = "1";
- }
- break;
- case S_HEX:
- if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
- val_prefix = "0x";
- break;
- case S_STRING:
- escaped = escape_string_value(val);
- val = escaped;
- default:
- break;
- }
-
- fprintf(fp, "#define %s%s%s %s%s\n", CONFIG_, sym->name, sym_suffix,
- val_prefix, val);
-
- free(escaped);
-}
-
-static void print_symbol_for_rustccfg(FILE *fp, struct symbol *sym)
-{
- const char *val;
- const char *val_prefix = "";
- char *val_prefixed = NULL;
- size_t val_prefixed_len;
- char *escaped = NULL;
-
- if (sym->type == S_UNKNOWN)
- return;
-
- val = sym_get_string_value(sym);
-
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- /*
- * We do not care about disabled ones, i.e. no need for
- * what otherwise are "comments" in other printers.
- */
- if (*val == 'n')
- return;
-
- /*
- * To have similar functionality to the C macro `IS_ENABLED()`
- * we provide an empty `--cfg CONFIG_X` here in both `y`
- * and `m` cases.
- *
- * Then, the common `fprintf()` below will also give us
- * a `--cfg CONFIG_X="y"` or `--cfg CONFIG_X="m"`, which can
- * be used as the equivalent of `IS_BUILTIN()`/`IS_MODULE()`.
- */
- fprintf(fp, "--cfg=%s%s\n", CONFIG_, sym->name);
- break;
- case S_HEX:
- if (val[0] != '0' || (val[1] != 'x' && val[1] != 'X'))
- val_prefix = "0x";
- break;
- default:
- break;
- }
-
- if (strlen(val_prefix) > 0) {
- val_prefixed_len = strlen(val) + strlen(val_prefix) + 1;
- val_prefixed = xmalloc(val_prefixed_len);
- snprintf(val_prefixed, val_prefixed_len, "%s%s", val_prefix, val);
- val = val_prefixed;
- }
-
- /* All values get escaped: the `--cfg` option only takes strings */
- escaped = escape_string_value(val);
- val = escaped;
-
- fprintf(fp, "--cfg=%s%s=%s\n", CONFIG_, sym->name, val);
-
- free(escaped);
- free(val_prefixed);
-}
-
-/*
- * Write out a minimal config.
- * All values that has default values are skipped as this is redundant.
- */
-int conf_write_defconfig(const char *filename)
-{
- struct symbol *sym;
- struct menu *menu;
- FILE *out;
-
- out = fopen(filename, "w");
- if (!out)
- return 1;
-
- sym_clear_all_valid();
-
- /* Traverse all menus to find all relevant symbols */
- menu = rootmenu.list;
-
- while (menu != NULL)
- {
- sym = menu->sym;
- if (sym == NULL) {
- if (!menu_is_visible(menu))
- goto next_menu;
- } else if (!sym_is_choice(sym)) {
- sym_calc_value(sym);
- if (!(sym->flags & SYMBOL_WRITE))
- goto next_menu;
- sym->flags &= ~SYMBOL_WRITE;
- /* If we cannot change the symbol - skip */
- if (!sym_is_changeable(sym))
- goto next_menu;
- /* If symbol equals to default value - skip */
- if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
- goto next_menu;
-
- /*
- * If symbol is a choice value and equals to the
- * default for a choice - skip.
- * But only if value is bool and equal to "y" and
- * choice is not "optional".
- * (If choice is "optional" then all values can be "n")
- */
- if (sym_is_choice_value(sym)) {
- struct symbol *cs;
- struct symbol *ds;
-
- cs = prop_get_symbol(sym_get_choice_prop(sym));
- ds = sym_choice_default(cs);
- if (!sym_is_optional(cs) && sym == ds) {
- if ((sym->type == S_BOOLEAN) &&
- sym_get_tristate_value(sym) == yes)
- goto next_menu;
- }
- }
- print_symbol_for_dotconfig(out, sym);
- }
-next_menu:
- if (menu->list != NULL) {
- menu = menu->list;
- }
- else if (menu->next != NULL) {
- menu = menu->next;
- } else {
- while ((menu = menu->parent)) {
- if (menu->next != NULL) {
- menu = menu->next;
- break;
- }
- }
- }
- }
- fclose(out);
- return 0;
-}
-
-int conf_write(const char *name)
-{
- FILE *out;
- struct symbol *sym;
- struct menu *menu;
- const char *str;
- char tmpname[PATH_MAX + 1], oldname[PATH_MAX + 1];
- char *env;
- int i;
- bool need_newline = false;
-
- if (!name)
- name = conf_get_configname();
-
- if (!*name) {
- fprintf(stderr, "config name is empty\n");
- return -1;
- }
-
- if (is_dir(name)) {
- fprintf(stderr, "%s: Is a directory\n", name);
- return -1;
- }
-
- if (make_parent_dir(name))
- return -1;
-
- env = getenv("KCONFIG_OVERWRITECONFIG");
- if (env && *env) {
- *tmpname = 0;
- out = fopen(name, "w");
- } else {
- snprintf(tmpname, sizeof(tmpname), "%s.%d.tmp",
- name, (int)getpid());
- out = fopen(tmpname, "w");
- }
- if (!out)
- return 1;
-
- conf_write_heading(out, &comment_style_pound);
-
- if (!conf_get_changed())
- sym_clear_all_valid();
-
- 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);
- need_newline = false;
- } else if (!(sym->flags & SYMBOL_CHOICE) &&
- !(sym->flags & SYMBOL_WRITTEN)) {
- sym_calc_value(sym);
- if (!(sym->flags & SYMBOL_WRITE))
- goto next;
- if (need_newline) {
- fprintf(out, "\n");
- need_newline = false;
- }
- sym->flags |= SYMBOL_WRITTEN;
- print_symbol_for_dotconfig(out, sym);
- }
-
-next:
- if (menu->list) {
- menu = menu->list;
- continue;
- }
-
-end_check:
- if (!menu->sym && menu_is_visible(menu) && menu != &rootmenu &&
- menu->prompt->type == P_MENU) {
- fprintf(out, "# end of %s\n", menu_get_prompt(menu));
- need_newline = true;
- }
-
- if (menu->next) {
- menu = menu->next;
- } else {
- menu = menu->parent;
- if (menu)
- goto end_check;
- }
- }
- fclose(out);
-
- for_all_symbols(i, sym)
- sym->flags &= ~SYMBOL_WRITTEN;
-
- if (*tmpname) {
- if (is_same(name, tmpname)) {
- conf_message("No change to %s", name);
- unlink(tmpname);
- conf_set_changed(false);
- return 0;
- }
-
- snprintf(oldname, sizeof(oldname), "%s.old", name);
- rename(name, oldname);
- if (rename(tmpname, name))
- return 1;
- }
-
- conf_message("configuration written to %s", name);
-
- conf_set_changed(false);
-
- return 0;
-}
-
-/* write a dependency file as used by kbuild to track dependencies */
-static int conf_write_autoconf_cmd(const char *autoconf_name)
-{
- char name[PATH_MAX], tmp[PATH_MAX];
- struct file *file;
- FILE *out;
- int ret;
-
- ret = snprintf(name, sizeof(name), "%s.cmd", autoconf_name);
- if (ret >= sizeof(name)) /* check truncation */
- return -1;
-
- if (make_parent_dir(name))
- return -1;
-
- ret = snprintf(tmp, sizeof(tmp), "%s.cmd.tmp", autoconf_name);
- if (ret >= sizeof(tmp)) /* check truncation */
- return -1;
-
- out = fopen(tmp, "w");
- if (!out) {
- perror("fopen");
- return -1;
- }
-
- fprintf(out, "deps_config := \\\n");
- for (file = file_list; file; file = file->next)
- fprintf(out, "\t%s \\\n", file->name);
-
- fprintf(out, "\n%s: $(deps_config)\n\n", autoconf_name);
-
- env_write_dep(out, autoconf_name);
-
- fprintf(out, "\n$(deps_config): ;\n");
-
- fflush(out);
- ret = ferror(out); /* error check for all fprintf() calls */
- fclose(out);
- if (ret)
- return -1;
-
- if (rename(tmp, name)) {
- perror("rename");
- return -1;
- }
-
- return 0;
-}
-
-static int conf_touch_deps(void)
-{
- const char *name, *tmp;
- struct symbol *sym;
- int res, i;
-
- name = conf_get_autoconfig_name();
- tmp = strrchr(name, '/');
- depfile_prefix_len = tmp ? tmp - name + 1 : 0;
- if (depfile_prefix_len + 1 > sizeof(depfile_path))
- return -1;
-
- strncpy(depfile_path, name, depfile_prefix_len);
- depfile_path[depfile_prefix_len] = 0;
-
- conf_read_simple(name, S_DEF_AUTO);
- sym_calc_value(modules_sym);
-
- for_all_symbols(i, sym) {
- sym_calc_value(sym);
- if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
- continue;
- if (sym->flags & SYMBOL_WRITE) {
- if (sym->flags & SYMBOL_DEF_AUTO) {
- /*
- * symbol has old and new value,
- * so compare them...
- */
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- if (sym_get_tristate_value(sym) ==
- sym->def[S_DEF_AUTO].tri)
- continue;
- break;
- case S_STRING:
- case S_HEX:
- case S_INT:
- if (!strcmp(sym_get_string_value(sym),
- sym->def[S_DEF_AUTO].val))
- continue;
- break;
- default:
- break;
- }
- } else {
- /*
- * If there is no old value, only 'no' (unset)
- * is allowed as new value.
- */
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- if (sym_get_tristate_value(sym) == no)
- continue;
- break;
- default:
- break;
- }
- }
- } else if (!(sym->flags & SYMBOL_DEF_AUTO))
- /* There is neither an old nor a new value. */
- continue;
- /* else
- * There is an old value, but no new value ('no' (unset)
- * isn't saved in auto.conf, so the old value is always
- * different from 'no').
- */
-
- res = conf_touch_dep(sym->name);
- if (res)
- return res;
- }
-
- return 0;
-}
-
-static int __conf_write_autoconf(const char *filename,
- void (*print_symbol)(FILE *, struct symbol *),
- const struct comment_style *comment_style)
-{
- char tmp[PATH_MAX];
- FILE *file;
- struct symbol *sym;
- int ret, i;
-
- if (make_parent_dir(filename))
- return -1;
-
- ret = snprintf(tmp, sizeof(tmp), "%s.tmp", filename);
- if (ret >= sizeof(tmp)) /* check truncation */
- return -1;
-
- file = fopen(tmp, "w");
- if (!file) {
- perror("fopen");
- return -1;
- }
-
- conf_write_heading(file, comment_style);
-
- for_all_symbols(i, sym)
- if ((sym->flags & SYMBOL_WRITE) && sym->name)
- print_symbol(file, sym);
-
- fflush(file);
- /* check possible errors in conf_write_heading() and print_symbol() */
- ret = ferror(file);
- fclose(file);
- if (ret)
- return -1;
-
- if (rename(tmp, filename)) {
- perror("rename");
- return -1;
- }
-
- return 0;
-}
-
-int conf_write_autoconf(int overwrite)
-{
- struct symbol *sym;
- const char *autoconf_name = conf_get_autoconfig_name();
- int ret, i;
-
- if (!overwrite && is_present(autoconf_name))
- return 0;
-
- ret = conf_write_autoconf_cmd(autoconf_name);
- if (ret)
- return -1;
-
- if (conf_touch_deps())
- return 1;
-
- for_all_symbols(i, sym)
- sym_calc_value(sym);
-
- ret = __conf_write_autoconf(conf_get_autoheader_name(),
- print_symbol_for_c,
- &comment_style_c);
- if (ret)
- return ret;
-
- ret = __conf_write_autoconf(conf_get_rustccfg_name(),
- print_symbol_for_rustccfg,
- NULL);
- if (ret)
- return ret;
-
- /*
- * Create include/config/auto.conf. This must be the last step because
- * Kbuild has a dependency on auto.conf and this marks the successful
- * completion of the previous steps.
- */
- ret = __conf_write_autoconf(conf_get_autoconfig_name(),
- print_symbol_for_autoconf,
- &comment_style_pound);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static bool conf_changed;
-static void (*conf_changed_callback)(void);
-
-void conf_set_changed(bool val)
-{
- if (conf_changed_callback && conf_changed != val)
- conf_changed_callback();
-
- conf_changed = val;
-}
-
-bool conf_get_changed(void)
-{
- return conf_changed;
-}
-
-void conf_set_changed_callback(void (*fn)(void))
-{
- conf_changed_callback = fn;
-}
-
-void set_all_choice_values(struct symbol *csym)
-{
- struct property *prop;
- struct symbol *sym;
- struct expr *e;
-
- prop = sym_get_choice_prop(csym);
-
- /*
- * Set all non-assinged choice values to no
- */
- expr_list_for_each_sym(prop->expr, e, sym) {
- if (!sym_has_value(sym))
- sym->def[S_DEF_USER].tri = no;
- }
- csym->flags |= SYMBOL_DEF_USER;
- /* clear VALID to get value calculated */
- csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);
-}
diff --git a/tools/kconfig/expr.c b/tools/kconfig/expr.c
deleted file mode 100644
index 81ebf81..0000000
--- a/tools/kconfig/expr.c
+++ /dev/null
@@ -1,1303 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "lkc.h"
-
-#define DEBUG_EXPR 0
-
-static struct expr *expr_eliminate_yn(struct expr *e);
-
-struct expr *expr_alloc_symbol(struct symbol *sym)
-{
- struct expr *e = xcalloc(1, sizeof(*e));
- e->type = E_SYMBOL;
- e->left.sym = sym;
- return e;
-}
-
-struct expr *expr_alloc_one(enum expr_type type, struct expr *ce)
-{
- struct expr *e = xcalloc(1, sizeof(*e));
- e->type = type;
- e->left.expr = ce;
- return e;
-}
-
-struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2)
-{
- struct expr *e = xcalloc(1, sizeof(*e));
- e->type = type;
- e->left.expr = e1;
- e->right.expr = e2;
- return e;
-}
-
-struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2)
-{
- struct expr *e = xcalloc(1, sizeof(*e));
- e->type = type;
- e->left.sym = s1;
- e->right.sym = s2;
- return e;
-}
-
-struct expr *expr_alloc_and(struct expr *e1, struct expr *e2)
-{
- if (!e1)
- return e2;
- return e2 ? expr_alloc_two(E_AND, e1, e2) : e1;
-}
-
-struct expr *expr_alloc_or(struct expr *e1, struct expr *e2)
-{
- if (!e1)
- return e2;
- return e2 ? expr_alloc_two(E_OR, e1, e2) : e1;
-}
-
-struct expr *expr_copy(const struct expr *org)
-{
- struct expr *e;
-
- if (!org)
- return NULL;
-
- e = xmalloc(sizeof(*org));
- memcpy(e, org, sizeof(*org));
- switch (org->type) {
- case E_SYMBOL:
- e->left = org->left;
- break;
- case E_NOT:
- e->left.expr = expr_copy(org->left.expr);
- break;
- case E_EQUAL:
- case E_GEQ:
- case E_GTH:
- case E_LEQ:
- case E_LTH:
- case E_UNEQUAL:
- e->left.sym = org->left.sym;
- e->right.sym = org->right.sym;
- break;
- case E_AND:
- case E_OR:
- case E_LIST:
- e->left.expr = expr_copy(org->left.expr);
- e->right.expr = expr_copy(org->right.expr);
- break;
- default:
- fprintf(stderr, "can't copy type %d\n", e->type);
- free(e);
- e = NULL;
- break;
- }
-
- return e;
-}
-
-void expr_free(struct expr *e)
-{
- if (!e)
- return;
-
- switch (e->type) {
- case E_SYMBOL:
- break;
- case E_NOT:
- expr_free(e->left.expr);
- break;
- case E_EQUAL:
- case E_GEQ:
- case E_GTH:
- case E_LEQ:
- case E_LTH:
- case E_UNEQUAL:
- break;
- case E_OR:
- case E_AND:
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- break;
- default:
- fprintf(stderr, "how to free type %d?\n", e->type);
- break;
- }
- free(e);
-}
-
-static int trans_count;
-
-#define e1 (*ep1)
-#define e2 (*ep2)
-
-/*
- * expr_eliminate_eq() helper.
- *
- * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
- * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
- * against all other leaves. Two equal leaves are both replaced with either 'y'
- * or 'n' as appropriate for 'type', to be eliminated later.
- */
-static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2)
-{
- /* Recurse down to leaves */
-
- if (e1->type == type) {
- __expr_eliminate_eq(type, &e1->left.expr, &e2);
- __expr_eliminate_eq(type, &e1->right.expr, &e2);
- return;
- }
- if (e2->type == type) {
- __expr_eliminate_eq(type, &e1, &e2->left.expr);
- __expr_eliminate_eq(type, &e1, &e2->right.expr);
- return;
- }
-
- /* e1 and e2 are leaves. Compare them. */
-
- if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
- e1->left.sym == e2->left.sym &&
- (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
- return;
- if (!expr_eq(e1, e2))
- return;
-
- /* e1 and e2 are equal leaves. Prepare them for elimination. */
-
- trans_count++;
- expr_free(e1); expr_free(e2);
- switch (type) {
- case E_OR:
- e1 = expr_alloc_symbol(&symbol_no);
- e2 = expr_alloc_symbol(&symbol_no);
- break;
- case E_AND:
- e1 = expr_alloc_symbol(&symbol_yes);
- e2 = expr_alloc_symbol(&symbol_yes);
- break;
- default:
- ;
- }
-}
-
-/*
- * Rewrites the expressions 'ep1' and 'ep2' to remove operands common to both.
- * Example reductions:
- *
- * ep1: A && B -> ep1: y
- * ep2: A && B && C -> ep2: C
- *
- * ep1: A || B -> ep1: n
- * ep2: A || B || C -> ep2: C
- *
- * ep1: A && (B && FOO) -> ep1: FOO
- * ep2: (BAR && B) && A -> ep2: BAR
- *
- * ep1: A && (B || C) -> ep1: y
- * ep2: (C || B) && A -> ep2: y
- *
- * Comparisons are done between all operands at the same "level" of && or ||.
- * For example, in the expression 'e1 && (e2 || e3) && (e4 || e5)', the
- * following operands will be compared:
- *
- * - 'e1', 'e2 || e3', and 'e4 || e5', against each other
- * - e2 against e3
- * - e4 against e5
- *
- * Parentheses are irrelevant within a single level. 'e1 && (e2 && e3)' and
- * '(e1 && e2) && e3' are both a single level.
- *
- * See __expr_eliminate_eq() as well.
- */
-void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
-{
- if (!e1 || !e2)
- return;
- switch (e1->type) {
- case E_OR:
- case E_AND:
- __expr_eliminate_eq(e1->type, ep1, ep2);
- default:
- ;
- }
- if (e1->type != e2->type) switch (e2->type) {
- case E_OR:
- case E_AND:
- __expr_eliminate_eq(e2->type, ep1, ep2);
- default:
- ;
- }
- e1 = expr_eliminate_yn(e1);
- e2 = expr_eliminate_yn(e2);
-}
-
-#undef e1
-#undef e2
-
-/*
- * Returns true if 'e1' and 'e2' are equal, after minor simplification. Two
- * &&/|| expressions are considered equal if every operand in one expression
- * equals some operand in the other (operands do not need to appear in the same
- * order), recursively.
- */
-int expr_eq(struct expr *e1, struct expr *e2)
-{
- int res, old_count;
-
- /*
- * A NULL expr is taken to be yes, but there's also a different way to
- * represent yes. expr_is_yes() checks for either representation.
- */
- if (!e1 || !e2)
- return expr_is_yes(e1) && expr_is_yes(e2);
-
- if (e1->type != e2->type)
- return 0;
- switch (e1->type) {
- case E_EQUAL:
- case E_GEQ:
- case E_GTH:
- case E_LEQ:
- case E_LTH:
- case E_UNEQUAL:
- return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym;
- case E_SYMBOL:
- return e1->left.sym == e2->left.sym;
- case E_NOT:
- return expr_eq(e1->left.expr, e2->left.expr);
- case E_AND:
- case E_OR:
- e1 = expr_copy(e1);
- e2 = expr_copy(e2);
- old_count = trans_count;
- expr_eliminate_eq(&e1, &e2);
- res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
- e1->left.sym == e2->left.sym);
- expr_free(e1);
- expr_free(e2);
- trans_count = old_count;
- return res;
- case E_LIST:
- case E_RANGE:
- case E_NONE:
- /* panic */;
- }
-
- if (DEBUG_EXPR) {
- expr_fprint(e1, stdout);
- printf(" = ");
- expr_fprint(e2, stdout);
- printf(" ?\n");
- }
-
- return 0;
-}
-
-/*
- * Recursively performs the following simplifications in-place (as well as the
- * corresponding simplifications with swapped operands):
- *
- * expr && n -> n
- * expr && y -> expr
- * expr || n -> expr
- * expr || y -> y
- *
- * Returns the optimized expression.
- */
-static struct expr *expr_eliminate_yn(struct expr *e)
-{
- struct expr *tmp;
-
- if (e) switch (e->type) {
- case E_AND:
- e->left.expr = expr_eliminate_yn(e->left.expr);
- e->right.expr = expr_eliminate_yn(e->right.expr);
- if (e->left.expr->type == E_SYMBOL) {
- if (e->left.expr->left.sym == &symbol_no) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- e->right.expr = NULL;
- return e;
- } else if (e->left.expr->left.sym == &symbol_yes) {
- free(e->left.expr);
- tmp = e->right.expr;
- *e = *(e->right.expr);
- free(tmp);
- return e;
- }
- }
- if (e->right.expr->type == E_SYMBOL) {
- if (e->right.expr->left.sym == &symbol_no) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- e->right.expr = NULL;
- return e;
- } else if (e->right.expr->left.sym == &symbol_yes) {
- free(e->right.expr);
- tmp = e->left.expr;
- *e = *(e->left.expr);
- free(tmp);
- return e;
- }
- }
- break;
- case E_OR:
- e->left.expr = expr_eliminate_yn(e->left.expr);
- e->right.expr = expr_eliminate_yn(e->right.expr);
- if (e->left.expr->type == E_SYMBOL) {
- if (e->left.expr->left.sym == &symbol_no) {
- free(e->left.expr);
- tmp = e->right.expr;
- *e = *(e->right.expr);
- free(tmp);
- return e;
- } else if (e->left.expr->left.sym == &symbol_yes) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- e->right.expr = NULL;
- return e;
- }
- }
- if (e->right.expr->type == E_SYMBOL) {
- if (e->right.expr->left.sym == &symbol_no) {
- free(e->right.expr);
- tmp = e->left.expr;
- *e = *(e->left.expr);
- free(tmp);
- return e;
- } else if (e->right.expr->left.sym == &symbol_yes) {
- expr_free(e->left.expr);
- expr_free(e->right.expr);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- e->right.expr = NULL;
- return e;
- }
- }
- break;
- default:
- ;
- }
- return e;
-}
-
-/*
- * bool FOO!=n => FOO
- */
-struct expr *expr_trans_bool(struct expr *e)
-{
- if (!e)
- return NULL;
- switch (e->type) {
- case E_AND:
- case E_OR:
- case E_NOT:
- e->left.expr = expr_trans_bool(e->left.expr);
- e->right.expr = expr_trans_bool(e->right.expr);
- break;
- case E_UNEQUAL:
- // FOO!=n -> FOO
- if (e->left.sym->type == S_TRISTATE) {
- if (e->right.sym == &symbol_no) {
- e->type = E_SYMBOL;
- e->right.sym = NULL;
- }
- }
- break;
- default:
- ;
- }
- return e;
-}
-
-/*
- * e1 || e2 -> ?
- */
-static struct expr *expr_join_or(struct expr *e1, struct expr *e2)
-{
- struct expr *tmp;
- struct symbol *sym1, *sym2;
-
- if (expr_eq(e1, e2))
- return expr_copy(e1);
- if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
- return NULL;
- if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
- return NULL;
- if (e1->type == E_NOT) {
- tmp = e1->left.expr;
- if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
- return NULL;
- sym1 = tmp->left.sym;
- } else
- sym1 = e1->left.sym;
- if (e2->type == E_NOT) {
- if (e2->left.expr->type != E_SYMBOL)
- return NULL;
- sym2 = e2->left.expr->left.sym;
- } else
- sym2 = e2->left.sym;
- if (sym1 != sym2)
- return NULL;
- if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
- return NULL;
- if (sym1->type == S_TRISTATE) {
- if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
- ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
- (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) {
- // (a='y') || (a='m') -> (a!='n')
- return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no);
- }
- if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
- ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
- (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) {
- // (a='y') || (a='n') -> (a!='m')
- return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod);
- }
- if (e1->type == E_EQUAL && e2->type == E_EQUAL &&
- ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
- (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) {
- // (a='m') || (a='n') -> (a!='y')
- return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes);
- }
- }
- if (sym1->type == S_BOOLEAN && sym1 == sym2) {
- if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) ||
- (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL))
- return expr_alloc_symbol(&symbol_yes);
- }
-
- if (DEBUG_EXPR) {
- printf("optimize (");
- expr_fprint(e1, stdout);
- printf(") || (");
- expr_fprint(e2, stdout);
- printf(")?\n");
- }
- return NULL;
-}
-
-static struct expr *expr_join_and(struct expr *e1, struct expr *e2)
-{
- struct expr *tmp;
- struct symbol *sym1, *sym2;
-
- if (expr_eq(e1, e2))
- return expr_copy(e1);
- if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT)
- return NULL;
- if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT)
- return NULL;
- if (e1->type == E_NOT) {
- tmp = e1->left.expr;
- if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL)
- return NULL;
- sym1 = tmp->left.sym;
- } else
- sym1 = e1->left.sym;
- if (e2->type == E_NOT) {
- if (e2->left.expr->type != E_SYMBOL)
- return NULL;
- sym2 = e2->left.expr->left.sym;
- } else
- sym2 = e2->left.sym;
- if (sym1 != sym2)
- return NULL;
- if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE)
- return NULL;
-
- if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) ||
- (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes))
- // (a) && (a='y') -> (a='y')
- return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
-
- if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) ||
- (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no))
- // (a) && (a!='n') -> (a)
- return expr_alloc_symbol(sym1);
-
- if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) ||
- (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod))
- // (a) && (a!='m') -> (a='y')
- return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
-
- if (sym1->type == S_TRISTATE) {
- if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) {
- // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
- sym2 = e1->right.sym;
- if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
- return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
- : expr_alloc_symbol(&symbol_no);
- }
- if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) {
- // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b'
- sym2 = e2->right.sym;
- if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST))
- return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2)
- : expr_alloc_symbol(&symbol_no);
- }
- if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
- ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) ||
- (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes)))
- // (a!='y') && (a!='n') -> (a='m')
- return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod);
-
- if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
- ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) ||
- (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes)))
- // (a!='y') && (a!='m') -> (a='n')
- return expr_alloc_comp(E_EQUAL, sym1, &symbol_no);
-
- if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL &&
- ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) ||
- (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod)))
- // (a!='m') && (a!='n') -> (a='m')
- return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes);
-
- if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) ||
- (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) ||
- (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) ||
- (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes))
- return NULL;
- }
-
- if (DEBUG_EXPR) {
- printf("optimize (");
- expr_fprint(e1, stdout);
- printf(") && (");
- expr_fprint(e2, stdout);
- printf(")?\n");
- }
- return NULL;
-}
-
-/*
- * expr_eliminate_dups() helper.
- *
- * Walks the two expression trees given in 'ep1' and 'ep2'. Any node that does
- * not have type 'type' (E_OR/E_AND) is considered a leaf, and is compared
- * against all other leaves to look for simplifications.
- */
-static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2)
-{
-#define e1 (*ep1)
-#define e2 (*ep2)
- struct expr *tmp;
-
- /* Recurse down to leaves */
-
- if (e1->type == type) {
- expr_eliminate_dups1(type, &e1->left.expr, &e2);
- expr_eliminate_dups1(type, &e1->right.expr, &e2);
- return;
- }
- if (e2->type == type) {
- expr_eliminate_dups1(type, &e1, &e2->left.expr);
- expr_eliminate_dups1(type, &e1, &e2->right.expr);
- return;
- }
-
- /* e1 and e2 are leaves. Compare and process them. */
-
- if (e1 == e2)
- return;
-
- switch (e1->type) {
- case E_OR: case E_AND:
- expr_eliminate_dups1(e1->type, &e1, &e1);
- default:
- ;
- }
-
- switch (type) {
- case E_OR:
- tmp = expr_join_or(e1, e2);
- if (tmp) {
- expr_free(e1); expr_free(e2);
- e1 = expr_alloc_symbol(&symbol_no);
- e2 = tmp;
- trans_count++;
- }
- break;
- case E_AND:
- tmp = expr_join_and(e1, e2);
- if (tmp) {
- expr_free(e1); expr_free(e2);
- e1 = expr_alloc_symbol(&symbol_yes);
- e2 = tmp;
- trans_count++;
- }
- break;
- default:
- ;
- }
-#undef e1
-#undef e2
-}
-
-/*
- * Rewrites 'e' in-place to remove ("join") duplicate and other redundant
- * operands.
- *
- * Example simplifications:
- *
- * A || B || A -> A || B
- * A && B && A=y -> A=y && B
- *
- * Returns the deduplicated expression.
- */
-struct expr *expr_eliminate_dups(struct expr *e)
-{
- int oldcount;
- if (!e)
- return e;
-
- oldcount = trans_count;
- while (1) {
- trans_count = 0;
- switch (e->type) {
- case E_OR: case E_AND:
- expr_eliminate_dups1(e->type, &e, &e);
- default:
- ;
- }
- if (!trans_count)
- /* No simplifications done in this pass. We're done */
- break;
- e = expr_eliminate_yn(e);
- }
- trans_count = oldcount;
- return e;
-}
-
-/*
- * Performs various simplifications involving logical operators and
- * comparisons.
- *
- * Allocates and returns a new expression.
- */
-struct expr *expr_transform(struct expr *e)
-{
- struct expr *tmp;
-
- if (!e)
- return NULL;
- switch (e->type) {
- case E_EQUAL:
- case E_GEQ:
- case E_GTH:
- case E_LEQ:
- case E_LTH:
- case E_UNEQUAL:
- case E_SYMBOL:
- case E_LIST:
- break;
- default:
- e->left.expr = expr_transform(e->left.expr);
- e->right.expr = expr_transform(e->right.expr);
- }
-
- switch (e->type) {
- case E_EQUAL:
- if (e->left.sym->type != S_BOOLEAN)
- break;
- if (e->right.sym == &symbol_no) {
- e->type = E_NOT;
- e->left.expr = expr_alloc_symbol(e->left.sym);
- e->right.sym = NULL;
- break;
- }
- if (e->right.sym == &symbol_mod) {
- printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- e->right.sym = NULL;
- break;
- }
- if (e->right.sym == &symbol_yes) {
- e->type = E_SYMBOL;
- e->right.sym = NULL;
- break;
- }
- break;
- case E_UNEQUAL:
- if (e->left.sym->type != S_BOOLEAN)
- break;
- if (e->right.sym == &symbol_no) {
- e->type = E_SYMBOL;
- e->right.sym = NULL;
- break;
- }
- if (e->right.sym == &symbol_mod) {
- printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name);
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- e->right.sym = NULL;
- break;
- }
- if (e->right.sym == &symbol_yes) {
- e->type = E_NOT;
- e->left.expr = expr_alloc_symbol(e->left.sym);
- e->right.sym = NULL;
- break;
- }
- break;
- case E_NOT:
- switch (e->left.expr->type) {
- case E_NOT:
- // !!a -> a
- tmp = e->left.expr->left.expr;
- free(e->left.expr);
- free(e);
- e = tmp;
- e = expr_transform(e);
- break;
- case E_EQUAL:
- case E_UNEQUAL:
- // !a='x' -> a!='x'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL;
- break;
- case E_LEQ:
- case E_GEQ:
- // !a<='x' -> a>'x'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = e->type == E_LEQ ? E_GTH : E_LTH;
- break;
- case E_LTH:
- case E_GTH:
- // !a<'x' -> a>='x'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = e->type == E_LTH ? E_GEQ : E_LEQ;
- break;
- case E_OR:
- // !(a || b) -> !a && !b
- tmp = e->left.expr;
- e->type = E_AND;
- e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
- tmp->type = E_NOT;
- tmp->right.expr = NULL;
- e = expr_transform(e);
- break;
- case E_AND:
- // !(a && b) -> !a || !b
- tmp = e->left.expr;
- e->type = E_OR;
- e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr);
- tmp->type = E_NOT;
- tmp->right.expr = NULL;
- e = expr_transform(e);
- break;
- case E_SYMBOL:
- if (e->left.expr->left.sym == &symbol_yes) {
- // !'y' -> 'n'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = E_SYMBOL;
- e->left.sym = &symbol_no;
- break;
- }
- if (e->left.expr->left.sym == &symbol_mod) {
- // !'m' -> 'm'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = E_SYMBOL;
- e->left.sym = &symbol_mod;
- break;
- }
- if (e->left.expr->left.sym == &symbol_no) {
- // !'n' -> 'y'
- tmp = e->left.expr;
- free(e);
- e = tmp;
- e->type = E_SYMBOL;
- e->left.sym = &symbol_yes;
- break;
- }
- break;
- default:
- ;
- }
- break;
- default:
- ;
- }
- return e;
-}
-
-int expr_contains_symbol(struct expr *dep, struct symbol *sym)
-{
- if (!dep)
- return 0;
-
- switch (dep->type) {
- case E_AND:
- case E_OR:
- return expr_contains_symbol(dep->left.expr, sym) ||
- expr_contains_symbol(dep->right.expr, sym);
- case E_SYMBOL:
- return dep->left.sym == sym;
- case E_EQUAL:
- case E_GEQ:
- case E_GTH:
- case E_LEQ:
- case E_LTH:
- case E_UNEQUAL:
- return dep->left.sym == sym ||
- dep->right.sym == sym;
- case E_NOT:
- return expr_contains_symbol(dep->left.expr, sym);
- default:
- ;
- }
- return 0;
-}
-
-bool expr_depends_symbol(struct expr *dep, struct symbol *sym)
-{
- if (!dep)
- return false;
-
- switch (dep->type) {
- case E_AND:
- return expr_depends_symbol(dep->left.expr, sym) ||
- expr_depends_symbol(dep->right.expr, sym);
- case E_SYMBOL:
- return dep->left.sym == sym;
- case E_EQUAL:
- if (dep->left.sym == sym) {
- if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod)
- return true;
- }
- break;
- case E_UNEQUAL:
- if (dep->left.sym == sym) {
- if (dep->right.sym == &symbol_no)
- return true;
- }
- break;
- default:
- ;
- }
- return false;
-}
-
-/*
- * Inserts explicit comparisons of type 'type' to symbol 'sym' into the
- * expression 'e'.
- *
- * Examples transformations for type == E_UNEQUAL, sym == &symbol_no:
- *
- * A -> A!=n
- * !A -> A=n
- * A && B -> !(A=n || B=n)
- * A || B -> !(A=n && B=n)
- * A && (B || C) -> !(A=n || (B=n && C=n))
- *
- * Allocates and returns a new expression.
- */
-struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym)
-{
- struct expr *e1, *e2;
-
- if (!e) {
- e = expr_alloc_symbol(sym);
- if (type == E_UNEQUAL)
- e = expr_alloc_one(E_NOT, e);
- return e;
- }
- switch (e->type) {
- case E_AND:
- e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
- e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
- if (sym == &symbol_yes)
- e = expr_alloc_two(E_AND, e1, e2);
- if (sym == &symbol_no)
- e = expr_alloc_two(E_OR, e1, e2);
- if (type == E_UNEQUAL)
- e = expr_alloc_one(E_NOT, e);
- return e;
- case E_OR:
- e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym);
- e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym);
- if (sym == &symbol_yes)
- e = expr_alloc_two(E_OR, e1, e2);
- if (sym == &symbol_no)
- e = expr_alloc_two(E_AND, e1, e2);
- if (type == E_UNEQUAL)
- e = expr_alloc_one(E_NOT, e);
- return e;
- case E_NOT:
- return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym);
- case E_UNEQUAL:
- case E_LTH:
- case E_LEQ:
- case E_GTH:
- case E_GEQ:
- case E_EQUAL:
- if (type == E_EQUAL) {
- if (sym == &symbol_yes)
- return expr_copy(e);
- if (sym == &symbol_mod)
- return expr_alloc_symbol(&symbol_no);
- if (sym == &symbol_no)
- return expr_alloc_one(E_NOT, expr_copy(e));
- } else {
- if (sym == &symbol_yes)
- return expr_alloc_one(E_NOT, expr_copy(e));
- if (sym == &symbol_mod)
- return expr_alloc_symbol(&symbol_yes);
- if (sym == &symbol_no)
- return expr_copy(e);
- }
- break;
- case E_SYMBOL:
- return expr_alloc_comp(type, e->left.sym, sym);
- case E_LIST:
- case E_RANGE:
- case E_NONE:
- /* panic */;
- }
- return NULL;
-}
-
-enum string_value_kind {
- k_string,
- k_signed,
- k_unsigned,
-};
-
-union string_value {
- unsigned long long u;
- signed long long s;
-};
-
-static enum string_value_kind expr_parse_string(const char *str,
- enum symbol_type type,
- union string_value *val)
-{
- char *tail;
- enum string_value_kind kind;
-
- errno = 0;
- switch (type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- val->s = !strcmp(str, "n") ? 0 :
- !strcmp(str, "m") ? 1 :
- !strcmp(str, "y") ? 2 : -1;
- return k_signed;
- case S_INT:
- val->s = strtoll(str, &tail, 10);
- kind = k_signed;
- break;
- case S_HEX:
- val->u = strtoull(str, &tail, 16);
- kind = k_unsigned;
- break;
- default:
- val->s = strtoll(str, &tail, 0);
- kind = k_signed;
- break;
- }
- return !errno && !*tail && tail > str && isxdigit(tail[-1])
- ? kind : k_string;
-}
-
-tristate expr_calc_value(struct expr *e)
-{
- tristate val1, val2;
- const char *str1, *str2;
- enum string_value_kind k1 = k_string, k2 = k_string;
- union string_value lval = {}, rval = {};
- int res;
-
- if (!e)
- return yes;
-
- switch (e->type) {
- case E_SYMBOL:
- sym_calc_value(e->left.sym);
- return e->left.sym->curr.tri;
- case E_AND:
- val1 = expr_calc_value(e->left.expr);
- val2 = expr_calc_value(e->right.expr);
- return EXPR_AND(val1, val2);
- case E_OR:
- val1 = expr_calc_value(e->left.expr);
- val2 = expr_calc_value(e->right.expr);
- return EXPR_OR(val1, val2);
- case E_NOT:
- val1 = expr_calc_value(e->left.expr);
- return EXPR_NOT(val1);
- case E_EQUAL:
- case E_GEQ:
- case E_GTH:
- case E_LEQ:
- case E_LTH:
- case E_UNEQUAL:
- break;
- default:
- printf("expr_calc_value: %d?\n", e->type);
- return no;
- }
-
- sym_calc_value(e->left.sym);
- sym_calc_value(e->right.sym);
- str1 = sym_get_string_value(e->left.sym);
- str2 = sym_get_string_value(e->right.sym);
-
- if (e->left.sym->type != S_STRING || e->right.sym->type != S_STRING) {
- k1 = expr_parse_string(str1, e->left.sym->type, &lval);
- k2 = expr_parse_string(str2, e->right.sym->type, &rval);
- }
-
- if (k1 == k_string || k2 == k_string)
- res = strcmp(str1, str2);
- else if (k1 == k_unsigned || k2 == k_unsigned)
- res = (lval.u > rval.u) - (lval.u < rval.u);
- else /* if (k1 == k_signed && k2 == k_signed) */
- res = (lval.s > rval.s) - (lval.s < rval.s);
-
- switch(e->type) {
- case E_EQUAL:
- return res ? no : yes;
- case E_GEQ:
- return res >= 0 ? yes : no;
- case E_GTH:
- return res > 0 ? yes : no;
- case E_LEQ:
- return res <= 0 ? yes : no;
- case E_LTH:
- return res < 0 ? yes : no;
- case E_UNEQUAL:
- return res ? yes : no;
- default:
- printf("expr_calc_value: relation %d?\n", e->type);
- return no;
- }
-}
-
-static int expr_compare_type(enum expr_type t1, enum expr_type t2)
-{
- if (t1 == t2)
- return 0;
- switch (t1) {
- case E_LEQ:
- case E_LTH:
- case E_GEQ:
- case E_GTH:
- if (t2 == E_EQUAL || t2 == E_UNEQUAL)
- return 1;
- case E_EQUAL:
- case E_UNEQUAL:
- if (t2 == E_NOT)
- return 1;
- case E_NOT:
- if (t2 == E_AND)
- return 1;
- case E_AND:
- if (t2 == E_OR)
- return 1;
- case E_OR:
- if (t2 == E_LIST)
- return 1;
- case E_LIST:
- if (t2 == 0)
- return 1;
- default:
- return -1;
- }
- printf("[%dgt%d?]", t1, t2);
- return 0;
-}
-
-void expr_print(struct expr *e,
- void (*fn)(void *, struct symbol *, const char *),
- void *data, int prevtoken)
-{
- if (!e) {
- fn(data, NULL, "y");
- return;
- }
-
- if (expr_compare_type(prevtoken, e->type) > 0)
- fn(data, NULL, "(");
- switch (e->type) {
- case E_SYMBOL:
- if (e->left.sym->name)
- fn(data, e->left.sym, e->left.sym->name);
- else
- fn(data, NULL, "<choice>");
- break;
- case E_NOT:
- fn(data, NULL, "!");
- expr_print(e->left.expr, fn, data, E_NOT);
- break;
- case E_EQUAL:
- if (e->left.sym->name)
- fn(data, e->left.sym, e->left.sym->name);
- else
- fn(data, NULL, "<choice>");
- fn(data, NULL, "=");
- fn(data, e->right.sym, e->right.sym->name);
- break;
- case E_LEQ:
- case E_LTH:
- if (e->left.sym->name)
- fn(data, e->left.sym, e->left.sym->name);
- else
- fn(data, NULL, "<choice>");
- fn(data, NULL, e->type == E_LEQ ? "<=" : "<");
- fn(data, e->right.sym, e->right.sym->name);
- break;
- case E_GEQ:
- case E_GTH:
- if (e->left.sym->name)
- fn(data, e->left.sym, e->left.sym->name);
- else
- fn(data, NULL, "<choice>");
- fn(data, NULL, e->type == E_GEQ ? ">=" : ">");
- fn(data, e->right.sym, e->right.sym->name);
- break;
- case E_UNEQUAL:
- if (e->left.sym->name)
- fn(data, e->left.sym, e->left.sym->name);
- else
- fn(data, NULL, "<choice>");
- fn(data, NULL, "!=");
- fn(data, e->right.sym, e->right.sym->name);
- break;
- case E_OR:
- expr_print(e->left.expr, fn, data, E_OR);
- fn(data, NULL, " || ");
- expr_print(e->right.expr, fn, data, E_OR);
- break;
- case E_AND:
- expr_print(e->left.expr, fn, data, E_AND);
- fn(data, NULL, " && ");
- expr_print(e->right.expr, fn, data, E_AND);
- break;
- case E_LIST:
- fn(data, e->right.sym, e->right.sym->name);
- if (e->left.expr) {
- fn(data, NULL, " ^ ");
- expr_print(e->left.expr, fn, data, E_LIST);
- }
- break;
- case E_RANGE:
- fn(data, NULL, "[");
- fn(data, e->left.sym, e->left.sym->name);
- fn(data, NULL, " ");
- fn(data, e->right.sym, e->right.sym->name);
- fn(data, NULL, "]");
- break;
- default:
- {
- char buf[32];
- sprintf(buf, "<unknown type %d>", e->type);
- fn(data, NULL, buf);
- break;
- }
- }
- if (expr_compare_type(prevtoken, e->type) > 0)
- fn(data, NULL, ")");
-}
-
-static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
-{
- xfwrite(str, strlen(str), 1, data);
-}
-
-void expr_fprint(struct expr *e, FILE *out)
-{
- expr_print(e, expr_print_file_helper, out, E_NONE);
-}
-
-static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
-{
- struct gstr *gs = (struct gstr*)data;
- const char *sym_str = NULL;
-
- if (sym)
- sym_str = sym_get_string_value(sym);
-
- if (gs->max_width) {
- unsigned extra_length = strlen(str);
- const char *last_cr = strrchr(gs->s, '\n');
- unsigned last_line_length;
-
- if (sym_str)
- extra_length += 4 + strlen(sym_str);
-
- if (!last_cr)
- last_cr = gs->s;
-
- last_line_length = strlen(gs->s) - (last_cr - gs->s);
-
- if ((last_line_length + extra_length) > gs->max_width)
- str_append(gs, "\\\n");
- }
-
- str_append(gs, str);
- if (sym && sym->type != S_UNKNOWN)
- str_printf(gs, " [=%s]", sym_str);
-}
-
-void expr_gstr_print(struct expr *e, struct gstr *gs)
-{
- expr_print(e, expr_print_gstr_helper, gs, E_NONE);
-}
-
-/*
- * Transform the top level "||" tokens into newlines and prepend each
- * line with a minus. This makes expressions much easier to read.
- * Suitable for reverse dependency expressions.
- */
-static void expr_print_revdep(struct expr *e,
- void (*fn)(void *, struct symbol *, const char *),
- void *data, tristate pr_type, const char **title)
-{
- if (e->type == E_OR) {
- expr_print_revdep(e->left.expr, fn, data, pr_type, title);
- expr_print_revdep(e->right.expr, fn, data, pr_type, title);
- } else if (expr_calc_value(e) == pr_type) {
- if (*title) {
- fn(data, NULL, *title);
- *title = NULL;
- }
-
- fn(data, NULL, " - ");
- expr_print(e, fn, data, E_NONE);
- fn(data, NULL, "\n");
- }
-}
-
-void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
- tristate pr_type, const char *title)
-{
- expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);
-}
diff --git a/tools/kconfig/expr.h b/tools/kconfig/expr.h
deleted file mode 100644
index 9c9caca..0000000
--- a/tools/kconfig/expr.h
+++ /dev/null
@@ -1,326 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- */
-
-#ifndef EXPR_H
-#define EXPR_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <assert.h>
-#include <stdio.h>
-#include "list.h"
-#ifndef __cplusplus
-#include <stdbool.h>
-#endif
-
-struct file {
- struct file *next;
- struct file *parent;
- const char *name;
- int lineno;
-};
-
-typedef enum tristate {
- no, mod, yes
-} tristate;
-
-enum expr_type {
- E_NONE, E_OR, E_AND, E_NOT,
- E_EQUAL, E_UNEQUAL, E_LTH, E_LEQ, E_GTH, E_GEQ,
- E_LIST, 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 EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2))
-#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2))
-#define EXPR_NOT(dep) (2-(dep))
-
-#define expr_list_for_each_sym(l, e, s) \
- for (e = (l); e && (s = e->right.sym); e = e->left.expr)
-
-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
-};
-
-/* enum values are used as index to symbol.def[] */
-enum {
- S_DEF_USER, /* main user value */
- S_DEF_AUTO, /* values read from auto.conf */
- S_DEF_DEF3, /* Reserved for UI usage */
- S_DEF_DEF4, /* Reserved for UI usage */
- S_DEF_COUNT
-};
-
-/*
- * Represents a configuration symbol.
- *
- * Choices are represented as a special kind of symbol and have the
- * SYMBOL_CHOICE bit set in 'flags'.
- */
-struct symbol {
- /* The next symbol in the same bucket in the symbol hash table */
- struct symbol *next;
-
- /* The name of the symbol, e.g. "FOO" for 'config FOO' */
- char *name;
-
- /* S_BOOLEAN, S_TRISTATE, ... */
- enum symbol_type type;
-
- /*
- * The calculated value of the symbol. The SYMBOL_VALID bit is set in
- * 'flags' when this is up to date. Note that this value might differ
- * from the user value set in e.g. a .config file, due to visibility.
- */
- struct symbol_value curr;
-
- /*
- * Values for the symbol provided from outside. def[S_DEF_USER] holds
- * the .config value.
- */
- struct symbol_value def[S_DEF_COUNT];
-
- /*
- * An upper bound on the tristate value the user can set for the symbol
- * if it is a boolean or tristate. Calculated from prompt dependencies,
- * which also inherit dependencies from enclosing menus, choices, and
- * ifs. If 'n', the user value will be ignored.
- *
- * Symbols lacking prompts always have visibility 'n'.
- */
- tristate visible;
-
- /* SYMBOL_* flags */
- int flags;
-
- /* List of properties. See prop_type. */
- struct property *prop;
-
- /* Dependencies from enclosing menus, choices, and ifs */
- struct expr_value dir_dep;
-
- /* Reverse dependencies through being selected by other symbols */
- struct expr_value rev_dep;
-
- /*
- * "Weak" reverse dependencies through being implied by other symbols
- */
- struct expr_value implied;
-};
-
-#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next)
-
-#define SYMBOL_CONST 0x0001 /* symbol is const */
-#define SYMBOL_CHECK 0x0008 /* used during dependency checking */
-#define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */
-#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */
-#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */
-#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */
-#define SYMBOL_WRITE 0x0200 /* write symbol to file (KCONFIG_CONFIG) */
-#define SYMBOL_CHANGED 0x0400 /* ? */
-#define SYMBOL_WRITTEN 0x0800 /* track info to avoid double-write to .config */
-#define SYMBOL_NO_WRITE 0x1000 /* Symbol for internal use only; it will not be written */
-#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */
-#define SYMBOL_WARNED 0x8000 /* warning has been issued */
-
-/* Set when symbol.def[] is used */
-#define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */
-#define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */
-#define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */
-#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */
-#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */
-
-/* choice values need to be set before calculating this symbol value */
-#define SYMBOL_NEED_SET_CHOICE_VALUES 0x100000
-
-#define SYMBOL_MAXLENGTH 256
-#define SYMBOL_HASHSIZE 9973
-
-/* A property represent the config options that can be associated
- * with a config "symbol".
- * Sample:
- * config FOO
- * default y
- * prompt "foo prompt"
- * select BAR
- * config BAZ
- * int "BAZ Value"
- * range 1..255
- *
- * Please, also check parser.y:print_symbol() when modifying the
- * list of property types!
- */
-enum prop_type {
- P_UNKNOWN,
- P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */
- P_COMMENT, /* text associated with a comment */
- P_MENU, /* prompt associated with a menu or menuconfig symbol */
- P_DEFAULT, /* default y */
- P_CHOICE, /* choice value */
- P_SELECT, /* select BAR */
- P_IMPLY, /* imply BAR */
- P_RANGE, /* range 7..100 (for a symbol) */
- P_SYMBOL, /* where a symbol is defined */
-};
-
-struct property {
- struct property *next; /* next property - null if last */
- enum prop_type type; /* type of property */
- const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */
- struct expr_value visible;
- struct expr *expr; /* the optional conditional part of the property */
- struct menu *menu; /* the menu the property are associated with
- * valid for: P_SELECT, P_RANGE, P_CHOICE,
- * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */
- struct file *file; /* what file was this property defined */
- int lineno; /* what lineno was this property defined */
-};
-
-#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)
-
-/*
- * Represents a node in the menu tree, as seen in e.g. menuconfig (though used
- * for all front ends). Each symbol, menu, etc. defined in the Kconfig files
- * gets a node. A symbol defined in multiple locations gets one node at each
- * location.
- */
-struct menu {
- /* The next menu node at the same level */
- struct menu *next;
-
- /* The parent menu node, corresponding to e.g. a menu or choice */
- struct menu *parent;
-
- /* The first child menu node, for e.g. menus and choices */
- struct menu *list;
-
- /*
- * The symbol associated with the menu node. Choices are implemented as
- * a special kind of symbol. NULL for menus, comments, and ifs.
- */
- struct symbol *sym;
-
- /*
- * The prompt associated with the node. This holds the prompt for a
- * symbol as well as the text for a menu or comment, along with the
- * type (P_PROMPT, P_MENU, etc.)
- */
- struct property *prompt;
-
- /*
- * 'visible if' dependencies. If more than one is given, they will be
- * ANDed together.
- */
- struct expr *visibility;
-
- /*
- * Ordinary dependencies from e.g. 'depends on' and 'if', ANDed
- * together
- */
- struct expr *dep;
-
- /* MENU_* flags */
- unsigned int flags;
-
- /* Any help text associated with the node */
- char *help;
-
- /* The location where the menu node appears in the Kconfig files */
- struct file *file;
- int lineno;
-
- /* For use by front ends that need to store auxiliary data */
- void *data;
-};
-
-/*
- * Set on a menu node when the corresponding symbol changes state in some way.
- * Can be checked by front ends.
- */
-#define MENU_CHANGED 0x0001
-
-#define MENU_ROOT 0x0002
-
-struct jump_key {
- struct list_head entries;
- size_t offset;
- struct menu *target;
- int index;
-};
-
-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(const struct expr *org);
-void expr_free(struct expr *e);
-void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
-int expr_eq(struct expr *e1, struct expr *e2);
-tristate expr_calc_value(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_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);
-void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
- tristate pr_type, const char *title);
-
-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);
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* EXPR_H */
diff --git a/tools/kconfig/internal.h b/tools/kconfig/internal.h
deleted file mode 100644
index 2f7298c..0000000
--- a/tools/kconfig/internal.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-#ifndef INTERNAL_H
-#define INTERNAL_H
-
-struct menu;
-
-extern struct menu *current_menu, *current_entry;
-
-#endif /* INTERNAL_H */
diff --git a/tools/kconfig/lexer.l b/tools/kconfig/lexer.l
deleted file mode 100644
index cc386e4..0000000
--- a/tools/kconfig/lexer.l
+++ /dev/null
@@ -1,468 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- */
-%option nostdinit noyywrap never-interactive full ecs
-%option 8bit nodefault yylineno
-%x ASSIGN_VAL HELP STRING
-%{
-
-#include <assert.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "lkc.h"
-#include "parser.tab.h"
-
-#define YY_DECL static int yylex1(void)
-
-#define START_STRSIZE 16
-
-static struct {
- struct file *file;
- int lineno;
-} current_pos;
-
-static int prev_prev_token = T_EOL;
-static int prev_token = T_EOL;
-static char *text;
-static int text_size, text_asize;
-
-struct buffer {
- struct buffer *parent;
- YY_BUFFER_STATE state;
-};
-
-static struct buffer *current_buf;
-
-static int last_ts, first_ts;
-
-static char *expand_token(const char *in, size_t n);
-static void append_expanded_string(const char *in);
-static void zconf_endhelp(void);
-static void zconf_endfile(void);
-
-static void new_string(void)
-{
- text = xmalloc(START_STRSIZE);
- text_asize = START_STRSIZE;
- text_size = 0;
- *text = 0;
-}
-
-static void append_string(const char *str, int size)
-{
- int new_size = text_size + size + 1;
- if (new_size > text_asize) {
- new_size += START_STRSIZE - 1;
- new_size &= -START_STRSIZE;
- text = xrealloc(text, new_size);
- text_asize = new_size;
- }
- memcpy(text + text_size, str, size);
- text_size += size;
- text[text_size] = 0;
-}
-
-static void alloc_string(const char *str, int size)
-{
- text = xmalloc(size + 1);
- memcpy(text, str, size);
- text[size] = 0;
-}
-
-static void warn_ignored_character(char chr)
-{
- fprintf(stderr,
- "%s:%d:warning: ignoring unsupported character '%c'\n",
- current_file->name, yylineno, chr);
-}
-%}
-
-n [A-Za-z0-9_-]
-
-%%
- char open_quote = 0;
-
-#.* /* ignore comment */
-[ \t]* /* whitespaces */
-\\\n /* escaped new line */
-\n return T_EOL;
-"bool" return T_BOOL;
-"choice" return T_CHOICE;
-"comment" return T_COMMENT;
-"config" return T_CONFIG;
-"def_bool" return T_DEF_BOOL;
-"def_tristate" return T_DEF_TRISTATE;
-"default" return T_DEFAULT;
-"depends" return T_DEPENDS;
-"endchoice" return T_ENDCHOICE;
-"endif" return T_ENDIF;
-"endmenu" return T_ENDMENU;
-"help" return T_HELP;
-"hex" return T_HEX;
-"if" return T_IF;
-"imply" return T_IMPLY;
-"int" return T_INT;
-"mainmenu" return T_MAINMENU;
-"menu" return T_MENU;
-"menuconfig" return T_MENUCONFIG;
-"modules" return T_MODULES;
-"on" return T_ON;
-"optional" return T_OPTIONAL;
-"prompt" return T_PROMPT;
-"range" return T_RANGE;
-"select" return T_SELECT;
-"source" return T_SOURCE;
-"string" return T_STRING;
-"tristate" return T_TRISTATE;
-"visible" return T_VISIBLE;
-"||" return T_OR;
-"&&" return T_AND;
-"=" return T_EQUAL;
-"!=" return T_UNEQUAL;
-"<" return T_LESS;
-"<=" return T_LESS_EQUAL;
-">" return T_GREATER;
-">=" return T_GREATER_EQUAL;
-"!" return T_NOT;
-"(" return T_OPEN_PAREN;
-")" return T_CLOSE_PAREN;
-":=" return T_COLON_EQUAL;
-"+=" return T_PLUS_EQUAL;
-\"|\' {
- open_quote = yytext[0];
- new_string();
- BEGIN(STRING);
- }
-{n}+ {
- alloc_string(yytext, yyleng);
- yylval.string = text;
- return T_WORD;
- }
-({n}|$)+ {
- /* this token includes at least one '$' */
- yylval.string = expand_token(yytext, yyleng);
- if (strlen(yylval.string))
- return T_WORD;
- free(yylval.string);
- }
-. warn_ignored_character(*yytext);
-
-<ASSIGN_VAL>{
- [^[:blank:]\n]+.* {
- alloc_string(yytext, yyleng);
- yylval.string = text;
- return T_ASSIGN_VAL;
- }
- \n { BEGIN(INITIAL); return T_EOL; }
- .
-}
-
-<STRING>{
- "$".* append_expanded_string(yytext);
- [^$'"\\\n]+ {
- append_string(yytext, yyleng);
- }
- \\.? {
- append_string(yytext + 1, yyleng - 1);
- }
- \'|\" {
- if (open_quote == yytext[0]) {
- BEGIN(INITIAL);
- yylval.string = text;
- return T_WORD_QUOTE;
- } else
- append_string(yytext, 1);
- }
- \n {
- fprintf(stderr,
- "%s:%d:warning: multi-line strings not supported\n",
- zconf_curname(), zconf_lineno());
- unput('\n');
- BEGIN(INITIAL);
- yylval.string = text;
- return T_WORD_QUOTE;
- }
- <<EOF>> {
- BEGIN(INITIAL);
- yylval.string = text;
- return T_WORD_QUOTE;
- }
-}
-
-<HELP>{
- [ \t]+ {
- int ts, i;
-
- 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] {
- zconf_endhelp();
- return T_HELPTEXT;
- }
- [ \t]*\n {
- append_string("\n", 1);
- }
- [^ \t\n].* {
- while (yyleng) {
- if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
- break;
- yyleng--;
- }
- append_string(yytext, yyleng);
- if (!first_ts)
- first_ts = last_ts;
- }
- <<EOF>> {
- zconf_endhelp();
- return T_HELPTEXT;
- }
-}
-
-<<EOF>> {
- BEGIN(INITIAL);
-
- if (prev_token != T_EOL && prev_token != T_HELPTEXT)
- fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
- current_file->name, yylineno);
-
- if (current_file) {
- zconf_endfile();
- return T_EOL;
- }
- fclose(yyin);
- yyterminate();
-}
-
-%%
-
-/* second stage lexer */
-int yylex(void)
-{
- int token;
-
-repeat:
- token = yylex1();
-
- if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
- if (token == T_EOL) {
- /* Do not pass unneeded T_EOL to the parser. */
- goto repeat;
- } else {
- /*
- * For the parser, update file/lineno at the first token
- * of each statement. Generally, \n is a statement
- * terminator in Kconfig, but it is not always true
- * because \n could be escaped by a backslash.
- */
- current_pos.file = current_file;
- current_pos.lineno = yylineno;
- }
- }
-
- if (prev_prev_token == T_EOL && prev_token == T_WORD &&
- (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
- BEGIN(ASSIGN_VAL);
-
- prev_prev_token = prev_token;
- prev_token = token;
-
- return token;
-}
-
-static char *expand_token(const char *in, size_t n)
-{
- char *out;
- int c;
- char c2;
- const char *rest, *end;
-
- new_string();
- append_string(in, n);
-
- /* get the whole line because we do not know the end of token. */
- while ((c = input()) != EOF) {
- if (c == '\n') {
- unput(c);
- break;
- }
- c2 = c;
- append_string(&c2, 1);
- }
-
- rest = text;
- out = expand_one_token(&rest);
-
- /* push back unused characters to the input stream */
- end = rest + strlen(rest);
- while (end > rest)
- unput(*--end);
-
- free(text);
-
- return out;
-}
-
-static void append_expanded_string(const char *str)
-{
- const char *end;
- char *res;
-
- str++;
-
- res = expand_dollar(&str);
-
- /* push back unused characters to the input stream */
- end = str + strlen(str);
- while (end > str)
- unput(*--end);
-
- append_string(res, strlen(res));
-
- free(res);
-}
-
-void zconf_starthelp(void)
-{
- new_string();
- last_ts = first_ts = 0;
- BEGIN(HELP);
-}
-
-static void zconf_endhelp(void)
-{
- yylval.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 != NULL && name[0] != '/') {
- env = getenv(SRCTREE);
- if (env) {
- snprintf(fullname, sizeof(fullname),
- "%s/%s", env, name);
- f = fopen(fullname, "r");
- }
- }
- return f;
-}
-
-void zconf_initscan(const char *name)
-{
- yyin = zconf_fopen(name);
- if (!yyin) {
- fprintf(stderr, "can't find file %s\n", name);
- exit(1);
- }
-
- current_buf = xmalloc(sizeof(*current_buf));
- memset(current_buf, 0, sizeof(*current_buf));
-
- current_file = file_lookup(name);
- yylineno = 1;
-}
-
-void zconf_nextfile(const char *name)
-{
- struct file *iter;
- struct file *file = file_lookup(name);
- struct buffer *buf = xmalloc(sizeof(*buf));
- memset(buf, 0, sizeof(*buf));
-
- current_buf->state = YY_CURRENT_BUFFER;
- yyin = zconf_fopen(file->name);
- if (!yyin) {
- fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
- zconf_curname(), zconf_lineno(), file->name);
- exit(1);
- }
- yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
- buf->parent = current_buf;
- current_buf = buf;
-
- current_file->lineno = yylineno;
- file->parent = current_file;
-
- for (iter = current_file; iter; iter = iter->parent) {
- if (!strcmp(iter->name, file->name)) {
- fprintf(stderr,
- "Recursive inclusion detected.\n"
- "Inclusion path:\n"
- " current file : %s\n", file->name);
- iter = file;
- do {
- iter = iter->parent;
- fprintf(stderr, " included from: %s:%d\n",
- iter->name, iter->lineno - 1);
- } while (strcmp(iter->name, file->name));
- exit(1);
- }
- }
-
- yylineno = 1;
- current_file = file;
-}
-
-static void zconf_endfile(void)
-{
- struct buffer *parent;
-
- current_file = current_file->parent;
- if (current_file)
- yylineno = current_file->lineno;
-
- 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;
-}
-
-int zconf_lineno(void)
-{
- return current_pos.lineno;
-}
-
-const char *zconf_curname(void)
-{
- return current_pos.file ? current_pos.file->name : "<none>";
-}
diff --git a/tools/kconfig/list.h b/tools/kconfig/list.h
deleted file mode 100644
index 45cb237..0000000
--- a/tools/kconfig/list.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef LIST_H
-#define LIST_H
-
-/*
- * Copied from include/linux/...
- */
-
-#undef offsetof
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-
-/**
- * container_of - cast a member of a structure out to the containing structure
- * @ptr: the pointer to the member.
- * @type: the type of the container struct this is embedded in.
- * @member: the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({ \
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
- struct list_head name = LIST_HEAD_INIT(name)
-
-/**
- * list_entry - get the struct for this entry
- * @ptr: the &struct list_head pointer.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_head within the struct.
- */
-#define list_entry(ptr, type, member) \
- container_of(ptr, type, member)
-
-/**
- * list_for_each_entry - iterate over list of given type
- * @pos: the type * to use as a loop cursor.
- * @head: the head for your list.
- * @member: the name of the list_head within the struct.
- */
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-/**
- * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos: the type * to use as a loop cursor.
- * @n: another type * to use as temporary storage
- * @head: the head for your list.
- * @member: the name of the list_head within the struct.
- */
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-/**
- * list_empty - tests whether a list is empty
- * @head: the list to test.
- */
-static inline int list_empty(const struct list_head *head)
-{
- return head->next == head;
-}
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *_new,
- struct list_head *prev,
- struct list_head *next)
-{
- next->prev = _new;
- _new->next = next;
- _new->prev = prev;
- prev->next = _new;
-}
-
-/**
- * list_add_tail - add a new entry
- * @new: new entry to be added
- * @head: list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static inline void list_add_tail(struct list_head *_new, struct list_head *head)
-{
- __list_add(_new, head->prev, head);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head *prev, struct list_head *next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-#define LIST_POISON1 ((void *) 0x00100100)
-#define LIST_POISON2 ((void *) 0x00200200)
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty() on entry does not return true after this, the entry is
- * in an undefined state.
- */
-static inline void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- entry->next = (struct list_head*)LIST_POISON1;
- entry->prev = (struct list_head*)LIST_POISON2;
-}
-#endif
diff --git a/tools/kconfig/lkc.h b/tools/kconfig/lkc.h
deleted file mode 100644
index e7118d6..0000000
--- a/tools/kconfig/lkc.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- */
-
-#ifndef LKC_H
-#define LKC_H
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "expr.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "lkc_proto.h"
-
-#define SRCTREE "srctree"
-
-#ifndef CONFIG_
-#define CONFIG_ "CONFIG_"
-#endif
-static inline const char *CONFIG_prefix(void)
-{
- return getenv( "CONFIG_" ) ?: CONFIG_;
-}
-#undef CONFIG_
-#define CONFIG_ CONFIG_prefix()
-
-extern int yylineno;
-void zconfdump(FILE *out);
-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);
-const char *zconf_curname(void);
-
-/* confdata.c */
-const char *conf_get_configname(void);
-void set_all_choice_values(struct symbol *csym);
-
-/* confdata.c and expr.c */
-static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
-{
- assert(len != 0);
-
- if (fwrite(str, len, count, out) != count)
- fprintf(stderr, "Error in writing or end of file.\n");
-}
-
-/* util.c */
-struct file *file_lookup(const char *name);
-void *xmalloc(size_t size);
-void *xcalloc(size_t nmemb, size_t size);
-void *xrealloc(void *p, size_t size);
-char *xstrdup(const char *s);
-char *xstrndup(const char *s, size_t n);
-
-/* lexer.l */
-int yylex(void);
-
-struct gstr {
- size_t len;
- char *s;
- /*
- * when max_width is not zero long lines in string s (if any) get
- * wrapped not to exceed the max_width value
- */
- int max_width;
-};
-struct gstr str_new(void);
-void str_free(struct gstr *gs);
-void str_append(struct gstr *gs, const char *s);
-void str_printf(struct gstr *gs, const char *fmt, ...);
-char *str_get(struct gstr *gs);
-
-/* menu.c */
-void _menu_init(void);
-void menu_warn(struct menu *menu, const char *fmt, ...);
-struct menu *menu_add_menu(void);
-void menu_end_menu(void);
-void menu_add_entry(struct symbol *sym);
-void menu_add_dep(struct expr *dep);
-void menu_add_visibility(struct expr *dep);
-struct property *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);
-
-extern struct menu rootmenu;
-
-bool menu_is_empty(struct menu *menu);
-bool menu_is_visible(struct menu *menu);
-bool menu_has_prompt(struct menu *menu);
-const char *menu_get_prompt(struct menu *menu);
-struct menu *menu_get_parent_menu(struct menu *menu);
-bool menu_has_help(struct menu *menu);
-const char *menu_get_help(struct menu *menu);
-struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
-void menu_get_ext_help(struct menu *menu, struct gstr *help);
-
-/* symbol.c */
-void sym_clear_all_valid(void);
-struct symbol *sym_choice_default(struct symbol *sym);
-struct property *sym_get_range_prop(struct symbol *sym);
-const char *sym_get_string_default(struct symbol *sym);
-struct symbol *sym_check_deps(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_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_DEF_USER ? true : false;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LKC_H */
diff --git a/tools/kconfig/lkc_proto.h b/tools/kconfig/lkc_proto.h
deleted file mode 100644
index edd1e61..0000000
--- a/tools/kconfig/lkc_proto.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <stdarg.h>
-
-/* confdata.c */
-void conf_parse(const char *name);
-int conf_read(const char *name);
-int conf_read_simple(const char *name, int);
-int conf_write_defconfig(const char *name);
-int conf_write(const char *name);
-int conf_write_autoconf(int overwrite);
-void conf_set_changed(bool val);
-bool conf_get_changed(void);
-void conf_set_changed_callback(void (*fn)(void));
-void conf_set_message_callback(void (*fn)(const char *s));
-
-/* symbol.c */
-extern struct symbol * symbol_hash[SYMBOL_HASHSIZE];
-
-struct symbol * sym_lookup(const char *name, int flags);
-struct symbol * sym_find(const char *name);
-void print_symbol_for_listconfig(struct symbol *sym);
-struct symbol ** sym_re_search(const char *pattern);
-const char * sym_type_name(enum symbol_type type);
-void sym_calc_value(struct symbol *sym);
-enum symbol_type sym_get_type(struct symbol *sym);
-bool sym_tristate_within_range(struct symbol *sym,tristate tri);
-bool sym_set_tristate_value(struct symbol *sym,tristate tri);
-tristate sym_toggle_tristate_value(struct symbol *sym);
-bool sym_string_valid(struct symbol *sym, const char *newval);
-bool sym_string_within_range(struct symbol *sym, const char *str);
-bool sym_set_string_value(struct symbol *sym, const char *newval);
-bool sym_is_changeable(struct symbol *sym);
-struct property * sym_get_choice_prop(struct symbol *sym);
-const char * sym_get_string_value(struct symbol *sym);
-
-const char * prop_get_type_name(enum prop_type type);
-
-/* preprocess.c */
-enum variable_flavor {
- VAR_SIMPLE,
- VAR_RECURSIVE,
- VAR_APPEND,
-};
-void env_write_dep(FILE *f, const char *auto_conf_name);
-void variable_add(const char *name, const char *value,
- enum variable_flavor flavor);
-void variable_all_del(void);
-char *expand_dollar(const char **str);
-char *expand_one_token(const char **str);
-
-/* expr.c */
-void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken);
diff --git a/tools/kconfig/lxdialog/BIG.FAT.WARNING b/tools/kconfig/lxdialog/BIG.FAT.WARNING
deleted file mode 100644
index 7cb5a7e..0000000
--- a/tools/kconfig/lxdialog/BIG.FAT.WARNING
+++ /dev/null
@@ -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.
diff --git a/tools/kconfig/lxdialog/checklist.c b/tools/kconfig/lxdialog/checklist.c
deleted file mode 100644
index fd161cf..0000000
--- a/tools/kconfig/lxdialog/checklist.c
+++ /dev/null
@@ -1,319 +0,0 @@
-// SPDX-License-Identifier: GPL-2.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)
- */
-
-#include "dialog.h"
-
-static int list_width, check_x, item_x;
-
-/*
- * Print list item
- */
-static void print_item(WINDOW * win, int choice, int selected)
-{
- int i;
- char *list_item = malloc(list_width + 1);
-
- strncpy(list_item, item_str(), list_width - item_x);
- list_item[list_width - item_x] = '\0';
-
- /* Clear 'residue' of last item */
- wattrset(win, dlg.menubox.atr);
- wmove(win, choice, 0);
- for (i = 0; i < list_width; i++)
- waddch(win, ' ');
-
- wmove(win, choice, check_x);
- wattrset(win, selected ? dlg.check_selected.atr
- : dlg.check.atr);
- if (!item_is_tag(':'))
- wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
-
- wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
- mvwaddch(win, choice, item_x, list_item[0]);
- wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
- waddstr(win, list_item + 1);
- if (selected) {
- wmove(win, choice, check_x + 1);
- wrefresh(win);
- }
- free(list_item);
-}
-
-/*
- * 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, dlg.uarrow.atr);
- waddch(win, ACS_UARROW);
- waddstr(win, "(-)");
- } else {
- wattrset(win, dlg.menubox.atr);
- 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, dlg.darrow.atr);
- waddch(win, ACS_DARROW);
- waddstr(win, "(+)");
- } else {
- wattrset(win, dlg.menubox_border.atr);
- 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
- * in the style of radiolist (only one option turned on at a time).
- */
-int dialog_checklist(const char *title, const char *prompt, int height,
- int width, int list_height)
-{
- int i, x, y, box_x, box_y;
- int key = 0, button = 0, choice = 0, scroll = 0, max_choice;
- WINDOW *dialog, *list;
-
- /* which item to highlight */
- item_foreach() {
- if (item_is_tag('X'))
- choice = item_n();
- if (item_is_selected()) {
- choice = item_n();
- break;
- }
- }
-
-do_resize:
- if (getmaxy(stdscr) < (height + CHECKLIST_HEIGTH_MIN))
- return -ERRDISPLAYTOOSMALL;
- if (getmaxx(stdscr) < (width + CHECKLIST_WIDTH_MIN))
- return -ERRDISPLAYTOOSMALL;
-
- max_choice = MIN(list_height, item_count());
-
- /* center dialog box on screen */
- x = (getmaxx(stdscr) - width) / 2;
- y = (getmaxy(stdscr) - 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,
- dlg.dialog.atr, dlg.border.atr);
- wattrset(dialog, dlg.border.atr);
- mvwaddch(dialog, height - 3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch(dialog, ACS_HLINE);
- wattrset(dialog, dlg.dialog.atr);
- waddch(dialog, ACS_RTEE);
-
- print_title(dialog, title, width);
-
- wattrset(dialog, dlg.dialog.atr);
- 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,
- dlg.menubox_border.atr, dlg.menubox.atr);
-
- /* Find length of longest item in order to center checklist */
- check_x = 0;
- item_foreach()
- check_x = MAX(check_x, strlen(item_str()) + 4);
- check_x = MIN(check_x, list_width);
-
- 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++) {
- item_set(scroll + i);
- print_item(list, i, i == choice);
- }
-
- print_arrows(dialog, choice, item_count(), scroll,
- box_y, box_x + check_x + 5, list_height);
-
- print_buttons(dialog, height, width, 0);
-
- wnoutrefresh(dialog);
- wnoutrefresh(list);
- doupdate();
-
- while (key != KEY_ESC) {
- key = wgetch(dialog);
-
- for (i = 0; i < max_choice; i++) {
- item_set(i + scroll);
- if (toupper(key) == toupper(item_str()[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 */
- item_set(scroll);
- print_item(list, 0, FALSE);
- scrollok(list, TRUE);
- wscrl(list, -1);
- scrollok(list, FALSE);
- }
- scroll--;
- item_set(scroll);
- print_item(list, 0, TRUE);
- print_arrows(dialog, choice, item_count(),
- scroll, box_y, box_x + check_x + 5, list_height);
-
- wnoutrefresh(dialog);
- wrefresh(list);
-
- 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_count() - 1)
- continue;
- /* Scroll list up */
- if (list_height > 1) {
- /* De-highlight current last item before scrolling up */
- item_set(scroll + max_choice - 1);
- print_item(list,
- max_choice - 1,
- FALSE);
- scrollok(list, TRUE);
- wscrl(list, 1);
- scrollok(list, FALSE);
- }
- scroll++;
- item_set(scroll + max_choice - 1);
- print_item(list, max_choice - 1, TRUE);
-
- print_arrows(dialog, choice, item_count(),
- scroll, box_y, box_x + check_x + 5, list_height);
-
- wnoutrefresh(dialog);
- wrefresh(list);
-
- continue; /* wait for another key press */
- } else
- i = choice + 1;
- }
- if (i != choice) {
- /* De-highlight current item */
- item_set(scroll + choice);
- print_item(list, choice, FALSE);
- /* Highlight new item */
- choice = i;
- item_set(scroll + choice);
- print_item(list, choice, TRUE);
- wnoutrefresh(dialog);
- wrefresh(list);
- }
- continue; /* wait for another key press */
- }
- switch (key) {
- case 'H':
- case 'h':
- case '?':
- button = 1;
- /* fall-through */
- case 'S':
- case 's':
- case ' ':
- case '\n':
- item_foreach()
- item_set_selected(0);
- item_set(scroll + choice);
- item_set_selected(1);
- delwin(list);
- delwin(dialog);
- return button;
- 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 'X':
- case 'x':
- key = KEY_ESC;
- break;
- case KEY_ESC:
- key = on_key_esc(dialog);
- break;
- case KEY_RESIZE:
- delwin(list);
- delwin(dialog);
- on_key_resize();
- goto do_resize;
- }
-
- /* Now, update everything... */
- doupdate();
- }
- delwin(list);
- delwin(dialog);
- return key; /* ESC pressed */
-}
diff --git a/tools/kconfig/lxdialog/dialog.h b/tools/kconfig/lxdialog/dialog.h
deleted file mode 100644
index 68b565e..0000000
--- a/tools/kconfig/lxdialog/dialog.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * dialog.h -- common declarations for all dialog modules
- *
- * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- */
-
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-
-#ifdef __sun__
-#define CURS_MACROS
-#endif
-#include <ncurses.h>
-
-/*
- * 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 KEY_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
-
-/* error return codes */
-#define ERRDISPLAYTOOSMALL (KEY_MAX + 1)
-
-/*
- * Color definitions
- */
-struct dialog_color {
- chtype atr; /* Color attribute */
- int fg; /* foreground */
- int bg; /* background */
- int hl; /* highlight this item */
-};
-
-struct subtitle_list {
- struct subtitle_list *next;
- const char *text;
-};
-
-struct dialog_info {
- const char *backtitle;
- struct subtitle_list *subtitles;
- struct dialog_color screen;
- struct dialog_color shadow;
- struct dialog_color dialog;
- struct dialog_color title;
- struct dialog_color border;
- struct dialog_color button_active;
- struct dialog_color button_inactive;
- struct dialog_color button_key_active;
- struct dialog_color button_key_inactive;
- struct dialog_color button_label_active;
- struct dialog_color button_label_inactive;
- struct dialog_color inputbox;
- struct dialog_color inputbox_border;
- struct dialog_color searchbox;
- struct dialog_color searchbox_title;
- struct dialog_color searchbox_border;
- struct dialog_color position_indicator;
- struct dialog_color menubox;
- struct dialog_color menubox_border;
- struct dialog_color item;
- struct dialog_color item_selected;
- struct dialog_color tag;
- struct dialog_color tag_selected;
- struct dialog_color tag_key;
- struct dialog_color tag_key_selected;
- struct dialog_color check;
- struct dialog_color check_selected;
- struct dialog_color uarrow;
- struct dialog_color darrow;
-};
-
-/*
- * Global variables
- */
-extern struct dialog_info dlg;
-extern char dialog_input_result[];
-extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */
-
-/*
- * Function prototypes
- */
-
-/* item list as used by checklist and menubox */
-void item_reset(void);
-void item_make(const char *fmt, ...);
-void item_add_str(const char *fmt, ...);
-void item_set_tag(char tag);
-void item_set_data(void *p);
-void item_set_selected(int val);
-int item_activate_selected(void);
-void *item_data(void);
-char item_tag(void);
-
-/* item list manipulation for lxdialog use */
-#define MAXITEMSTR 200
-struct dialog_item {
- char str[MAXITEMSTR]; /* prompt displayed */
- char tag;
- void *data; /* pointer to menu item - used by menubox+checklist */
- int selected; /* Set to 1 by dialog_*() function if selected. */
-};
-
-/* list of lialog_items */
-struct dialog_list {
- struct dialog_item node;
- struct dialog_list *next;
-};
-
-extern struct dialog_list *item_cur;
-extern struct dialog_list item_nil;
-extern struct dialog_list *item_head;
-
-int item_count(void);
-void item_set(int n);
-int item_n(void);
-const char *item_str(void);
-int item_is_selected(void);
-int item_is_tag(char tag);
-#define item_foreach() \
- for (item_cur = item_head ? item_head: item_cur; \
- item_cur && (item_cur != &item_nil); item_cur = item_cur->next)
-
-/* generic key handlers */
-int on_key_esc(WINDOW *win);
-int on_key_resize(void);
-
-/* minimum (re)size values */
-#define CHECKLIST_HEIGTH_MIN 6 /* For dialog_checklist() */
-#define CHECKLIST_WIDTH_MIN 6
-#define INPUTBOX_HEIGTH_MIN 2 /* For dialog_inputbox() */
-#define INPUTBOX_WIDTH_MIN 2
-#define MENUBOX_HEIGTH_MIN 15 /* For dialog_menu() */
-#define MENUBOX_WIDTH_MIN 65
-#define TEXTBOX_HEIGTH_MIN 8 /* For dialog_textbox() */
-#define TEXTBOX_WIDTH_MIN 8
-#define YESNO_HEIGTH_MIN 4 /* For dialog_yesno() */
-#define YESNO_WIDTH_MIN 4
-#define WINDOW_HEIGTH_MIN 19 /* For init_dialog() */
-#define WINDOW_WIDTH_MIN 80
-
-int init_dialog(const char *backtitle);
-void set_dialog_backtitle(const char *backtitle);
-void set_dialog_subtitles(struct subtitle_list *subtitles);
-void end_dialog(int x, int y);
-void attr_clear(WINDOW * win, int height, int width, chtype attr);
-void dialog_clear(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 print_title(WINDOW *dialog, const char *title, int width);
-void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box,
- chtype border);
-void draw_shadow(WINDOW * win, int y, int x, int height, int width);
-
-int first_alpha(const char *string, const char *exempt);
-int dialog_yesno(const char *title, const char *prompt, int height, int width);
-int dialog_msgbox(const char *title, const char *prompt, int height,
- int width, int pause);
-
-
-typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
- *_data);
-int dialog_textbox(const char *title, char *tbuf, int initial_height,
- int initial_width, int *keys, int *_vscroll, int *_hscroll,
- update_text_fn update_text, void *data);
-int dialog_menu(const char *title, const char *prompt,
- const void *selected, int *s_scroll);
-int dialog_checklist(const char *title, const char *prompt, int height,
- int width, int list_height);
-int dialog_inputbox(const char *title, const char *prompt, int height,
- int width, const char *init);
-
-/*
- * This is the base for fictitious keys, which activate
- * the buttons.
- *
- * Mouse-generated keys are the following:
- * -- the first 32 are used as numbers, in addition to '0'-'9'
- * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o')
- * -- uppercase chars are used to invoke the button (M_EVENT + 'O')
- */
-#define M_EVENT (KEY_MAX+1)
diff --git a/tools/kconfig/lxdialog/inputbox.c b/tools/kconfig/lxdialog/inputbox.c
deleted file mode 100644
index 1dcfb28..0000000
--- a/tools/kconfig/lxdialog/inputbox.c
+++ /dev/null
@@ -1,289 +0,0 @@
-// SPDX-License-Identifier: GPL-2.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)
- */
-
-#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, key = 0, button = -1;
- int show_x, len, pos;
- char *instr = dialog_input_result;
- WINDOW *dialog;
-
- if (!init)
- instr[0] = '\0';
- else
- strcpy(instr, init);
-
-do_resize:
- if (getmaxy(stdscr) <= (height - INPUTBOX_HEIGTH_MIN))
- return -ERRDISPLAYTOOSMALL;
- if (getmaxx(stdscr) <= (width - INPUTBOX_WIDTH_MIN))
- return -ERRDISPLAYTOOSMALL;
-
- /* center dialog box on screen */
- x = (getmaxx(stdscr) - width) / 2;
- y = (getmaxy(stdscr) - 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,
- dlg.dialog.atr, dlg.border.atr);
- wattrset(dialog, dlg.border.atr);
- mvwaddch(dialog, height - 3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch(dialog, ACS_HLINE);
- wattrset(dialog, dlg.dialog.atr);
- waddch(dialog, ACS_RTEE);
-
- print_title(dialog, title, width);
-
- wattrset(dialog, dlg.dialog.atr);
- 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,
- dlg.dialog.atr, dlg.border.atr);
-
- print_buttons(dialog, height, width, 0);
-
- /* Set up the initial value */
- wmove(dialog, box_y, box_x);
- wattrset(dialog, dlg.inputbox.atr);
-
- len = strlen(instr);
- pos = len;
-
- if (len >= box_width) {
- show_x = len - box_width + 1;
- input_x = box_width - 1;
- for (i = 0; i < box_width - 1; i++)
- waddch(dialog, instr[show_x + i]);
- } else {
- show_x = 0;
- input_x = len;
- waddstr(dialog, instr);
- }
-
- wmove(dialog, box_y, box_x + input_x);
-
- wrefresh(dialog);
-
- while (key != KEY_ESC) {
- key = wgetch(dialog);
-
- if (button == -1) { /* Input box selected */
- switch (key) {
- case TAB:
- case KEY_UP:
- case KEY_DOWN:
- break;
- case KEY_BACKSPACE:
- case 8: /* ^H */
- case 127: /* ^? */
- if (pos) {
- wattrset(dialog, dlg.inputbox.atr);
- if (input_x == 0) {
- show_x--;
- } else
- input_x--;
-
- if (pos < len) {
- for (i = pos - 1; i < len; i++) {
- instr[i] = instr[i+1];
- }
- }
-
- pos--;
- len--;
- instr[len] = '\0';
- wmove(dialog, box_y, box_x);
- for (i = 0; i < box_width; i++) {
- if (!instr[show_x + i]) {
- waddch(dialog, ' ');
- break;
- }
- waddch(dialog, instr[show_x + i]);
- }
- wmove(dialog, box_y, input_x + box_x);
- wrefresh(dialog);
- }
- continue;
- case KEY_LEFT:
- if (pos > 0) {
- if (input_x > 0) {
- wmove(dialog, box_y, --input_x + box_x);
- } else if (input_x == 0) {
- show_x--;
- wmove(dialog, box_y, box_x);
- for (i = 0; i < box_width; i++) {
- if (!instr[show_x + i]) {
- waddch(dialog, ' ');
- break;
- }
- waddch(dialog, instr[show_x + i]);
- }
- wmove(dialog, box_y, box_x);
- }
- pos--;
- }
- continue;
- case KEY_RIGHT:
- if (pos < len) {
- if (input_x < box_width - 1) {
- wmove(dialog, box_y, ++input_x + box_x);
- } else if (input_x == box_width - 1) {
- show_x++;
- wmove(dialog, box_y, box_x);
- for (i = 0; i < box_width; i++) {
- if (!instr[show_x + i]) {
- waddch(dialog, ' ');
- break;
- }
- waddch(dialog, instr[show_x + i]);
- }
- wmove(dialog, box_y, input_x + box_x);
- }
- pos++;
- }
- continue;
- default:
- if (key < 0x100 && isprint(key)) {
- if (len < MAX_LEN) {
- wattrset(dialog, dlg.inputbox.atr);
- if (pos < len) {
- for (i = len; i > pos; i--)
- instr[i] = instr[i-1];
- instr[pos] = key;
- } else {
- instr[len] = key;
- }
- pos++;
- len++;
- instr[len] = '\0';
-
- if (input_x == box_width - 1) {
- show_x++;
- } else {
- input_x++;
- }
-
- wmove(dialog, box_y, box_x);
- for (i = 0; i < box_width; i++) {
- if (!instr[show_x + i]) {
- waddch(dialog, ' ');
- break;
- }
- waddch(dialog, instr[show_x + i]);
- }
- wmove(dialog, box_y, input_x + box_x);
- 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 "Help" 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 "Help" 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 = KEY_ESC;
- break;
- case KEY_ESC:
- key = on_key_esc(dialog);
- break;
- case KEY_RESIZE:
- delwin(dialog);
- on_key_resize();
- goto do_resize;
- }
- }
-
- delwin(dialog);
- return KEY_ESC; /* ESC pressed */
-}
diff --git a/tools/kconfig/lxdialog/menubox.c b/tools/kconfig/lxdialog/menubox.c
deleted file mode 100644
index 58c2f8a..0000000
--- a/tools/kconfig/lxdialog/menubox.c
+++ /dev/null
@@ -1,424 +0,0 @@
-// SPDX-License-Identifier: GPL-2.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)
- */
-
-/*
- * 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 do_print_item(WINDOW * win, const char *item, int line_y,
- int selected, int hotkey)
-{
- int j;
- char *menu_item = malloc(menu_width + 1);
-
- strncpy(menu_item, item, menu_width - item_x);
- menu_item[menu_width - item_x] = '\0';
- j = first_alpha(menu_item, "YyNnMmHh");
-
- /* Clear 'residue' of last item */
- wattrset(win, dlg.menubox.atr);
- wmove(win, line_y, 0);
-#if OLD_NCURSES
- {
- int i;
- for (i = 0; i < menu_width; i++)
- waddch(win, ' ');
- }
-#else
- wclrtoeol(win);
-#endif
- wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
- mvwaddstr(win, line_y, item_x, menu_item);
- if (hotkey) {
- wattrset(win, selected ? dlg.tag_key_selected.atr
- : dlg.tag_key.atr);
- mvwaddch(win, line_y, item_x + j, menu_item[j]);
- }
- if (selected) {
- wmove(win, line_y, item_x + 1);
- }
- free(menu_item);
- wrefresh(win);
-}
-
-#define print_item(index, choice, selected) \
-do { \
- item_set(index); \
- do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
-} while (0)
-
-/*
- * 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, dlg.uarrow.atr);
- waddch(win, ACS_UARROW);
- waddstr(win, "(-)");
- } else {
- wattrset(win, dlg.menubox.atr);
- waddch(win, ACS_HLINE);
- waddch(win, ACS_HLINE);
- waddch(win, ACS_HLINE);
- waddch(win, ACS_HLINE);
- }
-
- y = y + height + 1;
- wmove(win, y, x);
- wrefresh(win);
-
- if ((height < item_no) && (scroll + height < item_no)) {
- wattrset(win, dlg.darrow.atr);
- waddch(win, ACS_DARROW);
- waddstr(win, "(+)");
- } else {
- wattrset(win, dlg.menubox_border.atr);
- waddch(win, ACS_HLINE);
- waddch(win, ACS_HLINE);
- waddch(win, ACS_HLINE);
- waddch(win, ACS_HLINE);
- }
-
- wmove(win, cur_y, cur_x);
- wrefresh(win);
-}
-
-/*
- * Display the termination buttons.
- */
-static void print_buttons(WINDOW * win, int height, int width, int selected)
-{
- int x = width / 2 - 28;
- 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);
- print_button(win, " Save ", y, x + 36, selected == 3);
- print_button(win, " Load ", y, x + 48, selected == 4);
-
- wmove(win, y, x + 1 + 12 * selected);
- wrefresh(win);
-}
-
-/* scroll up n lines (n may be negative) */
-static void do_scroll(WINDOW *win, int *scroll, int n)
-{
- /* Scroll menu up */
- scrollok(win, TRUE);
- wscrl(win, n);
- scrollok(win, FALSE);
- *scroll = *scroll + n;
- wrefresh(win);
-}
-
-/*
- * Display a menu for choosing among a number of options
- */
-int dialog_menu(const char *title, const char *prompt,
- const void *selected, int *s_scroll)
-{
- int i, j, x, y, box_x, box_y;
- int height, width, menu_height;
- int key = 0, button = 0, scroll = 0, choice = 0;
- int first_item = 0, max_choice;
- WINDOW *dialog, *menu;
-
-do_resize:
- height = getmaxy(stdscr);
- width = getmaxx(stdscr);
- if (height < MENUBOX_HEIGTH_MIN || width < MENUBOX_WIDTH_MIN)
- return -ERRDISPLAYTOOSMALL;
-
- height -= 4;
- width -= 5;
- menu_height = height - 10;
-
- max_choice = MIN(menu_height, item_count());
-
- /* center dialog box on screen */
- x = (getmaxx(stdscr) - width) / 2;
- y = (getmaxy(stdscr) - 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,
- dlg.dialog.atr, dlg.border.atr);
- wattrset(dialog, dlg.border.atr);
- mvwaddch(dialog, height - 3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch(dialog, ACS_HLINE);
- wattrset(dialog, dlg.dialog.atr);
- wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
- waddch(dialog, ACS_RTEE);
-
- print_title(dialog, title, width);
-
- wattrset(dialog, dlg.dialog.atr);
- 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,
- dlg.menubox_border.atr, dlg.menubox.atr);
-
- if (menu_width >= 80)
- item_x = (menu_width - 70) / 2;
- else
- item_x = 4;
-
- /* Set choice to default item */
- item_foreach()
- if (selected && (selected == item_data()))
- choice = item_n();
- /* get the saved scroll info */
- scroll = *s_scroll;
- if ((scroll <= choice) && (scroll + max_choice > choice) &&
- (scroll >= 0) && (scroll + max_choice <= item_count())) {
- first_item = scroll;
- choice = choice - scroll;
- } else {
- scroll = 0;
- }
- if ((choice >= max_choice)) {
- if (choice >= item_count() - max_choice / 2)
- scroll = first_item = item_count() - 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(first_item + i, i, i == choice);
- }
-
- wnoutrefresh(menu);
-
- print_arrows(dialog, item_count(), scroll,
- box_y, box_x + item_x + 1, menu_height);
-
- print_buttons(dialog, height, width, 0);
- wmove(menu, choice, item_x + 1);
- wrefresh(menu);
-
- while (key != 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++) {
- item_set(scroll + i);
- j = first_alpha(item_str(), "YyNnMmHh");
- if (key == tolower(item_str()[j]))
- break;
- }
- if (i == max_choice)
- for (i = 0; i < max_choice; i++) {
- item_set(scroll + i);
- j = first_alpha(item_str(), "YyNnMmHh");
- if (key == tolower(item_str()[j]))
- break;
- }
- }
-
- if (item_count() != 0 &&
- (i < max_choice ||
- key == KEY_UP || key == KEY_DOWN ||
- key == '-' || key == '+' ||
- key == KEY_PPAGE || key == KEY_NPAGE)) {
- /* Remove highligt of current item */
- print_item(scroll + choice, choice, FALSE);
-
- if (key == KEY_UP || key == '-') {
- if (choice < 2 && scroll) {
- /* Scroll menu down */
- do_scroll(menu, &scroll, -1);
-
- print_item(scroll, 0, FALSE);
- } else
- choice = MAX(choice - 1, 0);
-
- } else if (key == KEY_DOWN || key == '+') {
- print_item(scroll+choice, choice, FALSE);
-
- if ((choice > max_choice - 3) &&
- (scroll + max_choice < item_count())) {
- /* Scroll menu up */
- do_scroll(menu, &scroll, 1);
-
- print_item(scroll+max_choice - 1,
- max_choice - 1, FALSE);
- } 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) {
- do_scroll(menu, &scroll, -1);
- print_item(scroll, 0, FALSE);
- } else {
- if (choice > 0)
- choice--;
- }
- }
-
- } else if (key == KEY_NPAGE) {
- for (i = 0; (i < max_choice); i++) {
- if (scroll + max_choice < item_count()) {
- do_scroll(menu, &scroll, 1);
- print_item(scroll+max_choice-1,
- max_choice - 1, FALSE);
- } else {
- if (choice + 1 < max_choice)
- choice++;
- }
- }
- } else
- choice = i;
-
- print_item(scroll + choice, choice, TRUE);
-
- print_arrows(dialog, item_count(), 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)
- ? 4 : (button > 4 ? 0 : button);
-
- print_buttons(dialog, height, width, button);
- wrefresh(menu);
- break;
- case ' ':
- case 's':
- case 'y':
- case 'n':
- case 'm':
- case '/':
- case 'h':
- case '?':
- case 'z':
- case '\n':
- /* save scroll info */
- *s_scroll = scroll;
- delwin(menu);
- delwin(dialog);
- item_set(scroll + choice);
- item_set_selected(1);
- switch (key) {
- case 'h':
- case '?':
- return 2;
- case 's':
- case 'y':
- return 5;
- case 'n':
- return 6;
- case 'm':
- return 7;
- case ' ':
- return 8;
- case '/':
- return 9;
- case 'z':
- return 10;
- case '\n':
- return button;
- }
- return 0;
- case 'e':
- case 'x':
- key = KEY_ESC;
- break;
- case KEY_ESC:
- key = on_key_esc(menu);
- break;
- case KEY_RESIZE:
- on_key_resize();
- delwin(menu);
- delwin(dialog);
- goto do_resize;
- }
- }
- delwin(menu);
- delwin(dialog);
- return key; /* ESC pressed */
-}
diff --git a/tools/kconfig/lxdialog/textbox.c b/tools/kconfig/lxdialog/textbox.c
deleted file mode 100644
index 4e339b1..0000000
--- a/tools/kconfig/lxdialog/textbox.c
+++ /dev/null
@@ -1,395 +0,0 @@
-// SPDX-License-Identifier: GPL-2.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)
- */
-
-#include "dialog.h"
-
-static void back_lines(int n);
-static void print_page(WINDOW *win, int height, int width, update_text_fn
- update_text, void *data);
-static void print_line(WINDOW *win, int row, int width);
-static char *get_line(void);
-static void print_position(WINDOW * win);
-
-static int hscroll;
-static int begin_reached, end_reached, page_length;
-static char *buf;
-static char *page;
-
-/*
- * refresh window content
- */
-static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
- int cur_y, int cur_x, update_text_fn update_text,
- void *data)
-{
- print_page(box, boxh, boxw, update_text, data);
- print_position(dialog);
- wmove(dialog, cur_y, cur_x); /* Restore cursor position */
- wrefresh(dialog);
-}
-
-
-/*
- * Display text from a file in a dialog box.
- *
- * keys is a null-terminated array
- * update_text() may not add or remove any '\n' or '\0' in tbuf
- */
-int dialog_textbox(const char *title, char *tbuf, int initial_height,
- int initial_width, int *keys, int *_vscroll, int *_hscroll,
- update_text_fn update_text, void *data)
-{
- int i, x, y, cur_x, cur_y, key = 0;
- int height, width, boxh, boxw;
- WINDOW *dialog, *box;
- bool done = false;
-
- begin_reached = 1;
- end_reached = 0;
- page_length = 0;
- hscroll = 0;
- buf = tbuf;
- page = buf; /* page is pointer to start of page to be displayed */
-
- if (_vscroll && *_vscroll) {
- begin_reached = 0;
-
- for (i = 0; i < *_vscroll; i++)
- get_line();
- }
- if (_hscroll)
- hscroll = *_hscroll;
-
-do_resize:
- getmaxyx(stdscr, height, width);
- if (height < TEXTBOX_HEIGTH_MIN || width < TEXTBOX_WIDTH_MIN)
- return -ERRDISPLAYTOOSMALL;
- if (initial_height != 0)
- height = initial_height;
- else
- if (height > 4)
- height -= 4;
- else
- height = 0;
- if (initial_width != 0)
- width = initial_width;
- else
- if (width > 5)
- width -= 5;
- else
- width = 0;
-
- /* center dialog box on screen */
- x = (getmaxx(stdscr) - width) / 2;
- y = (getmaxy(stdscr) - height) / 2;
-
- draw_shadow(stdscr, y, x, height, width);
-
- dialog = newwin(height, width, y, x);
- keypad(dialog, TRUE);
-
- /* Create window for box region, used for scrolling text */
- boxh = height - 4;
- boxw = width - 2;
- box = subwin(dialog, boxh, boxw, y + 1, x + 1);
- wattrset(box, dlg.dialog.atr);
- wbkgdset(box, dlg.dialog.atr & A_COLOR);
-
- keypad(box, TRUE);
-
- /* register the new window, along with its borders */
- draw_box(dialog, 0, 0, height, width,
- dlg.dialog.atr, dlg.border.atr);
-
- wattrset(dialog, dlg.border.atr);
- mvwaddch(dialog, height - 3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch(dialog, ACS_HLINE);
- wattrset(dialog, dlg.dialog.atr);
- wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
- waddch(dialog, ACS_RTEE);
-
- print_title(dialog, title, width);
-
- print_button(dialog, " Exit ", height - 2, width / 2 - 4, TRUE);
- wnoutrefresh(dialog);
- getyx(dialog, cur_y, cur_x); /* Save cursor position */
-
- /* Print first page of text */
- attr_clear(box, boxh, boxw, dlg.dialog.atr);
- refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
- data);
-
- while (!done) {
- key = wgetch(dialog);
- switch (key) {
- case 'E': /* Exit */
- case 'e':
- case 'X':
- case 'x':
- case 'q':
- case '\n':
- done = true;
- break;
- case 'g': /* First page */
- case KEY_HOME:
- if (!begin_reached) {
- begin_reached = 1;
- page = buf;
- refresh_text_box(dialog, box, boxh, boxw,
- cur_y, cur_x, update_text,
- data);
- }
- break;
- case 'G': /* Last page */
- case KEY_END:
-
- end_reached = 1;
- /* point to last char in buf */
- page = buf + strlen(buf);
- back_lines(boxh);
- refresh_text_box(dialog, box, boxh, boxw, cur_y,
- cur_x, update_text, data);
- break;
- case 'K': /* Previous line */
- case 'k':
- case KEY_UP:
- if (begin_reached)
- break;
-
- back_lines(page_length + 1);
- refresh_text_box(dialog, box, boxh, boxw, cur_y,
- cur_x, update_text, data);
- break;
- case 'B': /* Previous page */
- case 'b':
- case 'u':
- case KEY_PPAGE:
- if (begin_reached)
- break;
- back_lines(page_length + boxh);
- refresh_text_box(dialog, box, boxh, boxw, cur_y,
- cur_x, update_text, data);
- break;
- case 'J': /* Next line */
- case 'j':
- case KEY_DOWN:
- if (end_reached)
- break;
-
- back_lines(page_length - 1);
- refresh_text_box(dialog, box, boxh, boxw, cur_y,
- cur_x, update_text, data);
- break;
- case KEY_NPAGE: /* Next page */
- case ' ':
- case 'd':
- if (end_reached)
- break;
-
- begin_reached = 0;
- refresh_text_box(dialog, box, boxh, boxw, cur_y,
- cur_x, update_text, data);
- 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);
- refresh_text_box(dialog, box, boxh, boxw, cur_y,
- cur_x, update_text, data);
- 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);
- refresh_text_box(dialog, box, boxh, boxw, cur_y,
- cur_x, update_text, data);
- break;
- case KEY_ESC:
- if (on_key_esc(dialog) == KEY_ESC)
- done = true;
- break;
- case KEY_RESIZE:
- back_lines(height);
- delwin(box);
- delwin(dialog);
- on_key_resize();
- goto do_resize;
- default:
- for (i = 0; keys[i]; i++) {
- if (key == keys[i]) {
- done = true;
- break;
- }
- }
- }
- }
- delwin(box);
- delwin(dialog);
- if (_vscroll) {
- const char *s;
-
- s = buf;
- *_vscroll = 0;
- back_lines(page_length);
- while (s < page && (s = strchr(s, '\n'))) {
- (*_vscroll)++;
- s++;
- }
- }
- if (_hscroll)
- *_hscroll = hscroll;
- return key;
-}
-
-/*
- * Go back 'n' lines in text. Called by dialog_textbox().
- * 'page' will be updated to point to the desired line in 'buf'.
- */
-static void back_lines(int n)
-{
- int i;
-
- begin_reached = 0;
- /* Go back 'n' lines */
- for (i = 0; i < n; i++) {
- if (*page == '\0') {
- if (end_reached) {
- end_reached = 0;
- continue;
- }
- }
- if (page == buf) {
- begin_reached = 1;
- return;
- }
- page--;
- do {
- if (page == buf) {
- begin_reached = 1;
- return;
- }
- page--;
- } while (*page != '\n');
- page++;
- }
-}
-
-/*
- * Print a new page of text.
- */
-static void print_page(WINDOW *win, int height, int width, update_text_fn
- update_text, void *data)
-{
- int i, passed_end = 0;
-
- if (update_text) {
- char *end;
-
- for (i = 0; i < height; i++)
- get_line();
- end = page;
- back_lines(height);
- update_text(buf, page - buf, end - buf, data);
- }
-
- 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.
- */
-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 x = getcurx(win);
- int i;
- for (i = 0; i < width - x; i++)
- waddch(win, ' ');
- }
-#else
- wclrtoeol(win);
-#endif
-}
-
-/*
- * Return current line of text. Called by dialog_textbox() and print_line().
- * 'page' should point to start of current line before calling, and will be
- * updated to point to start of next line.
- */
-static char *get_line(void)
-{
- int i = 0;
- static char line[MAX_LEN + 1];
-
- end_reached = 0;
- while (*page != '\n') {
- if (*page == '\0') {
- 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 past '\n' */
-
- return line;
-}
-
-/*
- * Print current position
- */
-static void print_position(WINDOW * win)
-{
- int percent;
-
- wattrset(win, dlg.position_indicator.atr);
- wbkgdset(win, dlg.position_indicator.atr & A_COLOR);
- percent = (page - buf) * 100 / strlen(buf);
- wmove(win, getmaxy(win) - 3, getmaxx(win) - 9);
- wprintw(win, "(%3d%%)", percent);
-}
diff --git a/tools/kconfig/lxdialog/util.c b/tools/kconfig/lxdialog/util.c
deleted file mode 100644
index 3f78fb2..0000000
--- a/tools/kconfig/lxdialog/util.c
+++ /dev/null
@@ -1,700 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * util.c
- *
- * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com)
- */
-
-#include <stdarg.h>
-
-#include "dialog.h"
-
-/* Needed in signal handler in mconf.c */
-int saved_x, saved_y;
-
-struct dialog_info dlg;
-
-static void set_mono_theme(void)
-{
- dlg.screen.atr = A_NORMAL;
- dlg.shadow.atr = A_NORMAL;
- dlg.dialog.atr = A_NORMAL;
- dlg.title.atr = A_BOLD;
- dlg.border.atr = A_NORMAL;
- dlg.button_active.atr = A_REVERSE;
- dlg.button_inactive.atr = A_DIM;
- dlg.button_key_active.atr = A_REVERSE;
- dlg.button_key_inactive.atr = A_BOLD;
- dlg.button_label_active.atr = A_REVERSE;
- dlg.button_label_inactive.atr = A_NORMAL;
- dlg.inputbox.atr = A_NORMAL;
- dlg.inputbox_border.atr = A_NORMAL;
- dlg.searchbox.atr = A_NORMAL;
- dlg.searchbox_title.atr = A_BOLD;
- dlg.searchbox_border.atr = A_NORMAL;
- dlg.position_indicator.atr = A_BOLD;
- dlg.menubox.atr = A_NORMAL;
- dlg.menubox_border.atr = A_NORMAL;
- dlg.item.atr = A_NORMAL;
- dlg.item_selected.atr = A_REVERSE;
- dlg.tag.atr = A_BOLD;
- dlg.tag_selected.atr = A_REVERSE;
- dlg.tag_key.atr = A_BOLD;
- dlg.tag_key_selected.atr = A_REVERSE;
- dlg.check.atr = A_BOLD;
- dlg.check_selected.atr = A_REVERSE;
- dlg.uarrow.atr = A_BOLD;
- dlg.darrow.atr = A_BOLD;
-}
-
-#define DLG_COLOR(dialog, f, b, h) \
-do { \
- dlg.dialog.fg = (f); \
- dlg.dialog.bg = (b); \
- dlg.dialog.hl = (h); \
-} while (0)
-
-static void set_classic_theme(void)
-{
- DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true);
- DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true);
- DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false);
- DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true);
- DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true);
- DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true);
- DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false);
- DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true);
- DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false);
- DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true);
- DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true);
- DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false);
- DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false);
- DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false);
- DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true);
- DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true);
- DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true);
- DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false);
- DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true);
- DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false);
- DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true);
- DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true);
- DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true);
- DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true);
- DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true);
- DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false);
- DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true);
- DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true);
- DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true);
-}
-
-static void set_blackbg_theme(void)
-{
- DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true);
- DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false);
- DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false);
- DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false);
- DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true);
-
- DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false);
- DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false);
- DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true);
- DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false);
- DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false);
- DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true);
-
- DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false);
- DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false);
-
- DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false);
- DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true);
- DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true);
-
- DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false);
-
- DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false);
- DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true);
-
- DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false);
- DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false);
-
- DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false);
- DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true);
- DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false);
- DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true);
-
- DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false);
- DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true);
-
- DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false);
- DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false);
-}
-
-static void set_bluetitle_theme(void)
-{
- set_classic_theme();
- DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true);
- DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true);
- DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true);
- DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true);
- DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true);
- DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true);
- DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true);
-
-}
-
-/*
- * Select color theme
- */
-static int set_theme(const char *theme)
-{
- int use_color = 1;
- if (!theme)
- set_bluetitle_theme();
- else if (strcmp(theme, "classic") == 0)
- set_classic_theme();
- else if (strcmp(theme, "bluetitle") == 0)
- set_bluetitle_theme();
- else if (strcmp(theme, "blackbg") == 0)
- set_blackbg_theme();
- else if (strcmp(theme, "mono") == 0)
- use_color = 0;
-
- return use_color;
-}
-
-static void init_one_color(struct dialog_color *color)
-{
- static int pair = 0;
-
- pair++;
- init_pair(pair, color->fg, color->bg);
- if (color->hl)
- color->atr = A_BOLD | COLOR_PAIR(pair);
- else
- color->atr = COLOR_PAIR(pair);
-}
-
-static void init_dialog_colors(void)
-{
- init_one_color(&dlg.screen);
- init_one_color(&dlg.shadow);
- init_one_color(&dlg.dialog);
- init_one_color(&dlg.title);
- init_one_color(&dlg.border);
- init_one_color(&dlg.button_active);
- init_one_color(&dlg.button_inactive);
- init_one_color(&dlg.button_key_active);
- init_one_color(&dlg.button_key_inactive);
- init_one_color(&dlg.button_label_active);
- init_one_color(&dlg.button_label_inactive);
- init_one_color(&dlg.inputbox);
- init_one_color(&dlg.inputbox_border);
- init_one_color(&dlg.searchbox);
- init_one_color(&dlg.searchbox_title);
- init_one_color(&dlg.searchbox_border);
- init_one_color(&dlg.position_indicator);
- init_one_color(&dlg.menubox);
- init_one_color(&dlg.menubox_border);
- init_one_color(&dlg.item);
- init_one_color(&dlg.item_selected);
- init_one_color(&dlg.tag);
- init_one_color(&dlg.tag_selected);
- init_one_color(&dlg.tag_key);
- init_one_color(&dlg.tag_key_selected);
- init_one_color(&dlg.check);
- init_one_color(&dlg.check_selected);
- init_one_color(&dlg.uarrow);
- init_one_color(&dlg.darrow);
-}
-
-/*
- * Setup for color display
- */
-static void color_setup(const char *theme)
-{
- int use_color;
-
- use_color = set_theme(theme);
- if (use_color && has_colors()) {
- start_color();
- init_dialog_colors();
- } else
- set_mono_theme();
-}
-
-/*
- * 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)
-{
- int lines, columns;
-
- lines = getmaxy(stdscr);
- columns = getmaxx(stdscr);
-
- attr_clear(stdscr, lines, columns, dlg.screen.atr);
- /* Display background title if it exists ... - SLH */
- if (dlg.backtitle != NULL) {
- int i, len = 0, skip = 0;
- struct subtitle_list *pos;
-
- wattrset(stdscr, dlg.screen.atr);
- mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle);
-
- for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
- /* 3 is for the arrow and spaces */
- len += strlen(pos->text) + 3;
- }
-
- wmove(stdscr, 1, 1);
- if (len > columns - 2) {
- const char *ellipsis = "[...] ";
- waddstr(stdscr, ellipsis);
- skip = len - (columns - 2 - strlen(ellipsis));
- }
-
- for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
- if (skip == 0)
- waddch(stdscr, ACS_RARROW);
- else
- skip--;
-
- if (skip == 0)
- waddch(stdscr, ' ');
- else
- skip--;
-
- if (skip < strlen(pos->text)) {
- waddstr(stdscr, pos->text + skip);
- skip = 0;
- } else
- skip -= strlen(pos->text);
-
- if (skip == 0)
- waddch(stdscr, ' ');
- else
- skip--;
- }
-
- for (i = len + 1; i < columns - 1; i++)
- waddch(stdscr, ACS_HLINE);
- }
- wnoutrefresh(stdscr);
-}
-
-/*
- * Do some initialization for dialog
- */
-int init_dialog(const char *backtitle)
-{
- int height, width;
-
- initscr(); /* Init curses */
-
- /* Get current cursor position for signal handler in mconf.c */
- getyx(stdscr, saved_y, saved_x);
-
- getmaxyx(stdscr, height, width);
- if (height < WINDOW_HEIGTH_MIN || width < WINDOW_WIDTH_MIN) {
- endwin();
- return -ERRDISPLAYTOOSMALL;
- }
-
- dlg.backtitle = backtitle;
- color_setup(getenv("MENUCONFIG_COLOR"));
-
- keypad(stdscr, TRUE);
- cbreak();
- noecho();
- dialog_clear();
-
- return 0;
-}
-
-void set_dialog_backtitle(const char *backtitle)
-{
- dlg.backtitle = backtitle;
-}
-
-void set_dialog_subtitles(struct subtitle_list *subtitles)
-{
- dlg.subtitles = subtitles;
-}
-
-/*
- * End using dialog functions.
- */
-void end_dialog(int x, int y)
-{
- /* move cursor back to original position */
- move(y, x);
- refresh();
- endwin();
-}
-
-/* Print the title of the dialog. Center the title and truncate
- * tile if wider than dialog (- 2 chars).
- **/
-void print_title(WINDOW *dialog, const char *title, int width)
-{
- if (title) {
- int tlen = MIN(width - 2, strlen(title));
- wattrset(dialog, dlg.title.atr);
- mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' ');
- mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen);
- waddch(dialog, ' ');
- }
-}
-
-/*
- * 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 properly processed. 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 prompt_len, room, wlen;
- char tempstr[MAX_LEN + 1], *word, *sp, *sp2, *newline_separator = 0;
-
- strcpy(tempstr, prompt);
-
- prompt_len = strlen(tempstr);
-
- 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 = strpbrk(word, "\n ");
- if (sp && *sp == '\n')
- newline_separator = sp;
-
- 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 = strpbrk(sp, "\n "))
- || 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);
-
- /* Move to the next line if the word separator was a newline */
- if (newline_separator) {
- cur_y++;
- cur_x = x;
- newline_separator = 0;
- } else
- 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 ? dlg.button_active.atr
- : dlg.button_inactive.atr);
- waddstr(win, "<");
- temp = strspn(label, " ");
- label += temp;
- wattrset(win, selected ? dlg.button_label_active.atr
- : dlg.button_label_inactive.atr);
- for (i = 0; i < temp; i++)
- waddch(win, ' ');
- wattrset(win, selected ? dlg.button_key_active.atr
- : dlg.button_key_inactive.atr);
- waddch(win, label[0]);
- wattrset(win, selected ? dlg.button_label_active.atr
- : dlg.button_label_inactive.atr);
- waddstr(win, (char *)label + 1);
- wattrset(win, selected ? dlg.button_active.atr
- : dlg.button_inactive.atr);
- 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, dlg.shadow.atr);
- 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;
-}
-
-/*
- * ncurses uses ESC to detect escaped char sequences. This resutl in
- * a small timeout before ESC is actually delivered to the application.
- * lxdialog suggest <ESC> <ESC> which is correctly translated to two
- * times esc. But then we need to ignore the second esc to avoid stepping
- * out one menu too much. Filter away all escaped key sequences since
- * keypad(FALSE) turn off ncurses support for escape sequences - and that's
- * needed to make notimeout() do as expected.
- */
-int on_key_esc(WINDOW *win)
-{
- int key;
- int key2;
- int key3;
-
- nodelay(win, TRUE);
- keypad(win, FALSE);
- key = wgetch(win);
- key2 = wgetch(win);
- do {
- key3 = wgetch(win);
- } while (key3 != ERR);
- nodelay(win, FALSE);
- keypad(win, TRUE);
- if (key == KEY_ESC && key2 == ERR)
- return KEY_ESC;
- else if (key != ERR && key != KEY_ESC && key2 == ERR)
- ungetch(key);
-
- return -1;
-}
-
-/* redraw screen in new size */
-int on_key_resize(void)
-{
- dialog_clear();
- return KEY_RESIZE;
-}
-
-struct dialog_list *item_cur;
-struct dialog_list item_nil;
-struct dialog_list *item_head;
-
-void item_reset(void)
-{
- struct dialog_list *p, *next;
-
- for (p = item_head; p; p = next) {
- next = p->next;
- free(p);
- }
- item_head = NULL;
- item_cur = &item_nil;
-}
-
-void item_make(const char *fmt, ...)
-{
- va_list ap;
- struct dialog_list *p = malloc(sizeof(*p));
-
- if (item_head)
- item_cur->next = p;
- else
- item_head = p;
- item_cur = p;
- memset(p, 0, sizeof(*p));
-
- va_start(ap, fmt);
- vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap);
- va_end(ap);
-}
-
-void item_add_str(const char *fmt, ...)
-{
- va_list ap;
- size_t avail;
-
- avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str);
-
- va_start(ap, fmt);
- vsnprintf(item_cur->node.str + strlen(item_cur->node.str),
- avail, fmt, ap);
- item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0';
- va_end(ap);
-}
-
-void item_set_tag(char tag)
-{
- item_cur->node.tag = tag;
-}
-void item_set_data(void *ptr)
-{
- item_cur->node.data = ptr;
-}
-
-void item_set_selected(int val)
-{
- item_cur->node.selected = val;
-}
-
-int item_activate_selected(void)
-{
- item_foreach()
- if (item_is_selected())
- return 1;
- return 0;
-}
-
-void *item_data(void)
-{
- return item_cur->node.data;
-}
-
-char item_tag(void)
-{
- return item_cur->node.tag;
-}
-
-int item_count(void)
-{
- int n = 0;
- struct dialog_list *p;
-
- for (p = item_head; p; p = p->next)
- n++;
- return n;
-}
-
-void item_set(int n)
-{
- int i = 0;
- item_foreach()
- if (i++ == n)
- return;
-}
-
-int item_n(void)
-{
- int n = 0;
- struct dialog_list *p;
-
- for (p = item_head; p; p = p->next) {
- if (p == item_cur)
- return n;
- n++;
- }
- return 0;
-}
-
-const char *item_str(void)
-{
- return item_cur->node.str;
-}
-
-int item_is_selected(void)
-{
- return (item_cur->node.selected != 0);
-}
-
-int item_is_tag(char tag)
-{
- return (item_cur->node.tag == tag);
-}
diff --git a/tools/kconfig/lxdialog/yesno.c b/tools/kconfig/lxdialog/yesno.c
deleted file mode 100644
index bcaac9b..0000000
--- a/tools/kconfig/lxdialog/yesno.c
+++ /dev/null
@@ -1,101 +0,0 @@
-// SPDX-License-Identifier: GPL-2.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)
- */
-
-#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;
-
-do_resize:
- if (getmaxy(stdscr) < (height + YESNO_HEIGTH_MIN))
- return -ERRDISPLAYTOOSMALL;
- if (getmaxx(stdscr) < (width + YESNO_WIDTH_MIN))
- return -ERRDISPLAYTOOSMALL;
-
- /* center dialog box on screen */
- x = (getmaxx(stdscr) - width) / 2;
- y = (getmaxy(stdscr) - 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,
- dlg.dialog.atr, dlg.border.atr);
- wattrset(dialog, dlg.border.atr);
- mvwaddch(dialog, height - 3, 0, ACS_LTEE);
- for (i = 0; i < width - 2; i++)
- waddch(dialog, ACS_HLINE);
- wattrset(dialog, dlg.dialog.atr);
- waddch(dialog, ACS_RTEE);
-
- print_title(dialog, title, width);
-
- wattrset(dialog, dlg.dialog.atr);
- print_autowrap(dialog, prompt, width - 2, 1, 3);
-
- print_buttons(dialog, height, width, 0);
-
- while (key != 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 KEY_ESC:
- key = on_key_esc(dialog);
- break;
- case KEY_RESIZE:
- delwin(dialog);
- on_key_resize();
- goto do_resize;
- }
- }
-
- delwin(dialog);
- return key; /* ESC pressed */
-}
diff --git a/tools/kconfig/mconf.c b/tools/kconfig/mconf.c
deleted file mode 100644
index e67e0db..0000000
--- a/tools/kconfig/mconf.c
+++ /dev/null
@@ -1,1042 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- *
- * Introduced single menu mode (show all sub-menus in one large tree).
- * 2002-11-06 Petr Baudis <pasky@ucw.cz>
- *
- * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <signal.h>
-#include <unistd.h>
-
-#include "lkc.h"
-#include "lxdialog/dialog.h"
-
-#define JUMP_NB 9
-
-static const char mconf_readme[] =
-"Overview\n"
-"--------\n"
-"This interface lets you select features and parameters for the build.\n"
-"Features can either be built-in, modularized, or ignored. Parameters\n"
-"must be entered in as decimal or hexadecimal numbers or text.\n"
-"\n"
-"Menu items beginning with following braces represent features that\n"
-" [ ] can be built in or removed\n"
-" < > can be built in, modularized or removed\n"
-" { } can be built in or modularized (selected by other feature)\n"
-" - - are selected by other feature,\n"
-"while *, M or whitespace inside braces means to build in, build as\n"
-"a module or to exclude the feature respectively.\n"
-"\n"
-"To change any of these features, highlight it with the cursor\n"
-"keys and press <Y> to build it in, <M> to make it a module or\n"
-"<N> to remove it. You may also press the <Space Bar> to cycle\n"
-"through the available options (i.e. Y->N->M->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 you\n"
-" wish to change or the submenu you wish to select and press <Enter>.\n"
-" Submenus are designated by \"--->\", empty ones 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>, <Help>, <Save>, and <Load>.\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"
-"o To toggle the display of hidden options, press <Z>.\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 <u>, <d>, <SPACE BAR> and <B> for\n"
-" those who are familiar with less and lynx.\n"
-"\n"
-"o Press <E>, <X>, <q>, <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"
-"The <Save> button will let you save the current configuration to\n"
-"a file of your choosing. Use the <Load> button to load a previously\n"
-"saved alternate configuration.\n"
-"\n"
-"Even if you don't use alternate configuration files, but you find\n"
-"during a Menuconfig session that you have completely messed up your\n"
-"settings, you may use the <Load> button to restore your previously\n"
-"saved settings from \".config\" without 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 an xterm definition which supports\n"
-"color. Otherwise, Menuconfig will look rather bad. Menuconfig will\n"
-"not display correctly in an 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 menu,\n"
-"rather than the default multimenu hierarchy, run the menuconfig with\n"
-"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"
-"\n"
-
-"Search\n"
-"-------\n"
-"Pressing the forward-slash (/) anywhere brings up a search dialog box.\n"
-"\n"
-
-"Different color themes available\n"
-"--------------------------------\n"
-"It is possible to select different color themes using the variable\n"
-"MENUCONFIG_COLOR. To select a theme use:\n"
-"\n"
-"make MENUCONFIG_COLOR=<theme> menuconfig\n"
-"\n"
-"Available themes are\n"
-" mono => selects colors suitable for monochrome displays\n"
-" blackbg => selects a color scheme with black background\n"
-" classic => theme with blue background. The classic look\n"
-" bluetitle => an LCD friendly version of classic. (default)\n"
-"\n",
-menu_instructions[] =
- "Arrow keys navigate the menu. "
- "<Enter> selects submenus ---> (or empty submenus ----). "
- "Highlighted letters are hotkeys. "
- "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
- "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
- "Legend: [*] built-in [ ] excluded <M> module < > module capable",
-radiolist_instructions[] =
- "Use the arrow keys to navigate this window or "
- "press the hotkey of the item you wish to select "
- "followed by the <SPACE BAR>. "
- "Press <?> for additional information about this option.",
-inputbox_instructions_int[] =
- "Please enter a decimal value. "
- "Fractions will not be accepted. "
- "Use the <TAB> key to move from the input field to the buttons below it.",
-inputbox_instructions_hex[] =
- "Please enter a hexadecimal value. "
- "Use the <TAB> key to move from the input field to the buttons below it.",
-inputbox_instructions_string[] =
- "Please enter a string value. "
- "Use the <TAB> key to move from the input field to the buttons below it.",
-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.",
-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\n"
- "configurations available on a single machine.\n"
- "\n"
- "If you have saved a previous configuration in a file other than the\n"
- "default one, entering its name here will allow you to modify that\n"
- "configuration.\n"
- "\n"
- "If you are uncertain, then you have probably never used alternate\n"
- "configuration files. You should therefore 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 configurations\n"
- "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 symbols and display their relations.\n"
- "Regular expressions are allowed.\n"
- "Example: search for \"^FOO\"\n"
- "Result:\n"
- "-----------------------------------------------------------------\n"
- "Symbol: FOO [=m]\n"
- "Type : tristate\n"
- "Prompt: Foo bus is used to drive the bar HW\n"
- " Location:\n"
- " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
- " -> PCI support (PCI [=y])\n"
- "(1) -> PCI access mode (<choice> [=y])\n"
- " Defined at drivers/pci/Kconfig:47\n"
- " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
- " Selects: LIBCRC32\n"
- " Selected by: BAR [=n]\n"
- "-----------------------------------------------------------------\n"
- "o The line 'Type:' shows the type of the configuration option for\n"
- " this symbol (bool, tristate, string, ...)\n"
- "o The line 'Prompt:' shows the text used in the menu structure for\n"
- " this symbol\n"
- "o The 'Defined at' line tells at what file / line number the symbol\n"
- " is defined\n"
- "o The 'Depends on:' line tells what symbols need to be defined for\n"
- " this symbol to be visible in the menu (selectable)\n"
- "o The 'Location:' lines tells where in the menu structure this symbol\n"
- " is located\n"
- " A location followed by a [=y] indicates that this is a\n"
- " selectable menu item - and the current value is displayed inside\n"
- " brackets.\n"
- " Press the key in the (#) prefix to jump directly to that\n"
- " location. You will be returned to the current search results\n"
- " after exiting this new menu.\n"
- "o The 'Selects:' line tells what symbols will be automatically\n"
- " selected if this symbol is selected (y or m)\n"
- "o The 'Selected by' line tells what symbol has selected this symbol\n"
- "\n"
- "Only relevant lines are shown.\n"
- "\n\n"
- "Search examples:\n"
- "Examples: USB => find all symbols containing USB\n"
- " ^USB => find all symbols starting with USB\n"
- " USB$ => find all symbols ending with USB\n"
- "\n";
-
-static int indent;
-static struct menu *current_menu;
-static int child_count;
-static int single_menu_mode;
-static int show_all_options;
-static int save_and_exit;
-static int silent;
-
-static void conf(struct menu *menu, struct menu *active_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 int show_textbox_ext(const char *title, char *text, int r, int c,
- int *keys, int *vscroll, int *hscroll,
- update_text_fn update_text, void *data);
-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 char filename[PATH_MAX+1];
-static void set_config_filename(const char *config_filename)
-{
- static char menu_backtitle[PATH_MAX+128];
-
- snprintf(menu_backtitle, sizeof(menu_backtitle), "%s - %s",
- config_filename, rootmenu.prompt->text);
- set_dialog_backtitle(menu_backtitle);
-
- snprintf(filename, sizeof(filename), "%s", config_filename);
-}
-
-struct subtitle_part {
- struct list_head entries;
- const char *text;
-};
-static LIST_HEAD(trail);
-
-static struct subtitle_list *subtitles;
-static void set_subtitle(void)
-{
- struct subtitle_part *sp;
- struct subtitle_list *pos, *tmp;
-
- for (pos = subtitles; pos != NULL; pos = tmp) {
- tmp = pos->next;
- free(pos);
- }
-
- subtitles = NULL;
- list_for_each_entry(sp, &trail, entries) {
- if (sp->text) {
- if (pos) {
- pos->next = xcalloc(1, sizeof(*pos));
- pos = pos->next;
- } else {
- subtitles = pos = xcalloc(1, sizeof(*pos));
- }
- pos->text = sp->text;
- }
- }
-
- set_dialog_subtitles(subtitles);
-}
-
-static void reset_subtitle(void)
-{
- struct subtitle_list *pos, *tmp;
-
- for (pos = subtitles; pos != NULL; pos = tmp) {
- tmp = pos->next;
- free(pos);
- }
- subtitles = NULL;
- set_dialog_subtitles(subtitles);
-}
-
-struct search_data {
- struct list_head *head;
- struct menu **targets;
- int *keys;
-};
-
-static void update_text(char *buf, size_t start, size_t end, void *_data)
-{
- struct search_data *data = _data;
- struct jump_key *pos;
- int k = 0;
-
- list_for_each_entry(pos, data->head, entries) {
- if (pos->offset >= start && pos->offset < end) {
- char header[4];
-
- if (k < JUMP_NB) {
- int key = '0' + (pos->index % JUMP_NB) + 1;
-
- sprintf(header, "(%c)", key);
- data->keys[k] = key;
- data->targets[k] = pos->target;
- k++;
- } else {
- sprintf(header, " ");
- }
-
- memcpy(buf + pos->offset, header, sizeof(header) - 1);
- }
- }
- data->keys[k] = 0;
-}
-
-static void search_conf(void)
-{
- struct symbol **sym_arr;
- struct gstr res;
- struct gstr title;
- char *dialog_input;
- int dres, vscroll = 0, hscroll = 0;
- bool again;
- struct gstr sttext;
- struct subtitle_part stpart;
-
- title = str_new();
- str_printf( &title, "Enter (sub)string or regexp to search for "
- "(with or without \"%s\")", CONFIG_);
-
-again:
- dialog_clear();
- dres = dialog_inputbox("Search Configuration Parameter",
- str_get(&title),
- 10, 75, "");
- switch (dres) {
- case 0:
- break;
- case 1:
- show_helptext("Search Configuration", search_help);
- goto again;
- default:
- str_free(&title);
- return;
- }
-
- /* strip the prefix if necessary */
- dialog_input = dialog_input_result;
- if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
- dialog_input += strlen(CONFIG_);
-
- sttext = str_new();
- str_printf(&sttext, "Search (%s)", dialog_input_result);
- stpart.text = str_get(&sttext);
- list_add_tail(&stpart.entries, &trail);
-
- sym_arr = sym_re_search(dialog_input);
- do {
- LIST_HEAD(head);
- struct menu *targets[JUMP_NB];
- int keys[JUMP_NB + 1], i;
- struct search_data data = {
- .head = &head,
- .targets = targets,
- .keys = keys,
- };
- struct jump_key *pos, *tmp;
-
- res = get_relations_str(sym_arr, &head);
- set_subtitle();
- dres = show_textbox_ext("Search Results", str_get(&res), 0, 0,
- keys, &vscroll, &hscroll, &update_text,
- &data);
- again = false;
- for (i = 0; i < JUMP_NB && keys[i]; i++)
- if (dres == keys[i]) {
- conf(targets[i]->parent, targets[i]);
- again = true;
- }
- str_free(&res);
- list_for_each_entry_safe(pos, tmp, &head, entries)
- free(pos);
- } while (again);
- free(sym_arr);
- str_free(&title);
- list_del(trail.prev);
- str_free(&sttext);
-}
-
-static void build_conf(struct menu *menu)
-{
- struct symbol *sym;
- struct property *prop;
- struct menu *child;
- int type, tmp, doint = 2;
- tristate val;
- char ch;
- bool visible;
-
- /*
- * note: menu_is_visible() has side effect that it will
- * recalc the value of the symbol.
- */
- visible = menu_is_visible(menu);
- if (show_all_options && !menu_has_prompt(menu))
- return;
- else if (!show_all_options && !visible)
- 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++;
- if (single_menu_mode) {
- item_make("%s%*c%s",
- menu->data ? "-->" : "++>",
- indent + 1, ' ', prompt);
- } else
- item_make(" %*c%s %s",
- indent + 1, ' ', prompt,
- menu_is_empty(menu) ? "----" : "--->");
- item_set_tag('m');
- item_set_data(menu);
- if (single_menu_mode && menu->data)
- goto conf_childs;
- return;
- case P_COMMENT:
- if (prompt) {
- child_count++;
- item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
- item_set_tag(':');
- item_set_data(menu);
- }
- break;
- default:
- if (prompt) {
- child_count++;
- item_make("---%*c%s", indent + 1, ' ', prompt);
- item_set_tag(':');
- item_set_data(menu);
- }
- }
- } else
- doint = 0;
- goto conf_childs;
- }
-
- 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_changeable(sym)) {
- switch (type) {
- case S_BOOLEAN:
- item_make("[%c]", val == no ? ' ' : '*');
- break;
- case S_TRISTATE:
- switch (val) {
- case yes: ch = '*'; break;
- case mod: ch = 'M'; break;
- default: ch = ' '; break;
- }
- item_make("<%c>", ch);
- break;
- }
- item_set_tag('t');
- item_set_data(menu);
- } else {
- item_make(" ");
- item_set_tag(def_menu ? 't' : ':');
- item_set_data(menu);
- }
-
- item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
- if (val == yes) {
- if (def_menu) {
- item_add_str(" (%s)", menu_get_prompt(def_menu));
- item_add_str(" --->");
- if (def_menu->list) {
- indent += 2;
- build_conf(def_menu);
- indent -= 2;
- }
- }
- return;
- }
- } else {
- if (menu == current_menu) {
- item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
- item_set_tag(':');
- item_set_data(menu);
- goto conf_childs;
- }
- child_count++;
- val = sym_get_tristate_value(sym);
- if (sym_is_choice_value(sym) && val == yes) {
- item_make(" ");
- item_set_tag(':');
- item_set_data(menu);
- } else {
- switch (type) {
- case S_BOOLEAN:
- if (sym_is_changeable(sym))
- item_make("[%c]", val == no ? ' ' : '*');
- else
- item_make("-%c-", val == no ? ' ' : '*');
- item_set_tag('t');
- item_set_data(menu);
- break;
- case S_TRISTATE:
- switch (val) {
- case yes: ch = '*'; break;
- case mod: ch = 'M'; break;
- default: ch = ' '; break;
- }
- if (sym_is_changeable(sym)) {
- if (sym->rev_dep.tri == mod)
- item_make("{%c}", ch);
- else
- item_make("<%c>", ch);
- } else
- item_make("-%c-", ch);
- item_set_tag('t');
- item_set_data(menu);
- break;
- default:
- tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
- item_make("(%s)", sym_get_string_value(sym));
- tmp = indent - tmp + 4;
- if (tmp < 0)
- tmp = 0;
- item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
- (sym_has_value(sym) || !sym_is_changeable(sym)) ?
- "" : " (NEW)");
- item_set_tag('s');
- item_set_data(menu);
- goto conf_childs;
- }
- }
- item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
- (sym_has_value(sym) || !sym_is_changeable(sym)) ?
- "" : " (NEW)");
- if (menu->prompt->type == P_MENU) {
- item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
- 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 menu *active_menu)
-{
- struct menu *submenu;
- const char *prompt = menu_get_prompt(menu);
- struct subtitle_part stpart;
- struct symbol *sym;
- int res;
- int s_scroll = 0;
-
- if (menu != &rootmenu)
- stpart.text = menu_get_prompt(menu);
- else
- stpart.text = NULL;
- list_add_tail(&stpart.entries, &trail);
-
- while (1) {
- item_reset();
- current_menu = menu;
- build_conf(menu);
- if (!child_count)
- break;
- set_subtitle();
- dialog_clear();
- res = dialog_menu(prompt ? prompt : "Main Menu",
- menu_instructions,
- active_menu, &s_scroll);
- if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
- break;
- if (item_count() != 0) {
- if (!item_activate_selected())
- continue;
- if (!item_tag())
- continue;
- }
- submenu = item_data();
- active_menu = item_data();
- if (submenu)
- sym = submenu->sym;
- else
- sym = NULL;
-
- switch (res) {
- case 0:
- switch (item_tag()) {
- case 'm':
- if (single_menu_mode)
- submenu->data = (void *) (long) !submenu->data;
- else
- conf(submenu, NULL);
- 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, NULL);
- break;
- case 's':
- conf_string(submenu);
- break;
- }
- break;
- case 2:
- if (sym)
- show_help(submenu);
- else {
- reset_subtitle();
- show_helptext("README", mconf_readme);
- }
- break;
- case 3:
- reset_subtitle();
- conf_save();
- break;
- case 4:
- reset_subtitle();
- conf_load();
- break;
- case 5:
- if (item_is_tag('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 6:
- if (item_is_tag('t'))
- sym_set_tristate_value(sym, no);
- break;
- case 7:
- if (item_is_tag('t'))
- sym_set_tristate_value(sym, mod);
- break;
- case 8:
- if (item_is_tag('t'))
- sym_toggle_tristate_value(sym);
- else if (item_is_tag('m'))
- conf(submenu, NULL);
- break;
- case 9:
- search_conf();
- break;
- case 10:
- show_all_options = !show_all_options;
- break;
- }
- }
-
- list_del(trail.prev);
-}
-
-static int show_textbox_ext(const char *title, char *text, int r, int c, int
- *keys, int *vscroll, int *hscroll, update_text_fn
- update_text, void *data)
-{
- dialog_clear();
- return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
- update_text, data);
-}
-
-static void show_textbox(const char *title, const char *text, int r, int c)
-{
- show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
- NULL, NULL);
-}
-
-static void show_helptext(const char *title, const char *text)
-{
- show_textbox(title, text, 0, 0);
-}
-
-static void conf_message_callback(const char *s)
-{
- if (save_and_exit) {
- if (!silent)
- printf("%s", s);
- } else {
- show_textbox(NULL, s, 6, 60);
- }
-}
-
-static void show_help(struct menu *menu)
-{
- struct gstr help = str_new();
-
- help.max_width = getmaxx(stdscr) - 10;
- menu_get_ext_help(menu, &help);
-
- show_helptext(menu_get_prompt(menu), str_get(&help));
- str_free(&help);
-}
-
-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) {
- int res;
- int selected;
- item_reset();
-
- current_menu = menu;
- for (child = menu->list; child; child = child->next) {
- if (!menu_is_visible(child))
- continue;
- if (child->sym)
- item_make("%s", menu_get_prompt(child));
- else {
- item_make("*** %s ***", menu_get_prompt(child));
- item_set_tag(':');
- }
- item_set_data(child);
- if (child->sym == active)
- item_set_selected(1);
- if (child->sym == sym_get_choice_value(menu->sym))
- item_set_tag('X');
- }
- dialog_clear();
- res = dialog_checklist(prompt ? prompt : "Main Menu",
- radiolist_instructions,
- MENUBOX_HEIGTH_MIN,
- MENUBOX_WIDTH_MIN,
- CHECKLIST_HEIGTH_MIN);
- selected = item_activate_selected();
- switch (res) {
- case 0:
- if (selected) {
- child = item_data();
- if (!child->sym)
- break;
-
- sym_set_tristate_value(child->sym, yes);
- }
- return;
- case 1:
- if (selected) {
- child = item_data();
- show_help(child);
- active = child->sym;
- } else
- show_help(menu);
- break;
- case KEY_ESC:
- return;
- case -ERRDISPLAYTOOSMALL:
- return;
- }
- }
-}
-
-static void conf_string(struct menu *menu)
-{
- const char *prompt = menu_get_prompt(menu);
-
- while (1) {
- int res;
- const char *heading;
-
- switch (sym_get_type(menu->sym)) {
- case S_INT:
- heading = inputbox_instructions_int;
- break;
- case S_HEX:
- heading = inputbox_instructions_hex;
- break;
- case S_STRING:
- heading = inputbox_instructions_string;
- break;
- default:
- heading = "Internal mconf error!";
- }
- dialog_clear();
- res = dialog_inputbox(prompt ? prompt : "Main Menu",
- heading, 10, 75,
- sym_get_string_value(menu->sym));
- switch (res) {
- 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 KEY_ESC:
- return;
- }
- }
-}
-
-static void conf_load(void)
-{
-
- while (1) {
- int res;
- dialog_clear();
- res = dialog_inputbox(NULL, load_config_text,
- 11, 55, filename);
- switch(res) {
- case 0:
- if (!dialog_input_result[0])
- return;
- if (!conf_read(dialog_input_result)) {
- set_config_filename(dialog_input_result);
- conf_set_changed(true);
- return;
- }
- show_textbox(NULL, "File does not exist!", 5, 38);
- break;
- case 1:
- show_helptext("Load Alternate Configuration", load_config_help);
- break;
- case KEY_ESC:
- return;
- }
- }
-}
-
-static void conf_save(void)
-{
- while (1) {
- int res;
- dialog_clear();
- res = dialog_inputbox(NULL, save_config_text,
- 11, 55, filename);
- switch(res) {
- case 0:
- if (!dialog_input_result[0])
- return;
- if (!conf_write(dialog_input_result)) {
- set_config_filename(dialog_input_result);
- return;
- }
- show_textbox(NULL, "Can't create file!", 5, 60);
- break;
- case 1:
- show_helptext("Save Alternate Configuration", save_config_help);
- break;
- case KEY_ESC:
- return;
- }
- }
-}
-
-static int handle_exit(void)
-{
- int res;
-
- save_and_exit = 1;
- reset_subtitle();
- dialog_clear();
- if (conf_get_changed())
- res = dialog_yesno(NULL,
- "Do you wish to save your new configuration?\n"
- "(Press <ESC><ESC> to continue kernel configuration.)",
- 6, 60);
- else
- res = -1;
-
- end_dialog(saved_x, saved_y);
-
- switch (res) {
- case 0:
- if (conf_write(filename)) {
- fprintf(stderr, "\n\n"
- "Error while writing of the configuration.\n"
- "Your configuration changes were NOT saved."
- "\n\n");
- return 1;
- }
- conf_write_autoconf(0);
- /* fall through */
- case -1:
- if (!silent)
- printf("\n\n"
- "*** End of the configuration.\n"
- "*** Execute 'make' to start the build or try 'make help'."
- "\n\n");
- res = 0;
- break;
- default:
- if (!silent)
- fprintf(stderr, "\n\n"
- "Your configuration changes were NOT saved."
- "\n\n");
- if (res != KEY_ESC)
- res = 0;
- }
-
- return res;
-}
-
-static void sig_handler(int signo)
-{
- exit(handle_exit());
-}
-
-int main(int ac, char **av)
-{
- char *mode;
- int res;
-
- signal(SIGINT, sig_handler);
-
- if (ac > 1 && strcmp(av[1], "-s") == 0) {
- silent = 1;
- /* Silence conf_read() until the real callback is set up */
- conf_set_message_callback(NULL);
- av++;
- }
- conf_parse(av[1]);
- conf_read(NULL);
-
- mode = getenv("MENUCONFIG_MODE");
- if (mode) {
- if (!strcasecmp(mode, "single_menu"))
- single_menu_mode = 1;
- }
-
- if (init_dialog(NULL)) {
- fprintf(stderr, "Your display is too small to run Menuconfig!\n");
- fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
- return 1;
- }
-
- set_config_filename(conf_get_configname());
- conf_set_message_callback(conf_message_callback);
- do {
- conf(&rootmenu, NULL);
- res = handle_exit();
- } while (res == KEY_ESC);
-
- return res;
-}
diff --git a/tools/kconfig/menu.c b/tools/kconfig/menu.c
deleted file mode 100644
index b90fff8..0000000
--- a/tools/kconfig/menu.c
+++ /dev/null
@@ -1,859 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- */
-
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "lkc.h"
-#include "internal.h"
-
-static const char nohelp_text[] = "There is no help available for this option.";
-
-struct menu rootmenu;
-static struct menu **last_entry_ptr;
-
-struct file *file_list;
-struct file *current_file;
-
-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 = xmalloc(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;
- if (sym)
- menu_add_symbol(P_SYMBOL, sym, NULL);
-}
-
-struct menu *menu_add_menu(void)
-{
- last_entry_ptr = &current_entry->list;
- current_menu = current_entry;
- return current_menu;
-}
-
-void menu_end_menu(void)
-{
- last_entry_ptr = &current_menu->next;
- current_menu = current_menu->parent;
-}
-
-/*
- * Rewrites 'm' to 'm' && MODULES, so that it evaluates to 'n' when running
- * without modules
- */
-static struct expr *rewrite_m(struct expr *e)
-{
- if (!e)
- return e;
-
- switch (e->type) {
- case E_NOT:
- e->left.expr = rewrite_m(e->left.expr);
- break;
- case E_OR:
- case E_AND:
- e->left.expr = rewrite_m(e->left.expr);
- e->right.expr = rewrite_m(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, 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,
- "ignoring type redefinition of '%s' from '%s' to '%s'",
- sym->name ? sym->name : "<choice>",
- sym_type_name(sym->type), sym_type_name(type));
-}
-
-static struct property *menu_add_prop(enum prop_type type, struct expr *expr,
- struct expr *dep)
-{
- struct property *prop;
-
- prop = xmalloc(sizeof(*prop));
- memset(prop, 0, sizeof(*prop));
- prop->type = type;
- prop->file = current_file;
- prop->lineno = zconf_lineno();
- prop->menu = current_entry;
- prop->expr = expr;
- prop->visible.expr = dep;
-
- /* append property to the prop list of symbol */
- if (current_entry->sym) {
- struct property **propp;
-
- for (propp = &current_entry->sym->prop;
- *propp;
- propp = &(*propp)->next)
- ;
- *propp = prop;
- }
-
- return prop;
-}
-
-struct property *menu_add_prompt(enum prop_type type, char *prompt,
- struct expr *dep)
-{
- struct property *prop = menu_add_prop(type, NULL, dep);
-
- if (isspace(*prompt)) {
- prop_warn(prop, "leading whitespace ignored");
- while (isspace(*prompt))
- prompt++;
- }
- if (current_entry->prompt)
- prop_warn(prop, "prompt redefined");
-
- /* Apply all upper menus' visibilities to actual prompts. */
- if (type == P_PROMPT) {
- struct menu *menu = current_entry;
-
- while ((menu = menu->parent) != NULL) {
- struct expr *dup_expr;
-
- if (!menu->visibility)
- continue;
- /*
- * Do not add a reference to the menu's visibility
- * expression but use a copy of it. Otherwise the
- * expression reduction functions will modify
- * expressions that have multiple references which
- * can cause unwanted side effects.
- */
- dup_expr = expr_copy(menu->visibility);
-
- prop->visible.expr = expr_alloc_and(prop->visible.expr,
- dup_expr);
- }
- }
-
- current_entry->prompt = prop;
- prop->text = prompt;
-
- return prop;
-}
-
-void menu_add_visibility(struct expr *expr)
-{
- current_entry->visibility = expr_alloc_and(current_entry->visibility,
- expr);
-}
-
-void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep)
-{
- menu_add_prop(type, expr, dep);
-}
-
-void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep)
-{
- menu_add_prop(type, expr_alloc_symbol(sym), dep);
-}
-
-static int menu_validate_number(struct symbol *sym, struct symbol *sym2)
-{
- return sym2->type == S_INT || sym2->type == S_HEX ||
- (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name));
-}
-
-static void sym_check_prop(struct symbol *sym)
-{
- struct property *prop;
- struct symbol *sym2;
- char *use;
-
- 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 '%s'"
- " must be a single symbol", sym->name);
- if (prop->expr->type != E_SYMBOL)
- break;
- sym2 = prop_get_symbol(prop);
- if (sym->type == S_HEX || sym->type == S_INT) {
- if (!menu_validate_number(sym, sym2))
- prop_warn(prop,
- "'%s': number is invalid",
- sym->name);
- }
- if (sym_is_choice(sym)) {
- struct property *choice_prop =
- sym_get_choice_prop(sym2);
-
- if (!choice_prop ||
- prop_get_symbol(choice_prop) != sym)
- prop_warn(prop,
- "choice default symbol '%s' is not contained in the choice",
- sym2->name);
- }
- break;
- case P_SELECT:
- case P_IMPLY:
- use = prop->type == P_SELECT ? "select" : "imply";
- sym2 = prop_get_symbol(prop);
- if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
- prop_warn(prop,
- "config symbol '%s' uses %s, but is "
- "not bool or tristate", sym->name, use);
- else if (sym2->type != S_UNKNOWN &&
- sym2->type != S_BOOLEAN &&
- sym2->type != S_TRISTATE)
- prop_warn(prop,
- "'%s' has wrong type. '%s' only "
- "accept arguments of bool and "
- "tristate type", sym2->name, use);
- 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 (!menu_validate_number(sym, prop->expr->left.sym) ||
- !menu_validate_number(sym, prop->expr->right.sym))
- 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) {
- /*
- * This menu node has children. We (recursively) process them
- * and propagate parent dependencies before moving on.
- */
-
- if (sym && sym_is_choice(sym)) {
- if (sym->type == S_UNKNOWN) {
- /* find the first choice value to find out choice type */
- current_entry = parent;
- for (menu = parent->list; menu; menu = menu->next) {
- if (menu->sym && menu->sym->type != S_UNKNOWN) {
- menu_set_type(menu->sym->type);
- break;
- }
- }
- }
- /* set the type of the remaining choice values */
- for (menu = parent->list; menu; menu = menu->next) {
- current_entry = menu;
- if (menu->sym && menu->sym->type == S_UNKNOWN)
- menu_set_type(sym->type);
- }
-
- /*
- * Use the choice itself as the parent dependency of
- * the contained items. This turns the mode of the
- * choice into an upper bound on the visibility of the
- * choice value symbols.
- */
- parentdep = expr_alloc_symbol(sym);
- } else {
- /* Menu node for 'menu', 'if' */
- parentdep = parent->dep;
- }
-
- /* For each child menu node... */
- for (menu = parent->list; menu; menu = menu->next) {
- /*
- * Propagate parent dependencies to the child menu
- * node, also rewriting and simplifying expressions
- */
- basedep = rewrite_m(menu->dep);
- basedep = expr_transform(basedep);
- basedep = expr_alloc_and(expr_copy(parentdep), basedep);
- basedep = expr_eliminate_dups(basedep);
- menu->dep = basedep;
-
- if (menu->sym)
- /*
- * Note: For symbols, all prompts are included
- * too in the symbol's own property list
- */
- prop = menu->sym->prop;
- else
- /*
- * For non-symbol menu nodes, we just need to
- * handle the prompt
- */
- prop = menu->prompt;
-
- /* For each property... */
- for (; prop; prop = prop->next) {
- if (prop->menu != menu)
- /*
- * Two possibilities:
- *
- * 1. The property lacks dependencies
- * and so isn't location-specific,
- * e.g. an 'option'
- *
- * 2. The property belongs to a symbol
- * defined in multiple locations and
- * is from some other location. It
- * will be handled there in that
- * case.
- *
- * Skip the property.
- */
- continue;
-
- /*
- * Propagate parent dependencies to the
- * property's condition, rewriting and
- * simplifying expressions at the same time
- */
- dep = rewrite_m(prop->visible.expr);
- dep = expr_transform(dep);
- 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;
-
- /*
- * Handle selects and implies, which modify the
- * dependencies of the selected/implied symbol
- */
- 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)));
- } else if (prop->type == P_IMPLY) {
- struct symbol *es = prop_get_symbol(prop);
- es->implied.expr = expr_alloc_or(es->implied.expr,
- expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
- }
- }
- }
-
- if (sym && sym_is_choice(sym))
- expr_free(parentdep);
-
- /*
- * Recursively process children in the same fashion before
- * moving on
- */
- for (menu = parent->list; menu; menu = menu->next)
- menu_finalize(menu);
- } else if (sym) {
- /*
- * Automatic submenu creation. If sym is a symbol and A, B, C,
- * ... are consecutive items (symbols, menus, ifs, etc.) that
- * all depend on sym, then the following menu structure is
- * created:
- *
- * sym
- * +-A
- * +-B
- * +-C
- * ...
- *
- * This also works recursively, giving the following structure
- * if A is a symbol and B depends on A:
- *
- * sym
- * +-A
- * | +-B
- * +-C
- * ...
- */
-
- basedep = parent->prompt ? parent->prompt->visible.expr : NULL;
- basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no);
- basedep = expr_eliminate_dups(expr_transform(basedep));
-
- /* Examine consecutive elements after sym */
- 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))
- /* No dependency, quit */
- break;
- if (expr_depends_symbol(dep, sym))
- /* Absolute dependency, put in submenu */
- goto next;
-
- /*
- * Also consider it a dependency on sym if our
- * dependencies contain sym and are a "superset" of
- * sym's dependencies, e.g. '(sym || Q) && R' when sym
- * depends on R.
- *
- * Note that 'R' might be from an enclosing menu or if,
- * making this a more common case than it might seem.
- */
- 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)) {
- /* Not superset, quit */
- expr_free(dep2);
- break;
- }
- /* Superset, put in submenu */
- expr_free(dep2);
- next:
- menu_finalize(menu);
- menu->parent = parent;
- last_menu = menu;
- }
- expr_free(basedep);
- if (last_menu) {
- parent->list = parent->next;
- parent->next = last_menu->next;
- last_menu->next = NULL;
- }
-
- sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep);
- }
- for (menu = parent->list; menu; menu = menu->next) {
- if (sym && sym_is_choice(sym) &&
- menu->sym && !sym_is_choice_value(menu->sym)) {
- current_entry = menu;
- 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_DEFAULT)
- prop_warn(prop, "defaults for choice "
- "values not supported");
- if (prop->menu == menu)
- continue;
- if (prop->type == P_PROMPT &&
- prop->menu->parent->sym != sym)
- prop_warn(prop, "choice value used outside its choice group");
- }
- /* Non-tristate choice values of tristate choices must
- * depend on the choice being set to Y. The choice
- * values' dependencies were propagated to their
- * properties above, so the change here must be re-
- * propagated.
- */
- if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) {
- basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes);
- menu->dep = expr_alloc_and(basedep, menu->dep);
- for (prop = menu->sym->prop; prop; prop = prop->next) {
- if (prop->menu != menu)
- continue;
- prop->visible.expr = expr_alloc_and(expr_copy(basedep),
- prop->visible.expr);
- }
- }
- 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_LIST, NULL);
- (*ep)->right.sym = menu->sym;
- }
-
- /*
- * This code serves two purposes:
- *
- * (1) Flattening 'if' blocks, which do not specify a submenu
- * and only add dependencies.
- *
- * (Automatic submenu creation might still create a submenu
- * from an 'if' before this code runs.)
- *
- * (2) "Undoing" any automatic submenus created earlier below
- * promptless symbols.
- *
- * Before:
- *
- * A
- * if ... (or promptless symbol)
- * +-B
- * +-C
- * D
- *
- * After:
- *
- * A
- * if ... (or promptless symbol)
- * B
- * C
- * D
- */
- 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");
-
- if (sym_is_choice(sym) && !parent->prompt)
- menu_warn(parent, "choice must have a prompt");
-
- /* Check properties connected to this symbol */
- sym_check_prop(sym);
- sym->flags |= SYMBOL_WARNED;
- }
-
- /*
- * For non-optional choices, add a reverse dependency (corresponding to
- * a select) of '<visibility> && m'. This prevents the user from
- * setting the choice mode to 'n' when the choice is visible.
- *
- * This would also work for non-choice symbols, but only non-optional
- * choices clear SYMBOL_OPTIONAL as of writing. Choices are implemented
- * as a type of symbol.
- */
- 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_has_prompt(struct menu *menu)
-{
- if (!menu->prompt)
- return false;
- return true;
-}
-
-/*
- * Determine if a menu is empty.
- * A menu is considered empty if it contains no or only
- * invisible entries.
- */
-bool menu_is_empty(struct menu *menu)
-{
- struct menu *child;
-
- for (child = menu->list; child; child = child->next) {
- if (menu_is_visible(child))
- return(false);
- }
- return(true);
-}
-
-bool menu_is_visible(struct menu *menu)
-{
- struct menu *child;
- struct symbol *sym;
- tristate visible;
-
- if (!menu->prompt)
- return false;
-
- if (menu->visibility) {
- if (expr_calc_value(menu->visibility) == no)
- 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)) {
- if (sym)
- sym->flags |= SYMBOL_DEF_USER;
- 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_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;
-}
-
-bool menu_has_help(struct menu *menu)
-{
- return menu->help != NULL;
-}
-
-const char *menu_get_help(struct menu *menu)
-{
- if (menu->help)
- return menu->help;
- else
- return "";
-}
-
-static void get_def_str(struct gstr *r, struct menu *menu)
-{
- str_printf(r, "Defined at %s:%d\n",
- menu->file->name, menu->lineno);
-}
-
-static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
-{
- if (!expr_is_yes(expr)) {
- str_append(r, prefix);
- expr_gstr_print(expr, r);
- str_append(r, "\n");
- }
-}
-
-static void get_prompt_str(struct gstr *r, struct property *prop,
- struct list_head *head)
-{
- int i, j;
- struct menu *submenu[8], *menu, *location = NULL;
- struct jump_key *jump = NULL;
-
- str_printf(r, " Prompt: %s\n", prop->text);
-
- get_dep_str(r, prop->menu->dep, " Depends on: ");
- /*
- * Most prompts in Linux have visibility that exactly matches their
- * dependencies. For these, we print only the dependencies to improve
- * readability. However, prompts with inline "if" expressions and
- * prompts with a parent that has a "visible if" expression have
- * differing dependencies and visibility. In these rare cases, we
- * print both.
- */
- if (!expr_eq(prop->menu->dep, prop->visible.expr))
- get_dep_str(r, prop->visible.expr, " Visible if: ");
-
- menu = prop->menu;
- for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
- submenu[i++] = menu;
- if (location == NULL && menu_is_visible(menu))
- location = menu;
- }
- if (head && location) {
- jump = xmalloc(sizeof(struct jump_key));
-
- jump->target = location;
-
- if (list_empty(head))
- jump->index = 0;
- else
- jump->index = list_entry(head->prev, struct jump_key,
- entries)->index + 1;
-
- list_add_tail(&jump->entries, head);
- }
-
- str_printf(r, " Location:\n");
- for (j = 4; --i >= 0; j += 2) {
- menu = submenu[i];
- if (jump && menu == location)
- jump->offset = strlen(r->s);
- 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_props_str(struct gstr *r, struct symbol *sym,
- enum prop_type tok, const char *prefix)
-{
- bool hit = false;
- struct property *prop;
-
- for_all_properties(sym, prop, tok) {
- if (!hit) {
- str_append(r, prefix);
- hit = true;
- } else
- str_printf(r, " && ");
- expr_gstr_print(prop->expr, r);
- }
- if (hit)
- str_append(r, "\n");
-}
-
-/*
- * head is optional and may be NULL
- */
-static void get_symbol_str(struct gstr *r, struct symbol *sym,
- struct list_head *head)
-{
- struct property *prop;
-
- if (sym && sym->name) {
- str_printf(r, "Symbol: %s [=%s]\n", sym->name,
- sym_get_string_value(sym));
- str_printf(r, "Type : %s\n", sym_type_name(sym->type));
- if (sym->type == S_INT || sym->type == S_HEX) {
- prop = sym_get_range_prop(sym);
- if (prop) {
- str_printf(r, "Range : ");
- expr_gstr_print(prop->expr, r);
- str_append(r, "\n");
- }
- }
- }
-
- /* Print the definitions with prompts before the ones without */
- for_all_properties(sym, prop, P_SYMBOL) {
- if (prop->menu->prompt) {
- get_def_str(r, prop->menu);
- get_prompt_str(r, prop->menu->prompt, head);
- }
- }
-
- for_all_properties(sym, prop, P_SYMBOL) {
- if (!prop->menu->prompt) {
- get_def_str(r, prop->menu);
- get_dep_str(r, prop->menu->dep, " Depends on: ");
- }
- }
-
- get_symbol_props_str(r, sym, P_SELECT, "Selects: ");
- if (sym->rev_dep.expr) {
- expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, "Selected by [y]:\n");
- expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, "Selected by [m]:\n");
- expr_gstr_print_revdep(sym->rev_dep.expr, r, no, "Selected by [n]:\n");
- }
-
- get_symbol_props_str(r, sym, P_IMPLY, "Implies: ");
- if (sym->implied.expr) {
- expr_gstr_print_revdep(sym->implied.expr, r, yes, "Implied by [y]:\n");
- expr_gstr_print_revdep(sym->implied.expr, r, mod, "Implied by [m]:\n");
- expr_gstr_print_revdep(sym->implied.expr, r, no, "Implied by [n]:\n");
- }
-
- str_append(r, "\n\n");
-}
-
-struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
-{
- 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, head);
- if (!i)
- str_append(&res, "No matches found.\n");
- return res;
-}
-
-
-void menu_get_ext_help(struct menu *menu, struct gstr *help)
-{
- struct symbol *sym = menu->sym;
- const char *help_text = nohelp_text;
-
- if (menu_has_help(menu)) {
- if (sym->name)
- str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
- help_text = menu_get_help(menu);
- }
- str_printf(help, "%s\n", help_text);
- if (sym)
- get_symbol_str(help, sym, NULL);
-}
diff --git a/tools/kconfig/parser.y b/tools/kconfig/parser.y
deleted file mode 100644
index 2af7ce4..0000000
--- a/tools/kconfig/parser.y
+++ /dev/null
@@ -1,716 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- */
-%{
-
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-
-#include "lkc.h"
-#include "internal.h"
-
-#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt)
-
-#define PRINTD 0x0001
-#define DEBUG_PARSE 0x0002
-
-int cdebug = PRINTD;
-
-static void yyerror(const char *err);
-static void zconfprint(const char *err, ...);
-static void zconf_error(const char *err, ...);
-static bool zconf_endtoken(const char *tokenname,
- const char *expected_tokenname);
-
-struct symbol *symbol_hash[SYMBOL_HASHSIZE];
-
-struct menu *current_menu, *current_entry;
-
-%}
-
-%union
-{
- char *string;
- struct symbol *symbol;
- struct expr *expr;
- struct menu *menu;
- enum symbol_type type;
- enum variable_flavor flavor;
-}
-
-%token <string> T_HELPTEXT
-%token <string> T_WORD
-%token <string> T_WORD_QUOTE
-%token T_BOOL
-%token T_CHOICE
-%token T_CLOSE_PAREN
-%token T_COLON_EQUAL
-%token T_COMMENT
-%token T_CONFIG
-%token T_DEFAULT
-%token T_DEF_BOOL
-%token T_DEF_TRISTATE
-%token T_DEPENDS
-%token T_ENDCHOICE
-%token T_ENDIF
-%token T_ENDMENU
-%token T_HELP
-%token T_HEX
-%token T_IF
-%token T_IMPLY
-%token T_INT
-%token T_MAINMENU
-%token T_MENU
-%token T_MENUCONFIG
-%token T_MODULES
-%token T_ON
-%token T_OPEN_PAREN
-%token T_OPTIONAL
-%token T_PLUS_EQUAL
-%token T_PROMPT
-%token T_RANGE
-%token T_SELECT
-%token T_SOURCE
-%token T_STRING
-%token T_TRISTATE
-%token T_VISIBLE
-%token T_EOL
-%token <string> T_ASSIGN_VAL
-
-%left T_OR
-%left T_AND
-%left T_EQUAL T_UNEQUAL
-%left T_LESS T_LESS_EQUAL T_GREATER T_GREATER_EQUAL
-%nonassoc T_NOT
-
-%type <symbol> nonconst_symbol
-%type <symbol> symbol
-%type <type> type logic_type default
-%type <expr> expr
-%type <expr> if_expr
-%type <string> end
-%type <menu> if_entry menu_entry choice_entry
-%type <string> word_opt assign_val
-%type <flavor> assign_op
-
-%destructor {
- fprintf(stderr, "%s:%d: missing end statement for this entry\n",
- $$->file->name, $$->lineno);
- if (current_menu == $$)
- menu_end_menu();
-} if_entry menu_entry choice_entry
-
-%%
-input: mainmenu_stmt stmt_list | stmt_list;
-
-/* mainmenu entry */
-
-mainmenu_stmt: T_MAINMENU T_WORD_QUOTE T_EOL
-{
- menu_add_prompt(P_MENU, $2, NULL);
-};
-
-stmt_list:
- /* empty */
- | stmt_list assignment_stmt
- | stmt_list choice_stmt
- | stmt_list comment_stmt
- | stmt_list config_stmt
- | stmt_list if_stmt
- | stmt_list menu_stmt
- | stmt_list menuconfig_stmt
- | stmt_list source_stmt
- | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
- | stmt_list error T_EOL { zconf_error("invalid statement"); }
-;
-
-stmt_list_in_choice:
- /* empty */
- | stmt_list_in_choice comment_stmt
- | stmt_list_in_choice config_stmt
- | stmt_list_in_choice if_stmt_in_choice
- | stmt_list_in_choice error T_EOL { zconf_error("invalid statement"); }
-;
-
-/* config/menuconfig entry */
-
-config_entry_start: T_CONFIG nonconst_symbol T_EOL
-{
- $2->flags |= SYMBOL_OPTIONAL;
- menu_add_entry($2);
- printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2->name);
-};
-
-config_stmt: config_entry_start config_option_list
-{
- printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
-};
-
-menuconfig_entry_start: T_MENUCONFIG nonconst_symbol T_EOL
-{
- $2->flags |= SYMBOL_OPTIONAL;
- menu_add_entry($2);
- printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2->name);
-};
-
-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");
- 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: type prompt_stmt_opt T_EOL
-{
- menu_set_type($1);
- printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
- zconf_curname(), zconf_lineno(),
- $1);
-};
-
-config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
-{
- menu_add_prompt(P_PROMPT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
-};
-
-config_option: default expr if_expr T_EOL
-{
- menu_add_expr(P_DEFAULT, $2, $3);
- if ($1 != S_UNKNOWN)
- menu_set_type($1);
- printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
- zconf_curname(), zconf_lineno(),
- $1);
-};
-
-config_option: T_SELECT nonconst_symbol if_expr T_EOL
-{
- menu_add_symbol(P_SELECT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
-};
-
-config_option: T_IMPLY nonconst_symbol if_expr T_EOL
-{
- menu_add_symbol(P_IMPLY, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:imply\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());
-};
-
-config_option: T_MODULES T_EOL
-{
- if (modules_sym)
- zconf_error("symbol '%s' redefines option 'modules' already defined by symbol '%s'",
- current_entry->sym->name, modules_sym->name);
- modules_sym = current_entry->sym;
-};
-
-/* choice entry */
-
-choice: T_CHOICE word_opt T_EOL
-{
- struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
- sym->flags |= SYMBOL_NO_WRITE;
- menu_add_entry(sym);
- menu_add_expr(P_CHOICE, NULL, NULL);
- free($2);
- printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
-};
-
-choice_entry: choice choice_option_list
-{
- $$ = menu_add_menu();
-};
-
-choice_end: end
-{
- if (zconf_endtoken($1, "choice")) {
- menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
- }
-};
-
-choice_stmt: choice_entry stmt_list_in_choice choice_end
-;
-
-choice_option_list:
- /* empty */
- | choice_option_list choice_option
- | choice_option_list depends
- | choice_option_list help
-;
-
-choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
-{
- menu_add_prompt(P_PROMPT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
-};
-
-choice_option: logic_type prompt_stmt_opt T_EOL
-{
- menu_set_type($1);
- printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
- zconf_curname(), zconf_lineno(), $1);
-};
-
-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 nonconst_symbol if_expr T_EOL
-{
- menu_add_symbol(P_DEFAULT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:default\n",
- zconf_curname(), zconf_lineno());
-};
-
-type:
- logic_type
- | T_INT { $$ = S_INT; }
- | T_HEX { $$ = S_HEX; }
- | T_STRING { $$ = S_STRING; }
-
-logic_type:
- T_BOOL { $$ = S_BOOLEAN; }
- | T_TRISTATE { $$ = S_TRISTATE; }
-
-default:
- T_DEFAULT { $$ = S_UNKNOWN; }
- | T_DEF_BOOL { $$ = S_BOOLEAN; }
- | T_DEF_TRISTATE { $$ = S_TRISTATE; }
-
-/* if entry */
-
-if_entry: 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_add_menu();
-};
-
-if_end: end
-{
- if (zconf_endtoken($1, "if")) {
- menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
- }
-};
-
-if_stmt: if_entry stmt_list if_end
-;
-
-if_stmt_in_choice: if_entry stmt_list_in_choice if_end
-;
-
-/* menu entry */
-
-menu: T_MENU T_WORD_QUOTE T_EOL
-{
- menu_add_entry(NULL);
- menu_add_prompt(P_MENU, $2, NULL);
- printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
-};
-
-menu_entry: menu menu_option_list
-{
- $$ = menu_add_menu();
-};
-
-menu_end: end
-{
- if (zconf_endtoken($1, "menu")) {
- menu_end_menu();
- printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
- }
-};
-
-menu_stmt: menu_entry stmt_list menu_end
-;
-
-menu_option_list:
- /* empty */
- | menu_option_list visible
- | menu_option_list depends
-;
-
-source_stmt: T_SOURCE T_WORD_QUOTE T_EOL
-{
- printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2);
- zconf_nextfile($2);
- free($2);
-};
-
-/* comment entry */
-
-comment: T_COMMENT T_WORD_QUOTE T_EOL
-{
- menu_add_entry(NULL);
- menu_add_prompt(P_COMMENT, $2, NULL);
- printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
-};
-
-comment_stmt: comment comment_option_list
-;
-
-comment_option_list:
- /* empty */
- | comment_option_list depends
-;
-
-/* 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
-{
- if (current_entry->help) {
- free(current_entry->help);
- zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used",
- current_entry->sym->name ?: "<choice>");
- }
-
- /* Is the help text empty or all whitespace? */
- if ($2[strspn($2, " \f\n\r\t\v")] == '\0')
- zconfprint("warning: '%s' defined with blank help text",
- current_entry->sym->name ?: "<choice>");
-
- current_entry->help = $2;
-};
-
-/* depends option */
-
-depends: T_DEPENDS T_ON expr T_EOL
-{
- menu_add_dep($3);
- printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
-};
-
-/* visibility option */
-visible: T_VISIBLE if_expr T_EOL
-{
- menu_add_visibility($2);
-};
-
-/* prompt statement */
-
-prompt_stmt_opt:
- /* empty */
- | T_WORD_QUOTE if_expr
-{
- menu_add_prompt(P_PROMPT, $1, $2);
-};
-
-end: T_ENDMENU T_EOL { $$ = "menu"; }
- | T_ENDCHOICE T_EOL { $$ = "choice"; }
- | T_ENDIF T_EOL { $$ = "if"; }
-;
-
-if_expr: /* empty */ { $$ = NULL; }
- | T_IF expr { $$ = $2; }
-;
-
-expr: symbol { $$ = expr_alloc_symbol($1); }
- | symbol T_LESS symbol { $$ = expr_alloc_comp(E_LTH, $1, $3); }
- | symbol T_LESS_EQUAL symbol { $$ = expr_alloc_comp(E_LEQ, $1, $3); }
- | symbol T_GREATER symbol { $$ = expr_alloc_comp(E_GTH, $1, $3); }
- | symbol T_GREATER_EQUAL symbol { $$ = expr_alloc_comp(E_GEQ, $1, $3); }
- | 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); }
-;
-
-/* For symbol definitions, selects, etc., where quotes are not accepted */
-nonconst_symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); };
-
-symbol: nonconst_symbol
- | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); }
-;
-
-word_opt: /* empty */ { $$ = NULL; }
- | T_WORD
-
-/* assignment statement */
-
-assignment_stmt: T_WORD assign_op assign_val T_EOL { variable_add($1, $3, $2); free($1); free($3); }
-
-assign_op:
- T_EQUAL { $$ = VAR_RECURSIVE; }
- | T_COLON_EQUAL { $$ = VAR_SIMPLE; }
- | T_PLUS_EQUAL { $$ = VAR_APPEND; }
-;
-
-assign_val:
- /* empty */ { $$ = xstrdup(""); };
- | T_ASSIGN_VAL
-;
-
-%%
-
-void conf_parse(const char *name)
-{
- struct symbol *sym;
- int i;
-
- zconf_initscan(name);
-
- _menu_init();
-
- if (getenv("ZCONF_DEBUG"))
- yydebug = 1;
- yyparse();
-
- /* Variables are expanded in the parse phase. We can free them here. */
- variable_all_del();
-
- if (yynerrs)
- exit(1);
- if (!modules_sym)
- modules_sym = sym_find( "n" );
-
- if (!menu_has_prompt(&rootmenu)) {
- current_entry = &rootmenu;
- menu_add_prompt(P_MENU, "Main menu", NULL);
- }
-
- menu_finalize(&rootmenu);
- for_all_symbols(i, sym) {
- if (sym_check_deps(sym))
- yynerrs++;
- }
- if (yynerrs)
- exit(1);
- conf_set_changed(true);
-}
-
-static bool zconf_endtoken(const char *tokenname,
- const char *expected_tokenname)
-{
- if (strcmp(tokenname, expected_tokenname)) {
- zconf_error("unexpected '%s' within %s block",
- tokenname, expected_tokenname);
- yynerrs++;
- return false;
- }
- if (current_menu->file != current_file) {
- zconf_error("'%s' in different file than '%s'",
- tokenname, expected_tokenname);
- fprintf(stderr, "%s:%d: location of the '%s'\n",
- current_menu->file->name, current_menu->lineno,
- expected_tokenname);
- yynerrs++;
- return false;
- }
- return true;
-}
-
-static void zconfprint(const char *err, ...)
-{
- va_list ap;
-
- fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
- va_start(ap, err);
- vfprintf(stderr, err, ap);
- va_end(ap);
- fprintf(stderr, "\n");
-}
-
-static void zconf_error(const char *err, ...)
-{
- va_list ap;
-
- yynerrs++;
- fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno());
- va_start(ap, err);
- vfprintf(stderr, err, ap);
- va_end(ap);
- fprintf(stderr, "\n");
-}
-
-static void yyerror(const char *err)
-{
- fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err);
-}
-
-static 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);
-}
-
-static void print_symbol(FILE *out, struct menu *menu)
-{
- struct symbol *sym = menu->sym;
- struct property *prop;
-
- if (sym_is_choice(sym))
- fprintf(out, "\nchoice\n");
- else
- fprintf(out, "\nconfig %s\n", sym->name);
- switch (sym->type) {
- case S_BOOLEAN:
- fputs(" bool\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;
- case P_SELECT:
- fputs( " select ", out);
- expr_fprint(prop->expr, out);
- fputc('\n', out);
- break;
- case P_IMPLY:
- fputs( " imply ", out);
- expr_fprint(prop->expr, out);
- fputc('\n', out);
- break;
- case P_RANGE:
- fputs( " range ", out);
- expr_fprint(prop->expr, out);
- fputc('\n', out);
- break;
- case P_MENU:
- fputs( " menu ", out);
- print_quoted_string(out, prop->text);
- fputc('\n', out);
- break;
- case P_SYMBOL:
- fputs( " symbol ", out);
- fprintf(out, "%s\n", prop->menu->sym->name);
- break;
- default:
- fprintf(out, " unknown prop %d!\n", prop->type);
- break;
- }
- }
- if (menu->help) {
- int len = strlen(menu->help);
- while (menu->help[--len] == '\n')
- menu->help[len] = 0;
- fprintf(out, " help\n%s\n", menu->help);
- }
-}
-
-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);
- }
- }
-
- 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;
- }
- }
- }
-}
diff --git a/tools/kconfig/preprocess.c b/tools/kconfig/preprocess.c
deleted file mode 100644
index 748da57..0000000
--- a/tools/kconfig/preprocess.c
+++ /dev/null
@@ -1,574 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com>
-
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "list.h"
-#include "lkc.h"
-
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-
-static char *expand_string_with_args(const char *in, int argc, char *argv[]);
-static char *expand_string(const char *in);
-
-static void __attribute__((noreturn)) pperror(const char *format, ...)
-{
- va_list ap;
-
- fprintf(stderr, "%s:%d: ", current_file->name, yylineno);
- va_start(ap, format);
- vfprintf(stderr, format, ap);
- va_end(ap);
- fprintf(stderr, "\n");
-
- exit(1);
-}
-
-/*
- * Environment variables
- */
-static LIST_HEAD(env_list);
-
-struct env {
- char *name;
- char *value;
- struct list_head node;
-};
-
-static void env_add(const char *name, const char *value)
-{
- struct env *e;
-
- e = xmalloc(sizeof(*e));
- e->name = xstrdup(name);
- e->value = xstrdup(value);
-
- list_add_tail(&e->node, &env_list);
-}
-
-static void env_del(struct env *e)
-{
- list_del(&e->node);
- free(e->name);
- free(e->value);
- free(e);
-}
-
-/* The returned pointer must be freed when done */
-static char *env_expand(const char *name)
-{
- struct env *e;
- const char *value;
-
- if (!*name)
- return NULL;
-
- list_for_each_entry(e, &env_list, node) {
- if (!strcmp(name, e->name))
- return xstrdup(e->value);
- }
-
- value = getenv(name);
- if (!value)
- return NULL;
-
- /*
- * We need to remember all referenced environment variables.
- * They will be written out to include/config/auto.conf.cmd
- */
- env_add(name, value);
-
- return xstrdup(value);
-}
-
-void env_write_dep(FILE *f, const char *autoconfig_name)
-{
- struct env *e, *tmp;
-
- list_for_each_entry_safe(e, tmp, &env_list, node) {
- fprintf(f, "ifneq \"$(%s)\" \"%s\"\n", e->name, e->value);
- fprintf(f, "%s: FORCE\n", autoconfig_name);
- fprintf(f, "endif\n");
- env_del(e);
- }
-}
-
-/*
- * Built-in functions
- */
-struct function {
- const char *name;
- unsigned int min_args;
- unsigned int max_args;
- char *(*func)(int argc, char *argv[]);
-};
-
-static char *do_error_if(int argc, char *argv[])
-{
- if (!strcmp(argv[0], "y"))
- pperror("%s", argv[1]);
-
- return xstrdup("");
-}
-
-static char *do_filename(int argc, char *argv[])
-{
- return xstrdup(current_file->name);
-}
-
-static char *do_info(int argc, char *argv[])
-{
- printf("%s\n", argv[0]);
-
- return xstrdup("");
-}
-
-static char *do_lineno(int argc, char *argv[])
-{
- char buf[16];
-
- sprintf(buf, "%d", yylineno);
-
- return xstrdup(buf);
-}
-
-static char *do_shell(int argc, char *argv[])
-{
- FILE *p;
- char buf[4096];
- char *cmd;
- size_t nread;
- int i;
-
- cmd = argv[0];
-
- p = popen(cmd, "r");
- if (!p) {
- perror(cmd);
- exit(1);
- }
-
- nread = fread(buf, 1, sizeof(buf), p);
- if (nread == sizeof(buf))
- nread--;
-
- /* remove trailing new lines */
- while (nread > 0 && buf[nread - 1] == '\n')
- nread--;
-
- buf[nread] = 0;
-
- /* replace a new line with a space */
- for (i = 0; i < nread; i++) {
- if (buf[i] == '\n')
- buf[i] = ' ';
- }
-
- if (pclose(p) == -1) {
- perror(cmd);
- exit(1);
- }
-
- return xstrdup(buf);
-}
-
-static char *do_warning_if(int argc, char *argv[])
-{
- if (!strcmp(argv[0], "y"))
- fprintf(stderr, "%s:%d: %s\n",
- current_file->name, yylineno, argv[1]);
-
- return xstrdup("");
-}
-
-static const struct function function_table[] = {
- /* Name MIN MAX Function */
- { "error-if", 2, 2, do_error_if },
- { "filename", 0, 0, do_filename },
- { "info", 1, 1, do_info },
- { "lineno", 0, 0, do_lineno },
- { "shell", 1, 1, do_shell },
- { "warning-if", 2, 2, do_warning_if },
-};
-
-#define FUNCTION_MAX_ARGS 16
-
-static char *function_expand(const char *name, int argc, char *argv[])
-{
- const struct function *f;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(function_table); i++) {
- f = &function_table[i];
- if (strcmp(f->name, name))
- continue;
-
- if (argc < f->min_args)
- pperror("too few function arguments passed to '%s'",
- name);
-
- if (argc > f->max_args)
- pperror("too many function arguments passed to '%s'",
- name);
-
- return f->func(argc, argv);
- }
-
- return NULL;
-}
-
-/*
- * Variables (and user-defined functions)
- */
-static LIST_HEAD(variable_list);
-
-struct variable {
- char *name;
- char *value;
- enum variable_flavor flavor;
- int exp_count;
- struct list_head node;
-};
-
-static struct variable *variable_lookup(const char *name)
-{
- struct variable *v;
-
- list_for_each_entry(v, &variable_list, node) {
- if (!strcmp(name, v->name))
- return v;
- }
-
- return NULL;
-}
-
-static char *variable_expand(const char *name, int argc, char *argv[])
-{
- struct variable *v;
- char *res;
-
- v = variable_lookup(name);
- if (!v)
- return NULL;
-
- if (argc == 0 && v->exp_count)
- pperror("Recursive variable '%s' references itself (eventually)",
- name);
-
- if (v->exp_count > 1000)
- pperror("Too deep recursive expansion");
-
- v->exp_count++;
-
- if (v->flavor == VAR_RECURSIVE)
- res = expand_string_with_args(v->value, argc, argv);
- else
- res = xstrdup(v->value);
-
- v->exp_count--;
-
- return res;
-}
-
-void variable_add(const char *name, const char *value,
- enum variable_flavor flavor)
-{
- struct variable *v;
- char *new_value;
- bool append = false;
-
- v = variable_lookup(name);
- if (v) {
- /* For defined variables, += inherits the existing flavor */
- if (flavor == VAR_APPEND) {
- flavor = v->flavor;
- append = true;
- } else {
- free(v->value);
- }
- } else {
- /* For undefined variables, += assumes the recursive flavor */
- if (flavor == VAR_APPEND)
- flavor = VAR_RECURSIVE;
-
- v = xmalloc(sizeof(*v));
- v->name = xstrdup(name);
- v->exp_count = 0;
- list_add_tail(&v->node, &variable_list);
- }
-
- v->flavor = flavor;
-
- if (flavor == VAR_SIMPLE)
- new_value = expand_string(value);
- else
- new_value = xstrdup(value);
-
- if (append) {
- v->value = xrealloc(v->value,
- strlen(v->value) + strlen(new_value) + 2);
- strcat(v->value, " ");
- strcat(v->value, new_value);
- free(new_value);
- } else {
- v->value = new_value;
- }
-}
-
-static void variable_del(struct variable *v)
-{
- list_del(&v->node);
- free(v->name);
- free(v->value);
- free(v);
-}
-
-void variable_all_del(void)
-{
- struct variable *v, *tmp;
-
- list_for_each_entry_safe(v, tmp, &variable_list, node)
- variable_del(v);
-}
-
-/*
- * Evaluate a clause with arguments. argc/argv are arguments from the upper
- * function call.
- *
- * Returned string must be freed when done
- */
-static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
-{
- char *tmp, *name, *res, *endptr, *prev, *p;
- int new_argc = 0;
- char *new_argv[FUNCTION_MAX_ARGS];
- int nest = 0;
- int i;
- unsigned long n;
-
- tmp = xstrndup(str, len);
-
- /*
- * If variable name is '1', '2', etc. It is generally an argument
- * from a user-function call (i.e. local-scope variable). If not
- * available, then look-up global-scope variables.
- */
- n = strtoul(tmp, &endptr, 10);
- if (!*endptr && n > 0 && n <= argc) {
- res = xstrdup(argv[n - 1]);
- goto free_tmp;
- }
-
- prev = p = tmp;
-
- /*
- * Split into tokens
- * The function name and arguments are separated by a comma.
- * For example, if the function call is like this:
- * $(foo,$(x),$(y))
- *
- * The input string for this helper should be:
- * foo,$(x),$(y)
- *
- * and split into:
- * new_argv[0] = 'foo'
- * new_argv[1] = '$(x)'
- * new_argv[2] = '$(y)'
- */
- while (*p) {
- if (nest == 0 && *p == ',') {
- *p = 0;
- if (new_argc >= FUNCTION_MAX_ARGS)
- pperror("too many function arguments");
- new_argv[new_argc++] = prev;
- prev = p + 1;
- } else if (*p == '(') {
- nest++;
- } else if (*p == ')') {
- nest--;
- }
-
- p++;
- }
- new_argv[new_argc++] = prev;
-
- /*
- * Shift arguments
- * new_argv[0] represents a function name or a variable name. Put it
- * into 'name', then shift the rest of the arguments. This simplifies
- * 'const' handling.
- */
- name = expand_string_with_args(new_argv[0], argc, argv);
- new_argc--;
- for (i = 0; i < new_argc; i++)
- new_argv[i] = expand_string_with_args(new_argv[i + 1],
- argc, argv);
-
- /* Search for variables */
- res = variable_expand(name, new_argc, new_argv);
- if (res)
- goto free;
-
- /* Look for built-in functions */
- res = function_expand(name, new_argc, new_argv);
- if (res)
- goto free;
-
- /* Last, try environment variable */
- if (new_argc == 0) {
- res = env_expand(name);
- if (res)
- goto free;
- }
-
- res = xstrdup("");
-free:
- for (i = 0; i < new_argc; i++)
- free(new_argv[i]);
- free(name);
-free_tmp:
- free(tmp);
-
- return res;
-}
-
-/*
- * Expand a string that follows '$'
- *
- * For example, if the input string is
- * ($(FOO)$($(BAR)))$(BAZ)
- * this helper evaluates
- * $($(FOO)$($(BAR)))
- * and returns a new string containing the expansion (note that the string is
- * recursively expanded), also advancing 'str' to point to the next character
- * after the corresponding closing parenthesis, in this case, *str will be
- * $(BAR)
- */
-static char *expand_dollar_with_args(const char **str, int argc, char *argv[])
-{
- const char *p = *str;
- const char *q;
- int nest = 0;
-
- /*
- * In Kconfig, variable/function references always start with "$(".
- * Neither single-letter variables as in $A nor curly braces as in ${CC}
- * are supported. '$' not followed by '(' loses its special meaning.
- */
- if (*p != '(') {
- *str = p;
- return xstrdup("$");
- }
-
- p++;
- q = p;
- while (*q) {
- if (*q == '(') {
- nest++;
- } else if (*q == ')') {
- if (nest-- == 0)
- break;
- }
- q++;
- }
-
- if (!*q)
- pperror("unterminated reference to '%s': missing ')'", p);
-
- /* Advance 'str' to after the expanded initial portion of the string */
- *str = q + 1;
-
- return eval_clause(p, q - p, argc, argv);
-}
-
-char *expand_dollar(const char **str)
-{
- return expand_dollar_with_args(str, 0, NULL);
-}
-
-static char *__expand_string(const char **str, bool (*is_end)(char c),
- int argc, char *argv[])
-{
- const char *in, *p;
- char *expansion, *out;
- size_t in_len, out_len;
-
- out = xmalloc(1);
- *out = 0;
- out_len = 1;
-
- p = in = *str;
-
- while (1) {
- if (*p == '$') {
- in_len = p - in;
- p++;
- expansion = expand_dollar_with_args(&p, argc, argv);
- out_len += in_len + strlen(expansion);
- out = xrealloc(out, out_len);
- strncat(out, in, in_len);
- strcat(out, expansion);
- free(expansion);
- in = p;
- continue;
- }
-
- if (is_end(*p))
- break;
-
- p++;
- }
-
- in_len = p - in;
- out_len += in_len;
- out = xrealloc(out, out_len);
- strncat(out, in, in_len);
-
- /* Advance 'str' to the end character */
- *str = p;
-
- return out;
-}
-
-static bool is_end_of_str(char c)
-{
- return !c;
-}
-
-/*
- * Expand variables and functions in the given string. Undefined variables
- * expand to an empty string.
- * The returned string must be freed when done.
- */
-static char *expand_string_with_args(const char *in, int argc, char *argv[])
-{
- return __expand_string(&in, is_end_of_str, argc, argv);
-}
-
-static char *expand_string(const char *in)
-{
- return expand_string_with_args(in, 0, NULL);
-}
-
-static bool is_end_of_token(char c)
-{
- return !(isalnum(c) || c == '_' || c == '-');
-}
-
-/*
- * Expand variables in a token. The parsing stops when a token separater
- * (in most cases, it is a whitespace) is encountered. 'str' is updated to
- * point to the next character.
- *
- * The returned string must be freed when done.
- */
-char *expand_one_token(const char **str)
-{
- return __expand_string(str, is_end_of_token, 0, NULL);
-}
diff --git a/tools/kconfig/symbol.c b/tools/kconfig/symbol.c
deleted file mode 100644
index 0572330..0000000
--- a/tools/kconfig/symbol.c
+++ /dev/null
@@ -1,1270 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
- */
-
-#include <sys/types.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <regex.h>
-
-#include "lkc.h"
-
-struct symbol symbol_yes = {
- .name = "y",
- .curr = { "y", yes },
- .flags = SYMBOL_CONST|SYMBOL_VALID,
-};
-
-struct symbol symbol_mod = {
- .name = "m",
- .curr = { "m", mod },
- .flags = SYMBOL_CONST|SYMBOL_VALID,
-};
-
-struct symbol symbol_no = {
- .name = "n",
- .curr = { "n", no },
- .flags = SYMBOL_CONST|SYMBOL_VALID,
-};
-
-static struct symbol symbol_empty = {
- .name = "",
- .curr = { "", no },
- .flags = SYMBOL_VALID,
-};
-
-struct symbol *modules_sym;
-static tristate modules_val;
-
-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 "bool";
- 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";
- }
- return "???";
-}
-
-struct property *sym_get_choice_prop(struct symbol *sym)
-{
- struct property *prop;
-
- for_all_choices(sym, prop)
- return prop;
- return NULL;
-}
-
-static 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 long long sym_get_range_val(struct symbol *sym, int base)
-{
- sym_calc_value(sym);
- switch (sym->type) {
- case S_INT:
- base = 10;
- break;
- case S_HEX:
- base = 16;
- break;
- default:
- break;
- }
- return strtoll(sym->curr.val, NULL, base);
-}
-
-static void sym_validate_range(struct symbol *sym)
-{
- struct property *prop;
- int base;
- long long val, val2;
- char str[64];
-
- switch (sym->type) {
- case S_INT:
- base = 10;
- break;
- case S_HEX:
- base = 16;
- break;
- default:
- return;
- }
- prop = sym_get_range_prop(sym);
- if (!prop)
- return;
- val = strtoll(sym->curr.val, NULL, base);
- val2 = sym_get_range_val(prop->expr->left.sym, base);
- if (val >= val2) {
- val2 = sym_get_range_val(prop->expr->right.sym, base);
- if (val <= val2)
- return;
- }
- if (sym->type == S_INT)
- sprintf(str, "%lld", val2);
- else
- sprintf(str, "0x%llx", val2);
- sym->curr.val = xstrdup(str);
-}
-
-static 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;
- }
-}
-
-static void sym_set_all_changed(void)
-{
- struct symbol *sym;
- int i;
-
- for_all_symbols(i, sym)
- sym_set_changed(sym);
-}
-
-static void sym_calc_visibility(struct symbol *sym)
-{
- struct property *prop;
- struct symbol *choice_sym = NULL;
- tristate tri;
-
- /* any prompt visible? */
- tri = no;
-
- if (sym_is_choice_value(sym))
- choice_sym = prop_get_symbol(sym_get_choice_prop(sym));
-
- for_all_prompts(sym, prop) {
- prop->visible.tri = expr_calc_value(prop->visible.expr);
- /*
- * Tristate choice_values with visibility 'mod' are
- * not visible if the corresponding choice's value is
- * 'yes'.
- */
- if (choice_sym && sym->type == S_TRISTATE &&
- prop->visible.tri == mod && choice_sym->curr.tri == yes)
- prop->visible.tri = no;
-
- tri = EXPR_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;
- /* defaulting to "yes" if no explicit "depends on" are given */
- tri = yes;
- if (sym->dir_dep.expr)
- tri = expr_calc_value(sym->dir_dep.expr);
- if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
- tri = yes;
- if (sym->dir_dep.tri != tri) {
- sym->dir_dep.tri = tri;
- sym_set_changed(sym);
- }
- 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);
- }
- tri = no;
- if (sym->implied.expr)
- tri = expr_calc_value(sym->implied.expr);
- if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
- tri = yes;
- if (sym->implied.tri != tri) {
- sym->implied.tri = tri;
- sym_set_changed(sym);
- }
-}
-
-/*
- * Find the default symbol for a choice.
- * First try the default values for the choice symbol
- * Next locate the first visible choice value
- * Return NULL if none was found
- */
-struct symbol *sym_choice_default(struct symbol *sym)
-{
- struct symbol *def_sym;
- struct property *prop;
- struct expr *e;
-
- /* 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);
- if (def_sym->visible != no)
- return def_sym;
- }
-
- /* just get the first visible value */
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, def_sym)
- if (def_sym->visible != no)
- return def_sym;
-
- /* failed to locate any defaults */
- return NULL;
-}
-
-static struct symbol *sym_calc_choice(struct symbol *sym)
-{
- struct symbol *def_sym;
- struct property *prop;
- struct expr *e;
- int flags;
-
- /* first calculate all choice values' visibilities */
- flags = sym->flags;
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, def_sym) {
- sym_calc_visibility(def_sym);
- if (def_sym->visible != no)
- flags &= def_sym->flags;
- }
-
- sym->flags &= flags | ~SYMBOL_DEF_USER;
-
- /* is the user choice visible? */
- def_sym = sym->def[S_DEF_USER].val;
- if (def_sym && def_sym->visible != no)
- return def_sym;
-
- def_sym = sym_choice_default(sym);
-
- if (def_sym == NULL)
- /* no choice? reset tristate value */
- sym->curr.tri = no;
-
- return def_sym;
-}
-
-static void sym_warn_unmet_dep(struct symbol *sym)
-{
- struct gstr gs = str_new();
-
- str_printf(&gs,
- "\nWARNING: unmet direct dependencies detected for %s\n",
- sym->name);
- str_printf(&gs,
- " Depends on [%c]: ",
- sym->dir_dep.tri == mod ? 'm' : 'n');
- expr_gstr_print(sym->dir_dep.expr, &gs);
- str_printf(&gs, "\n");
-
- expr_gstr_print_revdep(sym->rev_dep.expr, &gs, yes,
- " Selected by [y]:\n");
- expr_gstr_print_revdep(sym->rev_dep.expr, &gs, mod,
- " Selected by [m]:\n");
-
- fputs(str_get(&gs), stderr);
-}
-
-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;
-
- if (sym_is_choice_value(sym) &&
- sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES) {
- sym->flags &= ~SYMBOL_NEED_SET_CHOICE_VALUES;
- prop = sym_get_choice_prop(sym);
- sym_calc_value(prop_get_symbol(prop));
- }
-
- 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;
- }
- sym->flags &= ~SYMBOL_WRITE;
-
- sym_calc_visibility(sym);
-
- if (sym->visible != no)
- sym->flags |= SYMBOL_WRITE;
-
- /* 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 (sym->visible != no) {
- /* if the symbol is visible use the user value
- * if available, otherwise try the default value
- */
- if (sym_has_value(sym)) {
- newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
- sym->visible);
- goto calc_newval;
- }
- }
- if (sym->rev_dep.tri != no)
- sym->flags |= SYMBOL_WRITE;
- if (!sym_is_choice(sym)) {
- prop = sym_get_default_prop(sym);
- if (prop) {
- newval.tri = EXPR_AND(expr_calc_value(prop->expr),
- prop->visible.tri);
- if (newval.tri != no)
- sym->flags |= SYMBOL_WRITE;
- }
- if (sym->implied.tri != no) {
- sym->flags |= SYMBOL_WRITE;
- newval.tri = EXPR_OR(newval.tri, sym->implied.tri);
- newval.tri = EXPR_AND(newval.tri,
- sym->dir_dep.tri);
- }
- }
- calc_newval:
- if (sym->dir_dep.tri < sym->rev_dep.tri)
- sym_warn_unmet_dep(sym);
- newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
- }
- 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_has_value(sym)) {
- newval.val = sym->def[S_DEF_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);
- sym_validate_range(sym);
-
- if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
- sym_set_changed(sym);
- if (modules_sym == sym) {
- sym_set_all_changed();
- modules_val = modules_sym->curr.tri;
- }
- }
-
- if (sym_is_choice(sym)) {
- struct symbol *choice_sym;
-
- prop = sym_get_choice_prop(sym);
- expr_list_for_each_sym(prop->expr, e, choice_sym) {
- if ((sym->flags & SYMBOL_WRITE) &&
- choice_sym->visible != no)
- choice_sym->flags |= SYMBOL_WRITE;
- if (sym->flags & SYMBOL_CHANGED)
- sym_set_changed(choice_sym);
- }
- }
-
- if (sym->flags & SYMBOL_NO_WRITE)
- sym->flags &= ~SYMBOL_WRITE;
-
- if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
- set_all_choice_values(sym);
-}
-
-void sym_clear_all_valid(void)
-{
- struct symbol *sym;
- int i;
-
- for_all_symbols(i, sym)
- sym->flags &= ~SYMBOL_VALID;
- conf_set_changed(true);
- sym_calc_value(modules_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_DEF_USER)) {
- sym->flags |= SYMBOL_DEF_USER;
- sym_set_changed(sym);
- }
- /*
- * setting a choice value also resets the new flag of the choice
- * symbol and all other choice values.
- */
- if (sym_is_choice_value(sym) && val == yes) {
- struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
- struct property *prop;
- struct expr *e;
-
- cs->def[S_DEF_USER].val = sym;
- cs->flags |= SYMBOL_DEF_USER;
- prop = sym_get_choice_prop(cs);
- for (e = prop->expr; e; e = e->left.expr) {
- if (e->right.sym->visible != no)
- e->right.sym->flags |= SYMBOL_DEF_USER;
- }
- }
-
- sym->def[S_DEF_USER].tri = val;
- if (oldval != val)
- sym_clear_all_valid();
-
- 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;
- long long 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 = strtoll(str, NULL, 10);
- return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
- val <= sym_get_range_val(prop->expr->right.sym, 10);
- case S_HEX:
- if (!sym_string_valid(sym, str))
- return false;
- prop = sym_get_range_prop(sym);
- if (!prop)
- return true;
- val = strtoll(str, NULL, 16);
- return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
- val <= sym_get_range_val(prop->expr->right.sym, 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_DEF_USER)) {
- sym->flags |= SYMBOL_DEF_USER;
- sym_set_changed(sym);
- }
-
- oldval = sym->def[S_DEF_USER].val;
- size = strlen(newval) + 1;
- if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
- size += 2;
- sym->def[S_DEF_USER].val = val = xmalloc(size);
- *val++ = '0';
- *val++ = 'x';
- } else if (!oldval || strcmp(oldval, newval))
- sym->def[S_DEF_USER].val = val = xmalloc(size);
- else
- return true;
-
- strcpy(val, newval);
- free((void *)oldval);
- sym_clear_all_valid();
-
- return true;
-}
-
-/*
- * Find the default value associated to a symbol.
- * For tristate symbol handle the modules=n case
- * in which case "m" becomes "y".
- * If the symbol does not have any default then fallback
- * to the fixed default values.
- */
-const char *sym_get_string_default(struct symbol *sym)
-{
- struct property *prop;
- struct symbol *ds;
- const char *str;
- tristate val;
-
- sym_calc_visibility(sym);
- sym_calc_value(modules_sym);
- val = symbol_no.curr.tri;
- str = symbol_empty.curr.val;
-
- /* If symbol has a default value look it up */
- prop = sym_get_default_prop(sym);
- if (prop != NULL) {
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- /* The visibility may limit the value from yes => mod */
- val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
- break;
- default:
- /*
- * The following fails to handle the situation
- * where a default value is further limited by
- * the valid range.
- */
- ds = prop_get_symbol(prop);
- if (ds != NULL) {
- sym_calc_value(ds);
- str = (const char *)ds->curr.val;
- }
- }
- }
-
- /* Handle select statements */
- val = EXPR_OR(val, sym->rev_dep.tri);
-
- /* transpose mod to yes if modules are not enabled */
- if (val == mod)
- if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
- val = yes;
-
- /* transpose mod to yes if type is bool */
- if (sym->type == S_BOOLEAN && val == mod)
- val = yes;
-
- /* adjust the default value if this symbol is implied by another */
- if (val < sym->implied.tri)
- val = sym->implied.tri;
-
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE:
- switch (val) {
- case no: return "n";
- case mod: return "m";
- case yes: return "y";
- }
- case S_INT:
- case S_HEX:
- return str;
- case S_STRING:
- return str;
- case S_UNKNOWN:
- break;
- }
- return "";
-}
-
-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:
- sym_calc_value(modules_sym);
- return (modules_sym->curr.tri == no) ? "n" : "m";
- case yes:
- return "y";
- }
- break;
- default:
- ;
- }
- return (const char *)sym->curr.val;
-}
-
-bool sym_is_changeable(struct symbol *sym)
-{
- return sym->visible > sym->rev_dep.tri;
-}
-
-static unsigned strhash(const char *s)
-{
- /* fnv32 hash */
- unsigned hash = 2166136261U;
- for (; *s; s++)
- hash = (hash ^ *s) * 0x01000193;
- return hash;
-}
-
-struct symbol *sym_lookup(const char *name, int flags)
-{
- struct symbol *symbol;
- char *new_name;
- int hash;
-
- 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;
- }
- }
- hash = strhash(name) % SYMBOL_HASHSIZE;
-
- for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
- if (symbol->name &&
- !strcmp(symbol->name, name) &&
- (flags ? symbol->flags & flags
- : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE))))
- return symbol;
- }
- new_name = xstrdup(name);
- } else {
- new_name = NULL;
- hash = 0;
- }
-
- symbol = xmalloc(sizeof(*symbol));
- memset(symbol, 0, sizeof(*symbol));
- symbol->name = new_name;
- symbol->type = S_UNKNOWN;
- symbol->flags = flags;
-
- symbol->next = symbol_hash[hash];
- symbol_hash[hash] = symbol;
-
- return symbol;
-}
-
-struct symbol *sym_find(const char *name)
-{
- struct symbol *symbol = NULL;
- 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;
- }
- }
- hash = strhash(name) % SYMBOL_HASHSIZE;
-
- for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
- if (symbol->name &&
- !strcmp(symbol->name, name) &&
- !(symbol->flags & SYMBOL_CONST))
- break;
- }
-
- return symbol;
-}
-
-struct sym_match {
- struct symbol *sym;
- off_t so, eo;
-};
-
-/* Compare matched symbols as thus:
- * - first, symbols that match exactly
- * - then, alphabetical sort
- */
-static int sym_rel_comp(const void *sym1, const void *sym2)
-{
- const struct sym_match *s1 = sym1;
- const struct sym_match *s2 = sym2;
- int exact1, exact2;
-
- /* Exact match:
- * - if matched length on symbol s1 is the length of that symbol,
- * then this symbol should come first;
- * - if matched length on symbol s2 is the length of that symbol,
- * then this symbol should come first.
- * Note: since the search can be a regexp, both symbols may match
- * exactly; if this is the case, we can't decide which comes first,
- * and we fallback to sorting alphabetically.
- */
- exact1 = (s1->eo - s1->so) == strlen(s1->sym->name);
- exact2 = (s2->eo - s2->so) == strlen(s2->sym->name);
- if (exact1 && !exact2)
- return -1;
- if (!exact1 && exact2)
- return 1;
-
- /* As a fallback, sort symbols alphabetically */
- return strcmp(s1->sym->name, s2->sym->name);
-}
-
-struct symbol **sym_re_search(const char *pattern)
-{
- struct symbol *sym, **sym_arr = NULL;
- struct sym_match *sym_match_arr = NULL;
- int i, cnt, size;
- regex_t re;
- regmatch_t match[1];
-
- cnt = size = 0;
- /* Skip if empty */
- if (strlen(pattern) == 0)
- return NULL;
- if (regcomp(&re, pattern, REG_EXTENDED|REG_ICASE))
- return NULL;
-
- for_all_symbols(i, sym) {
- if (sym->flags & SYMBOL_CONST || !sym->name)
- continue;
- if (regexec(&re, sym->name, 1, match, 0))
- continue;
- if (cnt >= size) {
- void *tmp;
- size += 16;
- tmp = realloc(sym_match_arr, size * sizeof(struct sym_match));
- if (!tmp)
- goto sym_re_search_free;
- sym_match_arr = tmp;
- }
- sym_calc_value(sym);
- /* As regexec returned 0, we know we have a match, so
- * we can use match[0].rm_[se]o without further checks
- */
- sym_match_arr[cnt].so = match[0].rm_so;
- sym_match_arr[cnt].eo = match[0].rm_eo;
- sym_match_arr[cnt++].sym = sym;
- }
- if (sym_match_arr) {
- qsort(sym_match_arr, cnt, sizeof(struct sym_match), sym_rel_comp);
- sym_arr = malloc((cnt+1) * sizeof(struct symbol *));
- if (!sym_arr)
- goto sym_re_search_free;
- for (i = 0; i < cnt; i++)
- sym_arr[i] = sym_match_arr[i].sym;
- sym_arr[cnt] = NULL;
- }
-sym_re_search_free:
- /* sym_match_arr can be NULL if no match, but free(NULL) is OK */
- free(sym_match_arr);
- regfree(&re);
-
- return sym_arr;
-}
-
-/*
- * When we check for recursive dependencies we use a stack to save
- * current state so we can print out relevant info to user.
- * The entries are located on the call stack so no need to free memory.
- * Note insert() remove() must always match to properly clear the stack.
- */
-static struct dep_stack {
- struct dep_stack *prev, *next;
- struct symbol *sym;
- struct property *prop;
- struct expr **expr;
-} *check_top;
-
-static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
-{
- memset(stack, 0, sizeof(*stack));
- if (check_top)
- check_top->next = stack;
- stack->prev = check_top;
- stack->sym = sym;
- check_top = stack;
-}
-
-static void dep_stack_remove(void)
-{
- check_top = check_top->prev;
- if (check_top)
- check_top->next = NULL;
-}
-
-/*
- * Called when we have detected a recursive dependency.
- * check_top point to the top of the stact so we use
- * the ->prev pointer to locate the bottom of the stack.
- */
-static void sym_check_print_recursive(struct symbol *last_sym)
-{
- struct dep_stack *stack;
- struct symbol *sym, *next_sym;
- struct menu *menu = NULL;
- struct property *prop;
- struct dep_stack cv_stack;
-
- if (sym_is_choice_value(last_sym)) {
- dep_stack_insert(&cv_stack, last_sym);
- last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
- }
-
- for (stack = check_top; stack != NULL; stack = stack->prev)
- if (stack->sym == last_sym)
- break;
- if (!stack) {
- fprintf(stderr, "unexpected recursive dependency error\n");
- return;
- }
-
- for (; stack; stack = stack->next) {
- sym = stack->sym;
- next_sym = stack->next ? stack->next->sym : last_sym;
- prop = stack->prop;
- if (prop == NULL)
- prop = stack->sym->prop;
-
- /* for choice values find the menu entry (used below) */
- if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
- for (prop = sym->prop; prop; prop = prop->next) {
- menu = prop->menu;
- if (prop->menu)
- break;
- }
- }
- if (stack->sym == last_sym)
- fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
- prop->file->name, prop->lineno);
-
- if (sym_is_choice(sym)) {
- fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
- menu->file->name, menu->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
- } else if (sym_is_choice_value(sym)) {
- fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
- menu->file->name, menu->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
- } else if (stack->expr == &sym->dir_dep.expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
- prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
- } else if (stack->expr == &sym->rev_dep.expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
- prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
- } else if (stack->expr == &sym->implied.expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s is implied by %s\n",
- prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
- next_sym->name ? next_sym->name : "<choice>");
- } else if (stack->expr) {
- fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
- prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
- prop_get_type_name(prop->type),
- next_sym->name ? next_sym->name : "<choice>");
- } else {
- fprintf(stderr, "%s:%d:\tsymbol %s %s is visible depending on %s\n",
- prop->file->name, prop->lineno,
- sym->name ? sym->name : "<choice>",
- prop_get_type_name(prop->type),
- next_sym->name ? next_sym->name : "<choice>");
- }
- }
-
- fprintf(stderr,
- "For a resolution refer to Documentation/kbuild/kconfig-language.rst\n"
- "subsection \"Kconfig recursive dependency limitations\"\n"
- "\n");
-
- if (check_top == &cv_stack)
- dep_stack_remove();
-}
-
-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_GEQ:
- case E_GTH:
- case E_LEQ:
- case E_LTH:
- 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;
- }
- fprintf(stderr, "Oops! How to check %d?\n", e->type);
- return NULL;
-}
-
-/* return NULL when dependencies are OK */
-static struct symbol *sym_check_sym_deps(struct symbol *sym)
-{
- struct symbol *sym2;
- struct property *prop;
- struct dep_stack stack;
-
- dep_stack_insert(&stack, sym);
-
- stack.expr = &sym->dir_dep.expr;
- sym2 = sym_check_expr_deps(sym->dir_dep.expr);
- if (sym2)
- goto out;
-
- stack.expr = &sym->rev_dep.expr;
- sym2 = sym_check_expr_deps(sym->rev_dep.expr);
- if (sym2)
- goto out;
-
- stack.expr = &sym->implied.expr;
- sym2 = sym_check_expr_deps(sym->implied.expr);
- if (sym2)
- goto out;
-
- stack.expr = NULL;
-
- for (prop = sym->prop; prop; prop = prop->next) {
- if (prop->type == P_CHOICE || prop->type == P_SELECT ||
- prop->type == P_IMPLY)
- continue;
- stack.prop = prop;
- sym2 = sym_check_expr_deps(prop->visible.expr);
- if (sym2)
- break;
- if (prop->type != P_DEFAULT || sym_is_choice(sym))
- continue;
- stack.expr = &prop->expr;
- sym2 = sym_check_expr_deps(prop->expr);
- if (sym2)
- break;
- stack.expr = NULL;
- }
-
-out:
- dep_stack_remove();
-
- return sym2;
-}
-
-static struct symbol *sym_check_choice_deps(struct symbol *choice)
-{
- struct symbol *sym, *sym2;
- struct property *prop;
- struct expr *e;
- struct dep_stack stack;
-
- dep_stack_insert(&stack, choice);
-
- prop = sym_get_choice_prop(choice);
- expr_list_for_each_sym(prop->expr, e, sym)
- sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
-
- choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
- sym2 = sym_check_sym_deps(choice);
- choice->flags &= ~SYMBOL_CHECK;
- if (sym2)
- goto out;
-
- expr_list_for_each_sym(prop->expr, e, sym) {
- sym2 = sym_check_sym_deps(sym);
- if (sym2)
- break;
- }
-out:
- expr_list_for_each_sym(prop->expr, e, sym)
- sym->flags &= ~SYMBOL_CHECK;
-
- if (sym2 && sym_is_choice_value(sym2) &&
- prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
- sym2 = choice;
-
- dep_stack_remove();
-
- return sym2;
-}
-
-struct symbol *sym_check_deps(struct symbol *sym)
-{
- struct symbol *sym2;
- struct property *prop;
-
- if (sym->flags & SYMBOL_CHECK) {
- sym_check_print_recursive(sym);
- return sym;
- }
- if (sym->flags & SYMBOL_CHECKED)
- return NULL;
-
- if (sym_is_choice_value(sym)) {
- struct dep_stack stack;
-
- /* for choice groups start the check with main choice symbol */
- dep_stack_insert(&stack, sym);
- prop = sym_get_choice_prop(sym);
- sym2 = sym_check_deps(prop_get_symbol(prop));
- dep_stack_remove();
- } else if (sym_is_choice(sym)) {
- sym2 = sym_check_choice_deps(sym);
- } else {
- sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
- sym2 = sym_check_sym_deps(sym);
- sym->flags &= ~SYMBOL_CHECK;
- }
-
- return sym2;
-}
-
-struct symbol *prop_get_symbol(struct property *prop)
-{
- if (prop->expr && (prop->expr->type == E_SYMBOL ||
- prop->expr->type == E_LIST))
- 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_IMPLY:
- return "imply";
- case P_RANGE:
- return "range";
- case P_SYMBOL:
- return "symbol";
- case P_UNKNOWN:
- break;
- }
- return "unknown";
-}
diff --git a/tools/kconfig/util.c b/tools/kconfig/util.c
deleted file mode 100644
index b78f114..0000000
--- a/tools/kconfig/util.c
+++ /dev/null
@@ -1,129 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2002-2005 Roman Zippel <zippel@linux-m68k.org>
- * Copyright (C) 2002-2005 Sam Ravnborg <sam@ravnborg.org>
- */
-
-#include <stdarg.h>
-#include <stdlib.h>
-#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 = xmalloc(sizeof(*file));
- memset(file, 0, sizeof(*file));
- file->name = xstrdup(name);
- file->next = file_list;
- file_list = file;
- return file;
-}
-
-/* Allocate initial growable string */
-struct gstr str_new(void)
-{
- struct gstr gs;
- gs.s = xmalloc(sizeof(char) * 64);
- gs.len = 64;
- gs.max_width = 0;
- strcpy(gs.s, "\0");
- 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;
- if (s) {
- l = strlen(gs->s) + strlen(s) + 1;
- if (l > gs->len) {
- gs->s = xrealloc(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);
-}
-
-/* Retrieve value of growable string */
-char *str_get(struct gstr *gs)
-{
- return gs->s;
-}
-
-void *xmalloc(size_t size)
-{
- void *p = malloc(size);
- if (p)
- return p;
- fprintf(stderr, "Out of memory.\n");
- exit(1);
-}
-
-void *xcalloc(size_t nmemb, size_t size)
-{
- void *p = calloc(nmemb, size);
- if (p)
- return p;
- fprintf(stderr, "Out of memory.\n");
- exit(1);
-}
-
-void *xrealloc(void *p, size_t size)
-{
- p = realloc(p, size);
- if (p)
- return p;
- fprintf(stderr, "Out of memory.\n");
- exit(1);
-}
-
-char *xstrdup(const char *s)
-{
- char *p;
-
- p = strdup(s);
- if (p)
- return p;
- fprintf(stderr, "Out of memory.\n");
- exit(1);
-}
-
-char *xstrndup(const char *s, size_t n)
-{
- char *p;
-
- p = strndup(s, n);
- if (p)
- return p;
- fprintf(stderr, "Out of memory.\n");
- exit(1);
-}
diff --git a/tools/make_iso.bzl b/tools/make_iso.bzl
new file mode 100644
index 0000000..5ff20f5
--- /dev/null
+++ b/tools/make_iso.bzl
@@ -0,0 +1,41 @@
+def make_iso(**kwargs):
+ _make_iso(
+ image = "{name}.iso".format(**kwargs),
+ **kwargs
+ )
+
+def _make_iso_impl(ctx):
+ inputs = []
+ outputs = []
+ args = ctx.actions.args()
+
+ args.add("-c", ctx.file.bootloader.path)
+ inputs.append(ctx.file.bootloader)
+ args.add("-k", ctx.file.kernel.path)
+ inputs.append(ctx.file.kernel)
+
+ args.add("-o", ctx.outputs.image.path)
+ outputs.append(ctx.outputs.image)
+
+ ctx.actions.run(
+ inputs = inputs,
+ outputs = outputs,
+ arguments = [args],
+ executable = ctx.executable._generator,
+ progress_message = "Generating ISO image %s" % ctx.label.name,
+ )
+
+_make_iso = rule(
+ attrs = {
+ "bootloader": attr.label(allow_single_file = True),
+ "kernel": attr.label(allow_single_file = True),
+ "image": attr.output(),
+ "_generator": attr.label(
+ default = Label(":make_iso"),
+ executable = True,
+ allow_files = True,
+ cfg = "exec",
+ ),
+ },
+ implementation = _make_iso_impl,
+)
diff --git a/tools/make_iso.py b/tools/make_iso.py
new file mode 100755
index 0000000..7cb4506
--- /dev/null
+++ b/tools/make_iso.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+
+from subprocess import run
+import argparse
+import os
+import shutil
+import hashlib
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+ parser.add_argument('-k', '--kernel', required=True, help='path to kernel binary')
+ parser.add_argument('-c', '--config', required=True, help='path to bootloader config')
+ parser.add_argument('-o', '--output', required=True, help='path for output image')
+
+ parser.add_argument('--prefix-dir', default='isodir', help='prefix dir')
+ parser.add_argument('--boot-dir', default='boot/grub', help='bootloader dir')
+ parser.add_argument('--kernel-dir', default='boot/glitch', help='kernel dir')
+
+ # grub tools
+ parser.add_argument('--grub-file', default='grub-file',
+ help='grub-file executable')
+ parser.add_argument('--grub-script-check', default='grub-script-check',
+ help='grub-script-check executable')
+ parser.add_argument('--grub-mkrescue', default='grub-mkrescue',
+ help='grub-mkrescue executable')
+ # other tools
+ parser.add_argument('--strip', default='i686-elf-strip',
+ help='strip executable')
+
+ args = parser.parse_args()
+ args.boot_dir = f'{args.prefix_dir}/{args.boot_dir}'
+ args.kernel_dir = f'{args.prefix_dir}/{args.kernel_dir}'
+
+ # check inputs
+ run([ args.grub_file, '--is-x86-multiboot2', args.kernel ], check=True)
+ run([ args.grub_script_check, args.config ], check=True)
+
+ # create directory structure and copy files
+ os.makedirs(args.boot_dir, exist_ok=True)
+ os.makedirs(args.kernel_dir, exist_ok=True)
+ shutil.copyfile(args.config, f'{args.boot_dir}/grub.cfg')
+ shutil.copyfile(args.kernel, f'{args.kernel_dir}/glitch.elf')
+
+ # strip and hash binary
+ run([ args.strip, f'{args.kernel_dir}/glitch.elf' ], check=True)
+ with open(f'{args.kernel_dir}/checksums', 'w') as checksums:
+ with open(f'{args.kernel_dir}/glitch.elf', 'rb') as f:
+ digest = hashlib.file_digest(f, 'sha512').hexdigest()
+ path = f'{args.kernel_dir}/{args.kernel}'.removeprefix(args.prefix_dir)
+ print(f'{digest} {path}', file=checksums)
+
+ # create iso image
+ run([ args.grub_mkrescue, '-o', args.output, args.prefix_dir ], check=True)
+
+ # cleanup
+ #shutil.rmtree(args.prefix_dir)
+
diff --git a/tools/qemu.bzl b/tools/qemu.bzl
new file mode 100644
index 0000000..9493306
--- /dev/null
+++ b/tools/qemu.bzl
@@ -0,0 +1,33 @@
+load("//toolchains:i386_qemu.bzl", qemu_i386 = "qemu_wrapper")
+
+def qemu(**kwargs):
+ _qemu(
+ wrapper_content = select({
+ "@platforms//cpu:i386": qemu_i386(),
+ "//conditions:default": "/bin/false",
+ }),
+ **kwargs
+ )
+
+def _qemu_impl(ctx):
+ print(ctx)
+ print(ctx.attr)
+
+ wrapper = ctx.actions.declare_file("%s_wrapper" % ctx.label.name)
+ wrapper_content = ctx.attr.wrapper_content.format(
+ cdrom = ctx.file.cdrom.basename,
+ )
+ ctx.actions.write(wrapper, wrapper_content, is_executable = True)
+
+ runfiles = ctx.runfiles(files = [ctx.file.cdrom])
+
+ return [DefaultInfo(executable = wrapper, runfiles = runfiles)]
+
+_qemu = rule(
+ implementation = _qemu_impl,
+ attrs = {
+ "cdrom": attr.label(allow_single_file = True),
+ "wrapper_content": attr.string(),
+ },
+ executable = True,
+)