Compare commits

..

7 Commits

Author SHA1 Message Date
Bananymous c1978f9133 Shell: Implement redirections
This works well enough. At the moment redirections can appear anywhere
in the command **after** environment variables and possible alias
command. This means commands like `>foo echo hello` are not supported.
I don't think this is big enough problem for now (99% time redirections
are given after arguments) that i would rewrite the environment and
alias parsing.
2025-07-22 16:54:06 +03:00
Bananymous 05affda20c ports: Add python3 port 2025-07-22 14:11:09 +03:00
Bananymous e2eb555ca0 LibC: Add dummy libintl support
This doesn't really do anything but allows some ports to use it :D
2025-07-22 13:26:53 +03:00
Bananymous 418c3c9cfa ports: Remove unneeded libtool files after install 2025-07-22 10:32:52 +03:00
Bananymous bc66e181a5 ports: Update to new config.sub syntax
There is no longer need to manually patch config.sub files!
2025-07-22 10:31:56 +03:00
Bananymous 6971f76bd3 ports: Add support for downloading upstream config.sub
banan-os is now in the upstream config.sub. This means no more
config.sub patches!
2025-07-22 10:13:41 +03:00
Bananymous 1e65f02ff7 Terminal: Handle bell and warn on unimplemented control characters 2025-07-21 14:28:09 +03:00
64 changed files with 681 additions and 190 deletions

View File

@ -4,6 +4,7 @@ NAME='bash'
VERSION='5.2.37'
DOWNLOAD_URL="https://ftp.gnu.org/gnu/bash/bash-$VERSION.tar.gz#9599b22ecd1d5787ad7d3b7bf0c59f312b3396d1e281175dd1f8a4014da621ff"
DEPENDENCIES=('ncurses')
CONFIG_SUB=('support/config.sub')
CONFIGURE_OPTIONS=(
'--disable-nls'
'--without-bash-malloc'

View File

@ -1,12 +0,0 @@
diff -ruN bash-5.2.37/support/config.sub bash-5.2.37-banan_os/support/config.sub
--- bash-5.2.37/support/config.sub 2022-01-11 21:38:29.000000000 +0200
+++ bash-5.2.37-banan_os/support/config.sub 2024-12-07 05:43:54.697086738 +0200
@@ -1754,7 +1754,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* )
+ | fiwix* | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -15,3 +15,12 @@ CONFIGURE_OPTIONS=(
'--disable-nls'
'--disable-werror'
)
post_install() {
# remove libtool files
rm -f $BANAN_SYSROOT/usr/lib/libbfd.la
rm -f $BANAN_SYSROOT/usr/lib/libctf.la
rm -f $BANAN_SYSROOT/usr/lib/libctf-nobfd.la
rm -f $BANAN_SYSROOT/usr/lib/libopcodes.la
rm -f $BANAN_SYSROOT/usr/lib/libsframe.la
}

View File

@ -4,6 +4,7 @@ NAME='bochs'
VERSION='3.0'
DOWNLOAD_URL="https://sourceforge.net/projects/bochs/files/bochs/$VERSION/bochs-$VERSION.tar.gz#cb6f542b51f35a2cc9206b2a980db5602b7cd1b7cf2e4ed4f116acd5507781aa"
DEPENDENCIES=('SDL2')
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
'--with-sdl2'
'--enable-x86-64'

View File

@ -1,12 +0,0 @@
diff -ruN bochs-2.8/config.sub bochs-2.8-banan_os/config.sub
--- bochs-2.8/config.sub 2024-03-10 08:59:37.000000000 +0200
+++ bochs-2.8-banan_os/config.sub 2024-12-07 05:15:32.948901314 +0200
@@ -1368,7 +1368,7 @@
| powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
| skyos* | haiku* | rdos* | toppers* | drops* | es* \
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
- | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi*)
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* | banan_os*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
qnx*)

View File

@ -4,6 +4,7 @@ NAME='curl'
VERSION='8.11.1'
DOWNLOAD_URL="https://curl.se/download/curl-$VERSION.tar.gz#a889ac9dbba3644271bd9d1302b5c22a088893719b72be3487bc3d401e5c4e80"
DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd')
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
'--disable-threaded-resolver'
'--disable-ipv6'

View File

@ -1,12 +0,0 @@
diff -ruN curl-8.8.0/config.sub curl-patched/config.sub
--- curl-8.8.0/config.sub 2023-03-13 00:39:42.000000000 +0200
+++ curl-patched/config.sub 2024-06-17 21:16:00.348556957 +0300
@@ -1754,7 +1754,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* )
+ | fiwix* | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -3,3 +3,4 @@
NAME='expat'
VERSION='2.7.1'
DOWNLOAD_URL="https://github.com/libexpat/libexpat/releases/download/R_2_7_1/expat-$VERSION.tar.gz#0cce2e6e69b327fc607b8ff264f4b66bdf71ead55a87ffd5f3143f535f15cfa2"
CONFIG_SUB=('conftools/config.sub')

View File

@ -1,12 +0,0 @@
diff -ruN expat-2.7.1/conftools/config.sub expat-2.7.1-banan_os/conftools/config.sub
--- expat-2.7.1/conftools/config.sub 2022-07-27 15:26:54.000000000 +0300
+++ expat-2.7.1-banan_os/conftools/config.sub 2025-06-17 11:51:49.876848002 +0300
@@ -1775,7 +1775,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* )
+ | fiwix* | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -17,3 +17,10 @@ CONFIGURE_OPTIONS=(
'--disable-nls'
'--enable-languages=c,c++'
)
post_install() {
# remove libtool files
rm -f $BANAN_SYSROOT/usr/lib/libstdc++.la
rm -f $BANAN_SYSROOT/usr/lib/libstdc++exp.la
rm -f $BANAN_SYSROOT/usr/lib/libsupc++.la
}

View File

