diff options
| author | Paul Buetow <paul@buetow.org> | 2026-07-02 00:53:37 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-07-02 00:53:37 +0300 |
| commit | 5c744e37b6375f3f6842cdf3758a180a649bafea (patch) | |
| tree | eb28d27988539228727b0d47d32b2d7927bc145c /ycurses | |
| parent | 58602a28d2c92b603208f3e01c14c169d28cc7b0 (diff) | |
ycurses: get it building on modern GCC, verify in Docker (task 9s0)
ycurses shares no source files with ychat/yhttpd (it's an ncurses UI
toolkit, not part of the httpd/socket engine), so none of the sock/reqp/
html/logd/tool fixes apply here - only the same class of toolchain-gate
bugs did:
- Top-level configure's g++ 3.x version gate now accepts any GNU g++
(same fix as yhttpd/configure).
- scripts/config.pl silently BEGIN-failed on modern Perl (`use
scripts::modules::file` needs "." on @INC, dropped by Perl 5.26+); the
"yes" default answer was never actually read. Fixed with `perl -I.`
(also applied to yhttpd/configure, which had the same latent bug).
- src/configure's library search paths predate 64-bit multilib distros
(no /usr/lib64), so installed libpanel/libmenu/libncurses were reported
"NOT OK" on Rocky Linux 9 (also backported to yhttpd/src/configure).
- attributes.h declared `set<int> set_attr` (std::set, via `using
namespace std`) and separately two member functions literally named
`set` - GCC 11 treats that as ill-formed ("changes meaning of 'set'"),
not just a warning. Renamed both overloads to set_attr_flag; no
external caller used the bare set(...)/set(int) names.
Verified in a Rocky Linux 9 container: builds clean, links, and runs -
initializes curses, draws the demo screen using color/attributes
(exercising the fix above), exits cleanly. Added Dockerfile (build
verification only - it's an interactive demo, not a service) and
BUILD.md documenting the fixes and one pre-existing, deliberately
unfixed bug (unset() never actually clears an attribute).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'ycurses')
| -rw-r--r-- | ycurses/.dockerignore | 7 | ||||
| -rw-r--r-- | ycurses/.gitignore | 10 | ||||
| -rw-r--r-- | ycurses/BUILD.md | 66 | ||||
| -rw-r--r-- | ycurses/Dockerfile | 30 | ||||
| -rw-r--r-- | ycurses/Makefile | 8 | ||||
| -rwxr-xr-x | ycurses/configure | 26 | ||||
| -rwxr-xr-x | ycurses/src/configure | 3 | ||||
| -rw-r--r-- | ycurses/src/curses/attributes.cpp | 4 | ||||
| -rw-r--r-- | ycurses/src/curses/attributes.h | 35 |
9 files changed, 159 insertions, 30 deletions
diff --git a/ycurses/.dockerignore b/ycurses/.dockerignore new file mode 100644 index 0000000..6a4113d --- /dev/null +++ b/ycurses/.dockerignore @@ -0,0 +1,7 @@ +obj +bin +backuped +*.version +src/Makefile +src/includes.add +src/libs.add diff --git a/ycurses/.gitignore b/ycurses/.gitignore new file mode 100644 index 0000000..88e6d8c --- /dev/null +++ b/ycurses/.gitignore @@ -0,0 +1,10 @@ +bin +obj/ +g++.version +make.version +src/Makefile +src/includes.add +src/libs.add +backuped/ +*.o +*.so diff --git a/ycurses/BUILD.md b/ycurses/BUILD.md new file mode 100644 index 0000000..809c39d --- /dev/null +++ b/ycurses/BUILD.md @@ -0,0 +1,66 @@ +# ycurses — build revival + +`ycurses` is a standalone ncurses C++ toolkit (windows, menus, attributes, +color) from the same ~2003-2005 era as `../ychat` and `../yhttpd`, but it +shares no source files with them (no `sock`/`reqp`/`html`/`logd`/`tool`) - +it's a UI library, not a network daemon. `src/main.cpp` is an interactive +full-screen demo menu; there is no service to deploy, so unlike `../yhttpd` +this only needed a build fix, verified in Docker (`Dockerfile` here is a +build check, not a runtime image). + +## Build & verify (local) + +``` +podman build -t ycurses:dev . +podman run --rm -it ycurses:dev # interactive demo menu; Ctrl-C to exit +``` + +Verified: builds clean (one pre-existing, harmless `-Wreturn-type` warning +in `menu.cpp`), links, and runs - initializes curses, draws the demo screen +using `color`/`attributes` (exercising the fix below), exits cleanly on +EOF/SIGINT. + +## What was fixed + +- **Top-level `configure`'s g++ 3.x version gate** now accepts any GNU g++ + (was hardcoded to versions 3.1-3.4), same fix as `../yhttpd/configure`. +- **`scripts/config.pl` silently failed on modern Perl**: it does `use + scripts::modules::file`, which needs `.` on `@INC`; Perl 5.26+ dropped + `.` from the default `@INC`. The top-level `configure` invoked it via + `system("perl ...")` without `-I.`, so it `BEGIN`-failed before ever + reading the "yes" answer - harmless here only because the committed + `src/glob.h` defaults already matched, but it means the interactive + configurator never actually ran. Fixed with `perl -I.` (also applied to + `../yhttpd/configure`, which has the same bug). +- **`src/configure`'s library search path list predates 64-bit multilib + distros**: it only checked `/usr/lib`, `/lib`, etc., never `/usr/lib64` + or `/lib64`, so `libpanel.so`/`libmenu.so`/`libncurses.so` were reported + "NOT OK" on Rocky Linux 9 even though they're installed - the script + aborts before generating a Makefile if a required lib "isn't found" (the + actual compiler/linker would have found them fine via its own default + search path; this is purely the custom dependency-checker being + outdated). Added `/lib64`, `/usr/lib64`, `/usr/local/lib64` to + `@libpaths` (also applied to `../yhttpd/src/configure` for the same + latent gap, even though yhttpd doesn't currently need any of these + libs). +- **`attributes` class member functions named `set`/`set(int)` collide + with `std::set`**: `attributes.h` does `using namespace std` and declares + `set<int> set_attr` (a `std::set`), then separately declares member + *functions* literally named `set` - GCC 11 treats declaring a member + with the same name as a using-directive-visible type as ill-formed + ("changes meaning of 'set'"), not just a warning. Renamed both + overloads to `set_attr_flag` (`attributes.h`, `attributes.cpp`); no + external caller used the bare `set(...)`/`set(int)` names (checked all + of `src/`), only the named setters (`set_bold`, etc.) and the unrelated + `window::set_attributes`. Same category of fix as the + `function`->`mod_func_t` rename in `../ychat`/`../yhttpd`'s `glob.h`. + +## Known pre-existing issue (not fixed - out of scope for this pass) + +`attributes::set_attr_flag(bool b, int i_attr)` (`attributes.cpp`) never +actually removes a flag when `b` is `false`: it only checks whether the +current membership already equals `b` and, if not, unconditionally +**inserts** into `set_attr` - so `unset(...)` cannot clear an attribute +once set (it either no-ops or wrongly re-inserts). This bug predates this +revival and is unrelated to the build/toolchain fixes above; flagging it +here rather than fixing it silently while touching this function. diff --git a/ycurses/Dockerfile b/ycurses/Dockerfile new file mode 100644 index 0000000..c27b45c --- /dev/null +++ b/ycurses/Dockerfile @@ -0,0 +1,30 @@ +# ycurses — Docker build verification +# +# ycurses is a standalone ncurses C++ toolkit (windows/menus/attributes/ +# color), demoed by an interactive full-screen menu (src/main.cpp) - there +# is no server/service to run, so unlike ../yhttpd this image is a build +# check, not a deployable runtime. +# +# Builds entirely in a container on Rocky Linux 9, whose GCC 11 accepts the +# legacy C++ this ~2005 codebase uses once the fixes below are applied. + +FROM rockylinux:9 AS builder + +RUN dnf -y install \ + gcc-c++ \ + make \ + perl \ + which \ + ncurses-devel \ + && dnf clean all + +WORKDIR /build/ycurses +COPY . . +RUN rm -rf obj bin backuped g++.version make.version src/Makefile src/includes.add src/libs.add + +# config.pl is interactive (asks yes/no); "yes" = use default before-compile +# options. +RUN echo yes | ./configure \ + && make + +ENTRYPOINT ["/build/ycurses/bin"] diff --git a/ycurses/Makefile b/ycurses/Makefile index 6e1e203..3f12b2b 100644 --- a/ycurses/Makefile +++ b/ycurses/Makefile @@ -27,13 +27,13 @@ deinstall: @exit 1 base: @if test -f bin/ycurses; then echo "Backing up old binary";if test -f bin/ycurses.old; then rm -f bin/ycurses.old; fi; mv bin/ycurses bin/ycurses.old; fi - @perl ./scripts/buildnr.pl - @perl ./scripts/setglobvals.pl - @${MAKE} -C ./src + @perl -I. ./scripts/buildnr.pl + @perl -I. ./scripts/setglobvals.pl + @${MAKE} -C ./src clean_base: @${MAKE} -C ./src clean stats: - @perl scripts/stats.pl + @perl -I. scripts/stats.pl run: ./bin/ycurses base_start: base diff --git a/ycurses/configure b/ycurses/configure index 9aab971..56f015f 100755 --- a/ycurses/configure +++ b/ycurses/configure @@ -51,17 +51,25 @@ perl -e ' } &check_make; print "Checking compiler version\n"; - my $r = 0; - for (my $i = 4; $i > 0 && $r == 0; --$i ) { - $r = &check_gcc(3,$i); - } - if ($r == 0) { - print "No suitable g++ compiler found!\n"; - print "Please install a right version of GNU G++!\n"; + # Accept any GNU g++ (the original check only accepted g++ 3.x; modern GCC + # works fine with the legacy-C++ fixes applied). Write g++.version as + # "<version>\ng++\n" - src/configure reads the last line as the compiler. + my $ver = `g++ -dumpversion 2>/dev/null`; + chomp $ver; + if ( $ver eq "" ) { + print "No GNU g++ compiler found!\nPlease install GNU G++!\n"; exit(1); } - - system("perl \"scripts/config.pl\""); + `echo $ver > g++.version`; + `echo g++ >> g++.version`; + print "GNU G++ $ver found!\n"; + + # -I. : scripts/config.pl does "use scripts::modules::file", which needs + # "." on @INC. Perl 5.26+ dropped "." from the default @INC, so this + # silently BEGIN-failed on modern Perl (the "yes" answer was never even + # read - it happened to be harmless only because the committed glob.h + # defaults were already correct). + system("perl -I. \"scripts/config.pl\""); chdir("src"); system("./configure ".join(" ", @ARGV)); chdir(".."); diff --git a/ycurses/src/configure b/ycurses/src/configure index cb7c9ff..cffbbda 100755 --- a/ycurses/src/configure +++ b/ycurses/src/configure @@ -51,8 +51,11 @@ perl -e ' $ENV{HOME}."/lib", $ENV{HOME}."/usr/lib", "/lib", + "/lib64", "/usr/lib", + "/usr/lib64", "/usr/local/lib", + "/usr/local/lib64", "/usr/pkg/lib", "/opt/lib", "/opt/local/lib" diff --git a/ycurses/src/curses/attributes.cpp b/ycurses/src/curses/attributes.cpp index b859da0..02f7e27 100644 --- a/ycurses/src/curses/attributes.cpp +++ b/ycurses/src/curses/attributes.cpp @@ -11,7 +11,7 @@ attributes::attributes() attributes::attributes(int i_attr) { init(); - set(true, i_attr); + set_attr_flag(true, i_attr); } attributes::attributes(color& r_color) @@ -63,7 +63,7 @@ attributes::get(int i_attr) } void -attributes::set(bool b, int i_attr) +attributes::set_attr_flag(bool b, int i_attr) { if ((set_attr.find(i_attr) != set_attr.end() ) == b) return; diff --git a/ycurses/src/curses/attributes.h b/ycurses/src/curses/attributes.h index 2bc58d6..93a5e25 100644 --- a/ycurses/src/curses/attributes.h +++ b/ycurses/src/curses/attributes.h @@ -22,10 +22,15 @@ const int CharText = A_CHARTEXT; class attributes { private: - void init(); + void init(); set<int> set_attr; bool get(int i_attr); - void set(bool b, int i_attr); + // Named set_attr_flag (not "set") because a member named exactly "set" + // here would collide with std::set - "using namespace std" makes both + // visible and GCC treats declaring the member as ill-formed ("changes + // meaning of 'set'"). Same class of fix as the function->mod_func_t + // rename in ychat/yhttpd's glob.h. + void set_attr_flag(bool b, int i_attr); color* p_color; friend class window; @@ -37,22 +42,22 @@ public: attributes(int i_attr); attributes(color& r_color); - void set(int i_attr) { set(true, i_attr); } - void unset(int i_attr ) { set(false, i_attr); } + void set_attr_flag(int i_attr) { set_attr_flag(true, i_attr); } + void unset(int i_attr ) { set_attr_flag(false, i_attr); } void unset_all(); void set_color(color& r_color); - void set_normal(bool b) { set(b, Normal); } - void set_standout(bool b) { set(b, Standout); } - void set_underline(bool b) { set(b, Underline); } - void set_reverse(bool b) { set(b, Reverse); } - void set_blink(bool b) { set(b, Blink); } - void set_dim(bool b) { set(b, Dim); } - void set_bold(bool b) { set(b, Bold); } - void set_protect(bool b) { set(b, Protect); } - void set_invisible(bool b) { set(b, Invis); } - void set_altcharset(bool b) { set(b, AltCharSet); } - void set_chartext(bool b) { set(b, CharText); } + void set_normal(bool b) { set_attr_flag(b, Normal); } + void set_standout(bool b) { set_attr_flag(b, Standout); } + void set_underline(bool b) { set_attr_flag(b, Underline); } + void set_reverse(bool b) { set_attr_flag(b, Reverse); } + void set_blink(bool b) { set_attr_flag(b, Blink); } + void set_dim(bool b) { set_attr_flag(b, Dim); } + void set_bold(bool b) { set_attr_flag(b, Bold); } + void set_protect(bool b) { set_attr_flag(b, Protect); } + void set_invisible(bool b) { set_attr_flag(b, Invis); } + void set_altcharset(bool b) { set_attr_flag(b, AltCharSet); } + void set_chartext(bool b) { set_attr_flag(b, CharText); } bool get_normal() { return get(Normal); } bool get_standout() { return get(Standout); } |
