In Tcl_ChannelType, the second spot is the version field, a pointer to
struct Tcl_ChannelTypeVersion_, see tcl.h. For historic reasons, that's
where the ExpBlockModeProc function pointer sits. llvm22 is unhappy:
/usr/obj/ports/expect-5.45.4/expect5.45.4/exp_chan.c:62:5: error: incompatible
pointer types initializing 'Tcl_ChannelTypeVersion' (aka 'struct
Tcl_ChannelTypeVersion_ *') with an expression of type 'int (ClientData, int)'
(aka 'int (void *, int)') [-Wincompatible-pointer-types]
62 | ExpBlockModeProc, /* Set blocking/nonblocking
mode.*/
The intention is that works via this piece of beauty in lang/tcl/8.x:
Tcl_DriverBlockModeProc *
Tcl_ChannelBlockModeProc(
const Tcl_ChannelType *chanTypePtr)
/* Pointer to channel type. */
{
if (HaveVersion(chanTypePtr, TCL_CHANNEL_VERSION_2)) {
return chanTypePtr->blockModeProc;
} else {
/*
* The v1 structure had the blockModeProc in a different place.
*/
return (Tcl_DriverBlockModeProc *) (chanTypePtr->version);
}
}
Now, passing a function pointer through a normal pointer is undefined
behavior, so I'm a bit uneasy with doing this, although it currently
works:
- ExpBlockModeProc, /* Set blocking/nonblocking mode.*/
+ (Tcl_ChannelTypeVersion)ExpBlockModeProc, /* Set blocking/nonblocking
mode.*/
I decided to set the version to 2 and to move the ExpBlockModeProc to
the proper spot in the struct.
But perhaps that breaks something else. For example, it seems that
Tcl 9 only supports TCL_CHANNEL_VERSION_5...
Index: Makefile
===================================================================
RCS file: /cvs/ports/lang/expect/Makefile,v
diff -u -p -r1.77 Makefile
--- Makefile 21 Jan 2026 22:03:31 -0000 1.77
+++ Makefile 20 May 2026 20:49:33 -0000
@@ -1,6 +1,8 @@
COMMENT = sophisticated scripter based on Tcl/Tk
VERSION = 5.45.4
+REVISION = 0
+
DISTNAME = expect${VERSION}
PKGNAME = expect-${VERSION}
SHARED_LIBS = expect5454 0.0
Index: patches/patch-exp_chan_c
===================================================================
RCS file: /cvs/ports/lang/expect/patches/patch-exp_chan_c,v
diff -u -p -r1.2 patch-exp_chan_c
--- patches/patch-exp_chan_c 11 Mar 2022 19:28:56 -0000 1.2
+++ patches/patch-exp_chan_c 20 May 2026 21:20:44 -0000
@@ -1,7 +1,10 @@
Get rid of implicit declaration of function warning
---- exp_chan.c.orig Thu Sep 9 19:29:43 2010
-+++ exp_chan.c Thu Sep 9 19:30:27 2010
+error: incompatible pointer types initializing 'Tcl_ChannelTypeVersion' (aka
'struct Tcl_ChannelTypeVersion_ *') with an expression of type 'int
(ClientData, int)' (aka 'int (void *, int)') [-Wincompatible-pointer-types]
+
+Index: exp_chan.c
+--- exp_chan.c.orig
++++ exp_chan.c
@@ -37,6 +37,7 @@
#include "exp_log.h"
#include "tcldbg.h" /* Dbg_StdinMode */
@@ -10,3 +13,20 @@ Get rid of implicit declaration of funct
extern int expSetBlockModeProc _ANSI_ARGS_((int fd, int mode));
static int ExpBlockModeProc _ANSI_ARGS_((ClientData instanceData,
int mode));
+@@ -58,7 +59,7 @@ static int ExpGetHandleProc
_ANSI_ARGS_((ClientData i
+
+ Tcl_ChannelType expChannelType = {
+ "exp", /* Type name. */
+- ExpBlockModeProc, /* Set blocking/nonblocking mode.*/
++ TCL_CHANNEL_VERSION_2, /* Version. */
+ ExpCloseProc, /* Close proc. */
+ ExpInputProc, /* Input proc. */
+ ExpOutputProc, /* Output proc. */
+@@ -68,6 +69,7 @@ Tcl_ChannelType expChannelType = {
+ ExpWatchProc, /* Initialize notifier. */
+ ExpGetHandleProc, /* Get OS handles out of channel. */
+ NULL, /* Close2 proc */
++ ExpBlockModeProc, /* Set blocking/nonblocking mode.*/
+ };
+
+ typedef struct ThreadSpecificData {