@ -3,6 +3,12 @@
NAME='gmp'
VERSION='6.3.0'
DOWNLOAD_URL="https://ftp.gnu.org/gnu/gmp/gmp-$VERSION.tar.xz#a3c2b80201b89e68616f4ad30bc66aee4927c3ce50e33929ca819d5c43538898"
CONFIG_SUB=('configfsf.sub')
# configure does not work with (default) c23
export CFLAGS="--std=c17 $CFLAGS"
post_install() {
# remove libtool file
rm -f $BANAN_SYSROOT/usr/lib/libgmp.la
}

View File

@ -1,12 +0,0 @@
diff -ruN gmp-6.3.0/configfsf.sub gmp-6.3.0-banan_os/configfsf.sub
--- gmp-6.3.0/configfsf.sub 2023-07-29 16:42:16.000000000 +0300
+++ gmp-6.3.0-banan_os/configfsf.sub 2024-08-07 21:37:12.147551767 +0300
@@ -1759,7 +1759,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* | mlibc* )
+ | fiwix* | mlibc* | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -49,10 +49,26 @@ fi
MAKE_BUILD_TARGETS=('all')
MAKE_INSTALL_TARGETS=('install')
CONFIG_SUB=()
clean() {
find . -mindepth 1 -maxdepth 1 -not -name 'patches' -not -name 'build.sh' -exec rm -rf {} +
}
config_sub_update() {
[ ${#CONFIG_SUB[@]} -eq 0 ] && return
config_sub_path="$BANAN_PORT_DIR/config.sub"
if [ $(find $config_sub_path -mtime +1) ]; then
wget -O "$config_sub_path" 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD'
fi
for target in "${CONFIG_SUB[@]}"; do
cp "$config_sub_path" "$target"
done
}
pre_configure() {
:
}
@ -202,6 +218,7 @@ fi
cd "$build_dir"
if (( $needs_compile )); then
config_sub_update
configure
build
sha256sum "$BANAN_SYSROOT/usr/lib/libc.a" > "../.compile_hash"

View File

@ -4,6 +4,7 @@ NAME='libjpeg'
VERSION='9f'
DOWNLOAD_URL="https://www.ijg.org/files/jpegsrc.v9f.tar.gz#04705c110cb2469caa79fb71fba3d7bf834914706e9641a4589485c1f832565b"
TAR_CONTENT="jpeg-$VERSION"
CONFIG_SUB=('config.sub')
post_install() {
# remove libtool files

View File

@ -1,13 +0,0 @@
diff -ruN jpeg-9f/config.sub jpeg-9f-banan_os/config.sub
--- jpeg-9f/config.sub 2024-01-08 19:38:48.000000000 +0200
+++ jpeg-9f-banan_os/config.sub 2025-06-11 10:57:34.463953673 +0300
@@ -1748,7 +1748,8 @@
| skyos* | haiku* | rdos* | toppers* | drops* | es* \
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
- | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr*)
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+ | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -4,6 +4,7 @@ NAME='libpng'
VERSION='1.6.48'
DOWNLOAD_URL="https://download.sourceforge.net/libpng/libpng-$VERSION.tar.gz#68f3d83a79d81dfcb0a439d62b411aa257bb4973d7c67cd1ff8bdf8d011538cd"
DEPENDENCIES=('zlib')
CONFIG_SUB=('config.sub')
post_install() {
# remove libtool files

View File

@ -1,12 +0,0 @@
diff -ruN libpng-1.6.48/config.sub libpng-1.6.48-banan_os/config.sub
--- libpng-1.6.48/config.sub 2025-04-30 16:51:46.000000000 +0300
+++ libpng-1.6.48-banan_os/config.sub 2025-06-10 14:07:16.060041002 +0300
@@ -1768,7 +1768,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* | mlibc* | cos* | mbr* | ironclad* )
+ | fiwix* | mlibc* | cos* | mbr* | ironclad* | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -5,6 +5,7 @@ VERSION='4.7.0'
DOWNLOAD_URL="https://download.osgeo.org/libtiff/tiff-$VERSION.tar.gz#67160e3457365ab96c5b3286a0903aa6e78bdc44c4bc737d2e486bcecb6ba976"
TAR_CONTENT="tiff-$VERSION"
DEPENDENCIES=('zlib' 'zstd' 'libjpeg')
CONFIG_SUB=('config/config.sub')
post_install() {
# remove libtool files

View File

@ -1,11 +0,0 @@
diff -ruN tiff-4.7.0/config/config.sub tiff-4.7.0-banan_os/config/config.sub
--- tiff-4.7.0/config/config.sub 2024-09-11 10:38:00.000000000 +0300
+++ tiff-4.7.0-banan_os/config/config.sub 2025-06-11 12:55:18.797614388 +0300
@@ -1976,6 +1976,7 @@
| atheos* \
| auroraux* \
| aux* \
+ | banan_os* \
| beos* \
| bitrig* \
| bme* \

View File

@ -4,6 +4,7 @@ NAME='libwebp'
VERSION='1.5.0'
DOWNLOAD_URL="https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$VERSION.tar.gz#7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c"
DEPENDENCIES=('libpng' 'libjpeg' 'libtiff')
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
"--with-pngincludedir=$BANAN_SYSROOT/usr/include"
"--with-pnglibdir=$BANAN_SYSROOT/usr/lib"

View File

@ -1,12 +0,0 @@
diff -ruN libwebp-1.5.0/config.sub libwebp-1.5.0-banan_os/config.sub
--- libwebp-1.5.0/config.sub 2024-12-20 03:52:53.000000000 +0200
+++ libwebp-1.5.0-banan_os/config.sub 2025-06-11 12:46:06.199497350 +0300
@@ -1754,7 +1754,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* )
+ | fiwix* | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -5,6 +5,7 @@ VERSION='2.9.2'
DOWNLOAD_URL="https://invisible-island.net/archives/lynx/tarballs/lynx$VERSION.tar.gz#99f8f28f860094c533100d1cedf058c27fb242ce25e991e2d5f30ece4457a3bf"
TAR_CONTENT="lynx$VERSION"
DEPENDENCIES=('ncurses' 'ca-certificates' 'openssl' 'zlib')
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
'--without-system-type'
'--with-sceen=ncurses'

View File

@ -1,12 +0,0 @@
diff -ruN lynx2.9.2/config.sub lynx2.9.2-banan_os/config.sub
--- lynx2.9.2/config.sub 2023-12-27 16:41:27.000000000 +0200
+++ lynx2.9.2-banan_os/config.sub 2024-08-21 14:23:47.519364107 +0300
@@ -1768,7 +1768,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* | mlibc* | cos* | mbr* | ironclad* )
+ | fiwix* | mlibc* | cos* | mbr* | ironclad* | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -3,6 +3,7 @@
NAME='make'
VERSION='4.4.1'
DOWNLOAD_URL="https://ftp.gnu.org/gnu/make/make-$VERSION.tar.gz#dd16fb1d67bfab79a72f5e8390735c49e3e8e70b4945a15ab1f81ddb78658fb3"
CONFIG_SUB=('build-aux/config.sub')
CONFIGURE_OPTIONS=(
'--with-sysroot=/'
'--disable-nls'

View File

@ -1,12 +0,0 @@
diff -ruN make-4.4.1/build-aux/config.sub make-4.4.1-banan_os/build-aux/config.sub
--- make-4.4.1/build-aux/config.sub 2023-02-18 17:38:13.000000000 +0200
+++ make-4.4.1-banan_os/build-aux/config.sub 2024-12-04 23:15:11.865989888 +0200
@@ -1758,7 +1758,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* | mlibc* )
+ | fiwix* | mlibc* | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -4,7 +4,13 @@ NAME='mpc'
VERSION='1.3.1'
DOWNLOAD_URL="https://ftp.gnu.org/gnu/mpc/mpc-$VERSION.tar.gz#ab642492f5cf882b74aa0cb730cd410a81edcdbec895183ce930e706c1c759b8"
DEPENDENCIES=('gmp' 'mpfr')
CONFIG_SUB=('build-aux/config.sub')
CONFIGURE_OPTIONS=(
"--target=$BANAN_TOOLCHAIN_TRIPLE"
"--with-sysroot=$BANAN_SYSROOT"
)
post_install() {
# remove libtool file
rm -f $BANAN_SYSROOT/usr/lib/libmpc.la
}

View File

@ -1,13 +0,0 @@
diff -ruN mpc-1.3.1/build-aux/config.sub mpc-1.3.1-banan_os/build-aux/config.sub
--- mpc-1.3.1/build-aux/config.sub 2022-12-08 14:23:21.000000000 +0200
+++ mpc-1.3.1-banan_os/build-aux/config.sub 2024-08-07 22:52:40.072912471 +0300
@@ -1748,7 +1748,8 @@
| skyos* | haiku* | rdos* | toppers* | drops* | es* \
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
- | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr*)
+ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
+ | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -4,7 +4,13 @@ NAME='mpfr'
VERSION='4.2.2'
DOWNLOAD_URL="https://ftp.gnu.org/gnu/mpfr/mpfr-$VERSION.tar.gz#826cbb24610bd193f36fde172233fb8c009f3f5c2ad99f644d0dea2e16a20e42"
DEPENDENCIES=('gmp')
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
"--target=$BANAN_TOOLCHAIN_TRIPLE"
'--with-sysroot=/'
)
post_install() {
# remove libtool file
rm -f $BANAN_SYSROOT/usr/lib/libmpfr.la
}

