| git.druid.rocks | index | druid520 | ports | ports/ | networking/ | toybox/ | patches/ | 0003-make-mksh-sbase-compat.patch |
ports/networking/toybox/patches/0003-make-mksh-sbase-compat.patch
# a bundle of real, distinct portability gaps found building this
# under mksh + this tree's own sbase/coreutils instead of bash + gnu
# coreutils, each confirmed for real in isolation before being folded
# in here:
#
# - a "cmp -s <(...) <(...)" process substitution: mksh's own parser
# doesn't implement <(...) at all ("syntax error: unexpected '('").
# rewritten as a plain string comparison -- functionally identical
# for comparing two filtered command outputs.
# - two more "sort -s" occurrences sbase's own sort doesn't
# recognize (see 0002's own comment for why dropping -s is safe
# here).
# - "$SED -En $KCONFIG_CONFIG -e ... -e ..." (the config.h generation
# step): this tree's own sed (sbase, not gnu sed) doesn't look
# ahead for a later -e when deciding whether the first bare
# argument is a script or a file -- given before any -e, it's
# misread as a malformed script instead of the input file ("bad
# sed function"). reordered so every -e comes before the filename;
# gnu sed tolerates either order, sbase's own parser needs this
# one.
# - "od -Anone -vtx1": sbase's own od doesn't implement gnu od's
# long-form "-A" value aliases ("none" for "n", etc.), only the
# single-character posix ones -- switched to "-An".
# - the biggest one: "^USE_($TOYFILES)[(]...TOY[(]" built a single
# extended-regex alternation with one branch per enabled config
# name -- a real, working defconfig enables on the order of 200
# names, and musl's own regcomp() has a real, smaller internal
# branch-count limit than glibc's ("invalid regex: Missing ')'",
# reproduced in isolation starting around 100-150 branches).
# rewritten to use "grep -f" with the same patterns as separate
# lines instead -- finds the identical files without ever building
# one oversized alternation, and doesn't need libc changed at all.
# - one "\t" inside a sed REPLACEMENT string (a separate code path
# from the pattern-side gap above, confirmed for real still broken
# even after that fix): sbase's own sed drops the backslash and
# keeps the literal letter "t" instead of emitting a real tab
# byte, mangling generated C source ("tstruct" instead of a
# tab-indented "struct"). replaced with an actual literal tab
# character in the script text itself, sidestepping the escape
# entirely.
--- a/scripts/make.sh 2026-09-11 22:10:08.890795892 +0000
+++ b/scripts/make.sh 2026-09-11 22:10:21.950679108 +0000
@@ -89,7 +89,7 @@
# Force full rebuild if our compiler/linker options changed
OBJDIR="$UNSTRIPPED/obj"
-cmp -s <(compflags | grep '#d') <(grep '#d' "$GENDIR"/build.sh 2>/dev/null) ||
+[ "$(compflags | grep '#d')" = "$(grep '#d' "$GENDIR"/build.sh 2>/dev/null)" ] ||
rm -rf "$UNSTRIPPED"
mkdir -p "$OBJDIR" "$(dirname $OUTNAME)" || exit 1
@@ -97,8 +97,20 @@
# (First command names, then filenames with relevant {NEW,OLD}TOY() macro.)
[ -n "$V" ] && echo -e "\nWhich C files to build..."
-TOYFILES="$($SED -n 's/^CONFIG_\([^=]*\)=.*/\1/p' "$KCONFIG_CONFIG" | xargs | tr ' ' '|')"
-TOYFILES="main.c $(egrep -l "^USE_($TOYFILES)[(]...TOY[(]" toys/*/*.c | xargs)"
+# one pattern per line via -f, not a single "^USE_(a|b|c|...)[(]...TOY[(]"
+# alternation: a real, working defconfig enables on the order of 200
+# names, and a single extended-regex alternation with that many
+# branches overflows this tree's own regex engine's internal branch
+# limit ("invalid regex: Missing ')'", confirmed for real, reproduced
+# in isolation starting around 100-150 branches) -- musl's own
+# regcomp() genuinely has a smaller internal limit here than glibc's,
+# and this tree deliberately isn't patching libc to raise it. grep -f
+# with the same patterns as separate lines finds the identical files
+# without ever building one oversized alternation at all.
+TOYPATFILE="$(mktemp)"
+$SED -n 's/^CONFIG_\([^=]*\)=.*/^USE_\1[(]...TOY[(]/p' "$KCONFIG_CONFIG" > "$TOYPATFILE"
+TOYFILES="main.c $(egrep -l -f "$TOYPATFILE" toys/*/*.c | xargs)"
+rm -f "$TOYPATFILE"
if [ "${TOYFILES/pending//}" != "$TOYFILES" ]
then
@@ -119,14 +131,20 @@
echo "USE_TOYBOX(NEWTOY(toybox, 0, TOYFLAG_STAYROOT|TOYFLAG_NOHELP))" &&
# Sort rest by name for binary search (copy name to front, sort, remove copy)
$SED -n 's/^\(USE_[^(]*(.*TOY(\)\([^,]*\)\(,.*\)/\2 \1\2\3/p' toys/*/*.c \
- | sort -s -k 1,1 | $SED 's/[^ ]* //'
+ | sort -k 1,1 | $SED 's/[^ ]* //'
} > "$GENDIR"/newtoys.h || exit 1
# Rebuild config.h from .config
-$SED -En $KCONFIG_CONFIG > "$GENDIR"/config.h \
+# $KCONFIG_CONFIG last, not first: this tree's own sed (sbase, not gnu
+# sed) doesn't look ahead for a later -e when deciding whether the
+# first bare argument is a script or a file -- given BEFORE any -e, it
+# gets misread as a (malformed) script instead of the input file
+# ("bad sed function"), confirmed for real. gnu sed tolerates either
+# order; sbase's own parser needs every -e before the filename.
+$SED -En > "$GENDIR"/config.h \
-e 's/^# CONFIG_(.*) is not set.*/#define CFG_\1 0\n#define USE_\1(...)\n#define SKIP_\1(...) __VA_ARGS__/p;t' \
-e 's/^CONFIG_(.*)=y.*/#define CFG_\1 1\n#define USE_\1(...) __VA_ARGS__\n#define SKIP_\1(...)/p;t'\
- -e 's/^CONFIG_(.*)=/#define CFG_\1 /p' || exit 1
+ -e 's/^CONFIG_(.*)=/#define CFG_\1 /p' $KCONFIG_CONFIG || exit 1
# Process config.h and newtoys.h to generate FLAG_x macros. Note we must
# always #define the relevant macro, even when it's disabled, because we
@@ -156,7 +174,7 @@
# so allflags can define the appropriate zero macros.
done | $SED -n -e 's/" *"//g;/^#/d;t no;:no;s/"/"/p;t;s/\( [AB] \).*/\1 " "/p'|\
- sort -s | $SED -n -e 's/ A / /;t pair;h;s/\([^ ]*\).*/\1 " "/;x' \
+ sort | $SED -n -e 's/ A / /;t pair;h;s/\([^ ]*\).*/\1 " "/;x' \
-e 'b single;:pair;h;n;:single;s/[^ ]* B //;H;g;s/\n/ /;p' | \
brun mkflags > "$GENDIR"/flags.h || exit 1
@@ -168,7 +186,7 @@
$TOYFILES)"
echo "$STRUX" &&
echo "extern union global_union {" &&
- $SED -n 's/^struct \(.*\)_data .*/\1/;T;s/.*/\tstruct &_data &;/p' \
+ $SED -n 's/^struct \(.*\)_data .*/\1/;T;s/.*/ struct &_data &;/p' \
<<<"$STRUX" &&
echo "} this;"
} > "$GENDIR"/globals.h || exit 1
@@ -193,7 +211,7 @@
then
do_loudly $HOSTCC -I . scripts/install.c -o "$UNSTRIPPED"/instlist || exit 1
{ echo "#define ZHELP_LEN $("$UNSTRIPPED"/instlist --help | wc -c)" &&
- "$UNSTRIPPED"/instlist --help | gzip -9 | od -Anone -vtx1 | \
+ "$UNSTRIPPED"/instlist --help | gzip -9 | od -An -vtx1 | \
sed 's/ /,0x/g;1s/^,/static char zhelp_data[] = {\n /;$s/.*/&};/'
} > "$GENDIR"/zhelp.h || exit 1
else