summaryrefslogtreecommitdiff
path: root/ycurses
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-07-02 00:53:37 +0300
committerPaul Buetow <paul@buetow.org>2026-07-02 00:53:37 +0300
commit5c744e37b6375f3f6842cdf3758a180a649bafea (patch)
treeeb28d27988539228727b0d47d32b2d7927bc145c /ycurses
parent58602a28d2c92b603208f3e01c14c169d28cc7b0 (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/.dockerignore7
-rw-r--r--ycurses/.gitignore10
-rw-r--r--ycurses/BUILD.md66
-rw-r--r--ycurses/Dockerfile30
-rw-r--r--ycurses/Makefile8
-rwxr-xr-xycurses/configure26
-rwxr-xr-xycurses/src/configure3
-rw-r--r--ycurses/src/curses/attributes.cpp4
-rw-r--r--ycurses/src/curses/attributes.h35
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); }