View File

@ -1,12 +0,0 @@
diff -ruN mpfr-4.2.1/config.sub mpfr-4.2.1-banan_os/config.sub
--- mpfr-4.2.1/config.sub 2023-08-22 10:47:14.000000000 +0300
+++ mpfr-4.2.1-banan_os/config.sub 2024-08-07 22:48:27.798804026 +0300
@@ -1754,7 +1754,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* )
+ | fiwix* | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -3,6 +3,7 @@
NAME='nasm'
VERSION='2.16.03'
DOWNLOAD_URL="https://www.nasm.us/pub/nasm/releasebuilds/$VERSION/nasm-$VERSION.tar.gz#5bc940dd8a4245686976a8f7e96ba9340a0915f2d5b88356874890e207bdb581"
CONFIG_SUB=('autoconf/helpers/config.sub')
CONFIGURE_OPTIONS=(
'--disable-gdb'
)

View File

@ -1,12 +0,0 @@
diff -ruN nasm-2.16.03/autoconf/helpers/config.sub nasm-2.16.03-banan_os/autoconf/helpers/config.sub
--- nasm-2.16.03/autoconf/helpers/config.sub 2024-04-17 20:04:08.000000000 +0300
+++ nasm-2.16.03-banan_os/autoconf/helpers/config.sub 2024-08-18 18:47:13.768447183 +0300
@@ -1754,7 +1754,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* )
+ | fiwix* | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

View File

@ -3,6 +3,7 @@
NAME='ncurses'
VERSION='6.5'
DOWNLOAD_URL="https://ftp.gnu.org/gnu/ncurses/ncurses-$VERSION.tar.gz#136d91bc269a9a5785e5f9e980bc76ab57428f604ce3e5a5a90cebc767971cc6"
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
"--with-pkg-config='$PKG_CONFIG'"
"--with-pkg-config-libdir=/usr/lib/pkgconfig"

View File

@ -1,12 +0,0 @@
diff -ruN ncurses-6.5/config.sub ncurses-6.5-banan_os/config.sub
--- ncurses-6.5/config.sub 2023-12-27 16:41:27.000000000 +0200
+++ ncurses-6.5-banan_os/config.sub 2025-04-19 05:53:50.863635047 +0300
@@ -1768,7 +1768,7 @@
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* | mlibc* | cos* | mbr* | ironclad* )
+ | fiwix* | mlibc* | cos* | mbr* | ironclad* | banan_os* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)

25
ports/python3/build.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash ../install.sh
NAME='python'
VERSION='3.13.3'
DOWNLOAD_URL="https://www.python.org/ftp/python/$VERSION/Python-$VERSION.tar.xz#40f868bcbdeb8149a3149580bb9bfd407b3321cd48f0be631af955ac92c0e041"
TAR_CONTENT="Python-$VERSION"
DEPENDENCIES=('ncurses' 'zlib' 'openssl')
CONFIG_SUB=('config.sub')
CONFIGURE_OPTIONS=(
"--build=$(uname -m)-pc-linux-gnu"
"--with-build-python=python3.13"
'--without-ensurepip'
'--disable-ipv6'
'--disable-test-modules'
'--enable-shared'
'ac_cv_file__dev_ptmx=no'
'ac_cv_file__dev_ptc=no'
)
pre_configure() {
if ! command -v python3.13 &>/dev/null ; then
echo "You need to have python3.13 installed on your host machine" >&2
exit 1
fi
}

View File

@ -0,0 +1,60 @@
diff -ruN Python-3.13.3/configure Python-3.13.3-banan_os/configure
--- Python-3.13.3/configure 2025-04-08 16:54:08.000000000 +0300
+++ Python-3.13.3-banan_os/configure 2025-04-19 04:25:20.860260051 +0300
@@ -4052,6 +4052,9 @@
*-*-linux*)
ac_sys_system=Linux
;;
+ *-*-banan_os*)
+ ac_sys_system=banan_os
+ ;;
*-*-cygwin*)
ac_sys_system=Cygwin
;;
@@ -4500,6 +4503,9 @@
_host_ident=$host_cpu
esac
;;
+ *-*-banan_os*)
+ _host_ident=$host_cpu
+ ;;
*-*-cygwin*)
_host_ident=
;;
@@ -7603,6 +7609,11 @@
PY3LIBRARY=libpython3.so
fi
;;
+ banan_os*)
+ LDLIBRARY='libpython$(LDVERSION).so'
+ BLDLIBRARY='-L. -lpython$(LDVERSION)'
+ RUNSHARED=LD_LIBRARY_PATH=`pwd`${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
+ ;;
hp*|HP*)
case `uname -m` in
ia64)
@@ -12983,7 +12994,7 @@
Emscripten*|WASI*)
LDSHARED='$(CC) -shared'
LDCXXSHARED='$(CXX) -shared';;
- Linux*|GNU*|QNX*|VxWorks*|Haiku*)
+ Linux*|GNU*|QNX*|VxWorks*|Haiku*|banan_os*)
LDSHARED='$(CC) -shared'
LDCXXSHARED='$(CXX) -shared';;
FreeBSD*)
@@ -13069,6 +13080,7 @@
else CCSHARED="+z";
fi;;
Linux*|GNU*) CCSHARED="-fPIC";;
+ banan_os*) CCSHARED="-fPIC";;
Emscripten*|WASI*)
if test "x$enable_wasm_dynamic_linking" = xyes
then :
@@ -23609,6 +23621,7 @@
case $ac_sys_system in
Darwin) ;;
+banan_os) ;;
*) LIBM=-lm
esac
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for --with-libm=STRING" >&5

View File

@ -0,0 +1,19 @@
diff -ruN Python-3.13.3/Objects/mimalloc/prim/unix/prim.c Python-3.13.3-banan_os/Objects/mimalloc/prim/unix/prim.c
--- Python-3.13.3/Objects/mimalloc/prim/unix/prim.c 2025-04-08 16:54:08.000000000 +0300
+++ Python-3.13.3-banan_os/Objects/mimalloc/prim/unix/prim.c 2025-04-19 02:14:12.417811656 +0300
@@ -608,10 +608,13 @@
getrusage(RUSAGE_SELF, &rusage);
pinfo->utime = timeval_secs(&rusage.ru_utime);
pinfo->stime = timeval_secs(&rusage.ru_stime);
-#if !defined(__HAIKU__)
+#if !defined(__HAIKU__) && !defined(__banan_os__)
pinfo->page_faults = rusage.ru_majflt;
#endif
-#if defined(__HAIKU__)
+#if defined(__banan_os__)
+ pinfo->page_faults = 0;
+ pinfo->peak_rss = 0;
+#elif defined(__HAIKU__)
// Haiku does not have (yet?) a way to
// get these stats per process
thread_info tid;

View File

@ -0,0 +1,13 @@
diff -ruN Python-3.13.3/Include/internal/pycore_time.h Python-3.13.3-banan_os/Include/internal/pycore_time.h
--- Python-3.13.3/Include/internal/pycore_time.h 2025-04-08 16:54:08.000000000 +0300
+++ Python-3.13.3-banan_os/Include/internal/pycore_time.h 2025-04-19 02:27:02.327447295 +0300
@@ -58,9 +58,7 @@
#endif
-#ifdef __clang__
struct timeval;
-#endif
#define _SIZEOF_PYTIME_T 8

View File

@ -0,0 +1,19 @@
diff -ruN Python-3.13.3/Modules/resource.c Python-3.13.3-banan_os/Modules/resource.c
--- Python-3.13.3/Modules/resource.c 2025-04-08 16:54:08.000000000 +0300
+++ Python-3.13.3-banan_os/Modules/resource.c 2025-04-19 02:36:06.945810525 +0300
@@ -126,6 +126,7 @@
PyFloat_FromDouble(doubletime(ru.ru_utime)));
PyStructSequence_SetItem(result, 1,
PyFloat_FromDouble(doubletime(ru.ru_stime)));
+#if !defined(__banan_os__)
PyStructSequence_SetItem(result, 2, PyLong_FromLong(ru.ru_maxrss));
PyStructSequence_SetItem(result, 3, PyLong_FromLong(ru.ru_ixrss));
PyStructSequence_SetItem(result, 4, PyLong_FromLong(ru.ru_idrss));
@@ -140,6 +141,7 @@
PyStructSequence_SetItem(result, 13, PyLong_FromLong(ru.ru_nsignals));
PyStructSequence_SetItem(result, 14, PyLong_FromLong(ru.ru_nvcsw));
PyStructSequence_SetItem(result, 15, PyLong_FromLong(ru.ru_nivcsw));
+#endif
if (PyErr_Occurred()) {
Py_DECREF(result);

View File

@ -0,0 +1,17 @@
diff -ruN Python-3.13.3/Modules/grpmodule.c Python-3.13.3-banan_os/Modules/grpmodule.c
--- Python-3.13.3/Modules/grpmodule.c 2025-04-08 16:54:08.000000000 +0300
+++ Python-3.13.3-banan_os/Modules/grpmodule.c 2025-04-19 02:40:57.658713753 +0300
@@ -91,9 +91,12 @@
#define SET(i,val) PyStructSequence_SetItem(v, i, val)
SET(setIndex++, PyUnicode_DecodeFSDefault(p->gr_name));
+#if !defined(__banan_os__)
if (p->gr_passwd)
SET(setIndex++, PyUnicode_DecodeFSDefault(p->gr_passwd));
- else {
+ else
+#endif
+ {
SET(setIndex++, Py_None);
Py_INCREF(Py_None);
}

View File

@ -0,0 +1,14 @@
diff -ruN Python-3.13.3/Modules/selectmodule.c Python-3.13.3-banan_os/Modules/selectmodule.c
--- Python-3.13.3/Modules/selectmodule.c 2025-04-08 16:54:08.000000000 +0300
+++ Python-3.13.3-banan_os/Modules/selectmodule.c 2025-04-19 02:55:44.944860340 +0300
@@ -54,6 +54,10 @@
#include <sys/poll.h>
#endif
+#if defined(__banan_os__)
+#include <sys/select.h>
+#endif
+
#ifdef __sgi
/* This is missing from unistd.h */
extern void bzero(void *, int);

View File

@ -0,0 +1,22 @@
diff -ruN Python-3.13.3/Modules/socketmodule.c Python-3.13.3-banan_os/Modules/socketmodule.c
--- Python-3.13.3/Modules/socketmodule.c 2025-04-08 16:54:08.000000000 +0300
+++ Python-3.13.3-banan_os/Modules/socketmodule.c 2025-04-19 03:09:49.117436782 +0300
@@ -1676,10 +1676,17 @@
default:
/* If we don't know the address family, don't raise an
exception -- return it as an (int, bytes) tuple. */
+#if defined(__banan_os__)
return Py_BuildValue("iy#",
addr->sa_family,
addr->sa_data,
- sizeof(addr->sa_data));
+ sizeof(((struct sockaddr_storage){}).ss_storage));
+#else
+ return Py_BuildValue("iy#",
+ addr->sa_family,
+ addr->sa_data,
+ sizeof(addr->sa_data));
+#endif
}
}

View File

@ -15,6 +15,7 @@ set(LIBC_SOURCES
inttypes.cpp
langinfo.cpp
libgen.cpp
libintl.cpp
locale.cpp
malloc.cpp
math.cpp

View File

@ -0,0 +1,207 @@
#include <langinfo.h>
#include <libintl.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
struct text_domain_t
{
char* domain_name;
char* codeset;
char* dir_name;
};
static text_domain_t* s_text_domains = nullptr;
static size_t s_text_domain_count = 0;
static char* s_current_domain = nullptr;
static text_domain_t* find_text_domain(const char* domainname)
{
for (size_t i = 0; i < s_text_domain_count; i++)
{
if (strcmp(s_text_domains[i].domain_name, domainname) != 0)
continue;
return &s_text_domains[i];
}
return nullptr;
}
static text_domain_t* bind_new_textdomain(const char* domainname, const char* codeset, const char* dirname)
{
auto* new_text_domains = static_cast<text_domain_t*>(realloc(s_text_domains, (s_text_domain_count + 1) * sizeof(text_domain_t)));
if (new_text_domains == nullptr)
return nullptr;
s_text_domains = new_text_domains;
auto& new_text_domain = new_text_domains[s_text_domain_count];
new_text_domain.domain_name = strdup(domainname);
new_text_domain.dir_name = strdup(dirname);
new_text_domain.codeset = strdup(codeset);
if (!new_text_domain.domain_name || !new_text_domain.codeset || !new_text_domain.dir_name)
{
if (new_text_domain.domain_name)
free(new_text_domain.domain_name);
if (new_text_domain.codeset)
free(new_text_domain.codeset);
if (new_text_domain.dir_name)
free(new_text_domain.dir_name);
return nullptr;
}
s_text_domain_count++;
return &new_text_domain;
}
char* bindtextdomain(const char* domainname, const char* dirname)
{
if (domainname == nullptr || *domainname == '\0')
return nullptr;
auto* text_domain = find_text_domain(domainname);
if (dirname == nullptr)
{
if (text_domain != nullptr)
return text_domain->dir_name;
return const_cast<char*>("");
}
if (text_domain)
{
char* dirname_copy = strdup(dirname);
if (dirname_copy == nullptr)
return nullptr;
if (text_domain->dir_name)
free(text_domain->dir_name);
text_domain->dir_name = dirname_copy;
return text_domain->dir_name;
}
auto* new_current_domain = bind_new_textdomain(domainname, nl_langinfo(CODESET), dirname);
if (new_current_domain == nullptr)
return nullptr;
return new_current_domain->domain_name;
}
char* bind_textdomain_codeset(const char* domainname, const char* codeset)
{
if (domainname == nullptr || *domainname == '\0')
return nullptr;
auto* text_domain = find_text_domain(domainname);
if (codeset == nullptr || *codeset == '\0')
{
if (text_domain == nullptr)
return nl_langinfo(CODESET);
return text_domain->codeset;
}
if (text_domain)
{
char* codeset_copy = strdup(codeset);
if (codeset_copy == nullptr)
return nullptr;
free(text_domain->codeset);
text_domain->codeset = codeset_copy;
return codeset_copy;
}
auto* new_text_domain = bind_new_textdomain(domainname, codeset, "");
if (new_text_domain == nullptr)
return nullptr;
return new_text_domain->codeset;
}
char* textdomain(const char* domainname)
{
if (domainname == nullptr || *domainname == '\0')
{
if (s_current_domain == nullptr)
s_current_domain = strdup("messages");
return s_current_domain;
}
char* new_current_domain = strdup(domainname);
if (new_current_domain == nullptr)
return nullptr;
if (s_current_domain != nullptr)
free(s_current_domain);
s_current_domain = new_current_domain;
return s_current_domain;
}
char* dgettext(const char* domainname, const char* msgid)
{
return dgettext_l(domainname, msgid, __getlocale(LC_MESSAGES));
}
char* dgettext_l(const char* domainname, const char* msgid, locale_t locale)
{
return dngettext_l(domainname, msgid, nullptr, 1, locale);
}
char* dcgettext(const char* domainname, const char* msgid, int category)
{
return dcgettext_l(domainname, msgid, category, __getlocale(LC_MESSAGES));
}
char* dcgettext_l(const char* domainname, const char* msgid, int category, locale_t locale)
{
return dcngettext_l(domainname, msgid, nullptr, 1, category, locale);
}
char* dngettext(const char* domainname, const char* msgid, const char* msgid_plural, unsigned long int n)
{
return dngettext_l(domainname, msgid, msgid_plural, n, __getlocale(LC_MESSAGES));
}
char* dngettext_l(const char* domainname, const char* msgid, const char* msgid_plural, unsigned long int n, locale_t locale)
{
return dcngettext_l(domainname, msgid, msgid_plural, n, 0, locale);
}
char* dcngettext(const char* domainname, const char* msgid, const char* msgid_plural, unsigned long int n, int category)
{
return dcngettext_l(domainname, msgid, msgid_plural, n, category, __getlocale(LC_MESSAGES));
}
char* dcngettext_l(const char* domainname, const char* msgid, const char* msgid_plural, unsigned long int n, int category, locale_t locale)
{
// TODO: do actual translations :D
// FIXME: handle domain codeset
(void)locale;
(void)domainname;
(void)category;
return const_cast<char*>((n == 1) ? msgid : msgid_plural);
}
char* gettext(const char* msgid)
{
return gettext_l(msgid, __getlocale(LC_MESSAGES));
}
char* gettext_l(const char* msgid, locale_t locale)
{
return dgettext_l(s_current_domain, msgid, locale);
}
char* ngettext(const char* msgid, const char* msgid_plural, unsigned long int n)
{
return ngettext_l(msgid, msgid_plural, n, __getlocale(LC_MESSAGES));
}
char* ngettext_l(const char* msgid, const char* msgid_plural, unsigned long int n, locale_t locale)
{
return dngettext_l(s_current_domain, msgid, msgid_plural, n, locale);
}

View File

@ -2,7 +2,7 @@
#include <BAN/String.h>
#define COMMAND_GET_MACRO(_0, _1, _2, NAME, ...) NAME
#define COMMAND_GET_MACRO(_0, _1, _2, _3, NAME, ...) NAME
#define COMMAND_MOVE_0(class) \
class(class&& o) { } \
@ -13,7 +13,10 @@
#define COMMAND_MOVE_2(class, var1, var2) \
class(class&& o) { var1 = BAN::move(o.var1); var2 = BAN::move(o.var2); } \
class& operator=(class&& o) { var1 = BAN::move(o.var1); var2 = BAN::move(o.var2); return *this; }
#define COMMAND_MOVE(class, ...) COMMAND_GET_MACRO(_0 __VA_OPT__(,) __VA_ARGS__, COMMAND_MOVE_2, COMMAND_MOVE_1, COMMAND_MOVE_0)(class, __VA_ARGS__)
#define COMMAND_MOVE_3(class, var1, var2, var3) \
class(class&& o) { var1 = BAN::move(o.var1); var2 = BAN::move(o.var2); var3 = BAN::move(o.var3); } \
class& operator=(class&& o) { var1 = BAN::move(o.var1); var2 = BAN::move(o.var2); var3 = BAN::move(o.var3); return *this; }
#define COMMAND_MOVE(class, ...) COMMAND_GET_MACRO(_0 __VA_OPT__(,) __VA_ARGS__, COMMAND_MOVE_3, COMMAND_MOVE_2, COMMAND_MOVE_1, COMMAND_MOVE_0)(class, __VA_ARGS__)
#define COMMAND_RULE5(class, ...) \
class() = default; \
@ -67,9 +70,19 @@ struct SingleCommand
CommandArgument value;
};
COMMAND_RULE5(SingleCommand, environment, arguments);
struct Redirection
{
CommandArgument destination;
int source_fd;
bool append;
bool duplicate;
bool input;
};
COMMAND_RULE5(SingleCommand, environment, arguments, redirections);
BAN::Vector<EnvironmentVariable> environment;
BAN::Vector<CommandArgument> arguments;
BAN::Vector<Redirection> redirections;
};
struct PipedCommand

View File

@ -99,6 +99,47 @@ BAN::ErrorOr<Execute::ExecuteResult> Execute::execute_command_no_wait(const Inte
CHECK_FD_OR_PERROR_AND_EXIT(command.fd_in, STDIN_FILENO);
CHECK_FD_OR_PERROR_AND_EXIT(command.fd_out, STDOUT_FILENO);
for (const auto& redirection : command.redirections)
{
int dst_fd = -1;
if (redirection.duplicate)
{
if (!redirection.path.empty())
{
dst_fd = 0;
for (char ch : redirection.path)
{
if (!isdigit(ch))
{
dst_fd = -1;
break;
}
dst_fd = (dst_fd * 10) + (ch - '0');
}
}
}
else
{
const int flags = O_CREAT
| (redirection.input ? O_RDONLY : O_WRONLY)
| (redirection.append ? O_APPEND : O_TRUNC);
dst_fd = open(redirection.path.data(), flags, 0644);
if (dst_fd == -1)
{
perror("open");
exit(errno);
}
}
CHECK_FD_OR_PERROR_AND_EXIT(dst_fd, redirection.source_fd);
if (!redirection.duplicate)
close(dst_fd);
}
execv(command.command.get<BAN::String>().data(), const_cast<char* const*>(exec_args.data()));
perror("execv");
exit(errno);
@ -125,6 +166,7 @@ BAN::ErrorOr<int> Execute::execute_command_sync(BAN::Span<const BAN::String> arg
.command = {},
.arguments = arguments,
.environments = {},
.redirections = {},
.fd_in = fd_in,
.fd_out = fd_out,
.background = false,
@ -194,6 +236,22 @@ BAN::ErrorOr<void> Execute::execute_command(const PipedCommand& piped_command)
return result;
};
const auto evaluate_redirections =
[this](BAN::Span<const SingleCommand::Redirection> redirections) -> BAN::ErrorOr<BAN::Vector<InternalCommand::Redirection>>
{
BAN::Vector<InternalCommand::Redirection> result;
TRY(result.reserve(redirections.size()));
for (const auto& redirection : redirections)
TRY(result.push_back({
.path = TRY(redirection.destination.evaluate(*this)),
.source_fd = redirection.source_fd,
.append = redirection.append,
.duplicate = redirection.duplicate,
.input = redirection.input,
}));
return result;
};
const int stdin_flags = fcntl(STDIN_FILENO, F_GETFL);
if (stdin_flags == -1)
perror("fcntl");
@ -221,11 +279,13 @@ BAN::ErrorOr<void> Execute::execute_command(const PipedCommand& piped_command)
const auto arguments = TRY_OR_PERROR_AND_BREAK(evaluate_arguments(piped_command.commands[i].arguments.span()));
const auto environments = TRY_OR_PERROR_AND_BREAK(evaluate_environment(piped_command.commands[i].environment.span()));
const auto redirections = TRY_OR_PERROR_AND_BREAK(evaluate_redirections(piped_command.commands[i].redirections.span()));
InternalCommand command {
.command = {},
.arguments = arguments.span(),
.environments = environments.span(),
.redirections = redirections.span(),
.fd_in = fd_in,
.fd_out = fd_out,
.background = piped_command.background,

View File

@ -12,6 +12,7 @@ class Execute
public:
Execute() = default;
// FIXME: remove this, this is only used by *builtin* time which should not be a builtin
BAN::ErrorOr<int> execute_command_sync(BAN::Span<const BAN::String> arguments, int fd_in, int fd_out);
BAN::ErrorOr<void> execute_command(const SingleCommand&, int fd_in, int fd_out, bool background, pid_t pgrp = 0);
BAN::ErrorOr<void> execute_command(const PipedCommand&);
@ -39,9 +40,19 @@ private:
BAN::String value;
};
struct Redirection
{
BAN::String path;
int source_fd;
bool append;
bool duplicate;
bool input;
};
Command command;
BAN::Span<const BAN::String> arguments;
BAN::Span<const Environment> environments;
BAN::Span<Redirection> redirections;
int fd_in;
int fd_out;
bool background;

View File

@ -21,6 +21,8 @@ BAN::ErrorOr<BAN::Vector<Token>> tokenize_string(BAN::StringView string)
case ')': return Token::Type::CloseParen;
case '$': return Token::Type::Dollar;
case '"': return Token::Type::DoubleQuote;
case '>': return Token::Type::GreaterThan;
case '<': return Token::Type::LessThan;
case '{': return Token::Type::OpenCurly;
case '(': return Token::Type::OpenParen;
case '|': return Token::Type::Pipe;

View File

@ -27,6 +27,12 @@ void Token::debug_dump() const
case Type::DoubleQuote:
dprintln("Token <DoubleQuote>");
break;
case Type::GreaterThan:
dprintln("Token <GreaterThan>");
break;
case Type::LessThan:
dprintln("Token <LessThan>");
break;
case Type::OpenCurly:
dprintln("Token <OpenCurly>");
break;

View File

@ -19,6 +19,8 @@ public:
CloseParen,
Dollar,
DoubleQuote,
GreaterThan,
LessThan,
OpenCurly,
OpenParen,
Pipe,

View File

@ -7,6 +7,7 @@
#include <BAN/ScopeGuard.h>
#include <stdio.h>
#include <unistd.h>
static constexpr bool can_parse_argument_from_token_type(Token::Type token_type)
{
@ -18,6 +19,8 @@ static constexpr bool can_parse_argument_from_token_type(Token::Type token_type)
case Token::Type::Ampersand:
case Token::Type::CloseCurly:
case Token::Type::CloseParen:
case Token::Type::GreaterThan:
case Token::Type::LessThan:
case Token::Type::OpenCurly:
case Token::Type::OpenParen:
case Token::Type::Pipe:
@ -43,6 +46,8 @@ static constexpr char token_type_to_single_character(Token::Type type)
case Token::Type::CloseParen: return ')';
case Token::Type::Dollar: return '$';
case Token::Type::DoubleQuote: return '"';
case Token::Type::GreaterThan: return '>';
case Token::Type::LessThan: return '<';
case Token::Type::OpenCurly: return '{';
case Token::Type::OpenParen: return '(';
case Token::Type::Pipe: return '|';
@ -74,6 +79,10 @@ static constexpr BAN::Error unexpected_token_error(Token::Type type)
return BAN::Error::from_literal("unexpected token $");
case Token::Type::DoubleQuote:
return BAN::Error::from_literal("unexpected token \"");
case Token::Type::GreaterThan:
return BAN::Error::from_literal("unexpected token >");
case Token::Type::LessThan:
return BAN::Error::from_literal("unexpected token <");
case Token::Type::OpenCurly:
return BAN::Error::from_literal("unexpected token {");
case Token::Type::Pipe:
@ -185,6 +194,8 @@ BAN::ErrorOr<CommandArgument::ArgumentPart> TokenParser::parse_backslash(bool is
case Token::Type::CloseParen:
case Token::Type::Dollar:
case Token::Type::DoubleQuote:
case Token::Type::GreaterThan:
case Token::Type::LessThan:
case Token::Type::OpenCurly:
case Token::Type::OpenParen:
case Token::Type::Pipe:
@ -277,6 +288,8 @@ BAN::ErrorOr<CommandArgument::ArgumentPart> TokenParser::parse_dollar()
case Token::Type::CloseCurly:
case Token::Type::CloseParen:
case Token::Type::DoubleQuote:
case Token::Type::GreaterThan:
case Token::Type::LessThan:
case Token::Type::Pipe:
case Token::Type::Semicolon:
case Token::Type::SingleQuote:
@ -363,6 +376,8 @@ BAN::ErrorOr<CommandArgument::ArgumentPart> TokenParser::parse_single_quote()
case Token::Type::CloseParen:
case Token::Type::Dollar:
case Token::Type::DoubleQuote:
case Token::Type::GreaterThan:
case Token::Type::LessThan:
case Token::Type::OpenCurly:
case Token::Type::OpenParen:
case Token::Type::Pipe:
@ -403,6 +418,8 @@ BAN::ErrorOr<CommandArgument> TokenParser::parse_argument()
case Token::Type::Ampersand:
case Token::Type::CloseCurly:
case Token::Type::CloseParen:
case Token::Type::GreaterThan:
case Token::Type::LessThan:
case Token::Type::OpenCurly:
case Token::Type::OpenParen:
case Token::Type::Pipe:
@ -466,6 +483,56 @@ BAN::ErrorOr<CommandArgument> TokenParser::parse_argument()
return result;
}
BAN::ErrorOr<SingleCommand::Redirection> TokenParser::parse_redirection()
{
int source_fd = -1;
if (peek_token().type() == Token::Type::String)
{
const auto string = read_token().string();
source_fd = 0;
for (char ch : string)
source_fd = (source_fd * 10) + (ch - '0');
}
const auto token_type = peek_token().type();
consume_token();
switch (token_type)
{
case Token::Type::GreaterThan:
if (source_fd == -1)
source_fd = STDOUT_FILENO;
break;
case Token::Type::LessThan:
if (source_fd == -1)
source_fd = STDIN_FILENO;
break;
default:
ASSERT_NOT_REACHED();
}
const bool append = (peek_token().type() == token_type);
if (append)
consume_token();
const bool duplicate = (peek_token().type() == Token::Type::Ampersand);
if (duplicate)
consume_token();
while (peek_token().type() == Token::Type::Whitespace)
consume_token();
return SingleCommand::Redirection {
.destination = TRY(parse_argument()),
.source_fd = source_fd,
.append = append,
.duplicate = duplicate,
.input = (token_type == Token::Type::LessThan),
};
}
BAN::ErrorOr<SingleCommand> TokenParser::parse_single_command()
{
SingleCommand result;
@ -527,6 +594,8 @@ BAN::ErrorOr<SingleCommand> TokenParser::parse_single_command()
case Token::Type::CloseCurly:
case Token::Type::Dollar:
case Token::Type::DoubleQuote:
case Token::Type::GreaterThan:
case Token::Type::LessThan:
case Token::Type::OpenCurly:
case Token::Type::OpenParen:
case Token::Type::SingleQuote:
@ -562,18 +631,56 @@ BAN::ErrorOr<SingleCommand> TokenParser::parse_single_command()
consume_token();
}
const auto can_parse_redirection =
[this]() -> bool
{
const auto& token = peek_token();
if (token.type() == Token::Type::GreaterThan)
return true;
if (token.type() == Token::Type::LessThan)
return true;
if (token.type() != Token::Type::String)
return false;
if (token.string().empty())
return false;
bool is_number = true;
for (size_t i = 0; i < token.string().size() && is_number; i++)
is_number = isdigit(token.string()[i]);
if (!is_number)
return false;
auto temp = read_token();
const bool is_redir =
(peek_token().type() == Token::Type::GreaterThan) ||
(peek_token().type() == Token::Type::LessThan);
MUST(unget_token(BAN::move(temp)));
if (!is_redir)
return false;
return true;
};
while (peek_token().type() != Token::Type::EOF_)
{
while (peek_token().type() == Token::Type::Whitespace)
consume_token();
auto argument = TRY(parse_argument());
TRY(result.arguments.push_back(BAN::move(argument)));
while (peek_token().type() == Token::Type::Whitespace)
consume_token();
if (!can_parse_argument_from_token_type(peek_token().type()))
if (can_parse_redirection())
{
auto redirection = TRY(parse_redirection());
TRY(result.redirections.push_back(BAN::move(redirection)));
}
else if (can_parse_argument_from_token_type(peek_token().type()))
{
auto argument = TRY(parse_argument());
TRY(result.arguments.push_back(BAN::move(argument)));
}
else
{
break;
}
}
return result;

View File

@ -44,6 +44,8 @@ private:
BAN::ErrorOr<CommandArgument::ArgumentPart> parse_single_quote();
BAN::ErrorOr<CommandArgument> parse_argument();
BAN::ErrorOr<SingleCommand::Redirection> parse_redirection();
BAN::ErrorOr<SingleCommand> parse_single_command();
BAN::ErrorOr<PipedCommand> parse_piped_command();
BAN::ErrorOr<CommandTree> parse_command_tree();

View File

@ -676,6 +676,9 @@ Rectangle Terminal::putcodepoint(uint32_t codepoint)
auto& texture = m_window->texture();
switch (codepoint)
{
case '\a':
// TODO: bell
break;
case '\e':
m_state = State::ESC;
break;
@ -697,6 +700,12 @@ Rectangle Terminal::putcodepoint(uint32_t codepoint)
break;
default:
{
if (iscntrl(codepoint))
{
dwarnln("unhandled control character 0x{2H}", codepoint);
break;
}
if (m_cursor.x >= cols())
{
m_cursor.x = 0;