From 844439af999c1600c12f83c1e652a8add1c49d34 Mon Sep 17 00:00:00 2001 From: Johannes Kuhn Date: Tue, 4 Jun 2024 15:24:59 +0200 Subject: [PATCH] Add Tcl 9 compatibility init_tcl has been split into 2 parts: init_tcl0 sets the notifier, calls Tcl_FindExecutable and if Tcl >= 9 calls Tcl_InitSubsystem. init_tcl1 does the rest. init_tcl0 must be called before the thread local storage is used. Tests show that this compiles and runs with both Tcl 8.6.11 and Tcl 9.0b1. Following minor changes have been made: Replace TCL_INTERP_DESTROYED with Tcl_InterpDeleted() (also see TCL_INTERP_DESTROYED -> Tcl_InterpDeleted() #1537) Define EGG_CONST as const (CONST is gone) Introduce Tcl_Size - which is typedef int Tcl_Size if not provided by tcl.h Update variable types to Tcl_Size where needed. Replace Tcl_DStringTrunc with Tcl_DStringSetLength Test cases demonstrating functionality (if applicable): [Tcl9Eggdrop] (): Running Eggdrop 1.9.5+python 1090505 with Tcl 9.0b [Tcl8Eggdrop] (): Running Eggdrop 1.9.5+python 1090505 with Tcl 8.6. --- src/main.c | 8 +++++--- src/main.h | 13 ++++++++----- src/mod/channels.mod/channels.c | 2 +- src/mod/channels.mod/cmdschan.c | 2 +- src/mod/channels.mod/tclchan.c | 6 +++--- src/mod/irc.mod/tclirc.c | 6 ++++-- src/mod/server.mod/server.c | 5 +++-- src/mod/server.mod/tclisupport.c | 10 +++++----- src/tcl.c | 28 +++++++++++++++++----------- src/userent.c | 3 ++- 10 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/main.c b/src/main.c index 8d2874f62..17133c5b5 100644 --- a/src/main.c +++ b/src/main.c @@ -722,7 +722,8 @@ int init_userent(); int init_misc(); int init_bots(); int init_modules(); -void init_tcl(int, char **); +void init_tcl0(int, char **); +void init_tcl1(int, char **); void init_language(int); #ifdef TLS int ssl_init(); @@ -893,7 +894,7 @@ static void mainloop(int toplevel) } kill_tcl(); - init_tcl(argc, argv); + init_tcl1(argc, argv); init_language(0); /* this resets our modules which we didn't unload (encryption and uptime) */ @@ -1037,6 +1038,7 @@ int main(int arg_c, char **arg_v) init_mem(); if (argc > 1) do_arg(); + init_tcl0(argc, argv); init_language(1); printf("\n%s\n", version); @@ -1056,7 +1058,7 @@ int main(int arg_c, char **arg_v) init_modules(); if (backgrd) bg_prepare_split(); - init_tcl(argc, argv); + init_tcl1(argc, argv); init_language(0); #ifdef STATIC link_statics(); diff --git a/src/main.h b/src/main.h index f8f2b5032..79d388492 100644 --- a/src/main.h +++ b/src/main.h @@ -41,15 +41,18 @@ #include "eggint.h" #include "lush.h" +#ifndef TCL_SIZE_MAX + typedef int Tcl_Size; +# define Tcl_GetSizeIntFromObj Tcl_GetIntFromObj +# define TCL_SIZE_MAX INT_MAX +# define TCL_SIZE_MODIFIER "" +#endif + #ifndef TCL_PATCH_LEVEL # define TCL_PATCH_LEVEL "*unknown*" #endif -#ifdef CONST -# define EGG_CONST CONST -#else -# define EGG_CONST -#endif +#define EGG_CONST const #ifdef CONST86 # define TCL_CONST86 CONST86 diff --git a/src/mod/channels.mod/channels.c b/src/mod/channels.mod/channels.c index 95fed762b..d5d849879 100644 --- a/src/mod/channels.mod/channels.c +++ b/src/mod/channels.mod/channels.c @@ -737,7 +737,7 @@ static char *traced_globchanset(ClientData cdata, Tcl_Interp *irp, EGG_CONST char *name1, EGG_CONST char *name2, int flags) { - int i, items; + Tcl_Size i, items; char *t, *s; EGG_CONST char **item, *s2; diff --git a/src/mod/channels.mod/cmdschan.c b/src/mod/channels.mod/cmdschan.c index 4d96630a7..d613f43a9 100644 --- a/src/mod/channels.mod/cmdschan.c +++ b/src/mod/channels.mod/cmdschan.c @@ -1191,7 +1191,7 @@ static void cmd_mns_chrec(struct userrec *u, int idx, char *par) static void cmd_pls_chan(struct userrec *u, int idx, char *par) { - int i, argc; + Tcl_Size i, argc; EGG_CONST char **argv; char *chname; struct chanset_t *chan; diff --git a/src/mod/channels.mod/tclchan.c b/src/mod/channels.mod/tclchan.c index 79df93d02..f40f9f8d2 100644 --- a/src/mod/channels.mod/tclchan.c +++ b/src/mod/channels.mod/tclchan.c @@ -1013,7 +1013,7 @@ static int tcl_channel_getlist(Tcl_Interp *irp, struct chanset_t *chan) { char s[121], *str; EGG_CONST char **argv = NULL; - int argc = 0; + Tcl_Size argc = 0; struct udef_struct *ul; /* String values first */ @@ -1133,7 +1133,7 @@ static int tcl_channel_get(Tcl_Interp *irp, struct chanset_t *chan, { char s[121], *str = NULL; EGG_CONST char **argv = NULL; - int argc = 0; + Tcl_Size argc = 0; struct udef_struct *ul; if (!strcmp(setting, "chanmode")) @@ -2089,7 +2089,7 @@ static void clear_channel(struct chanset_t *chan, int reset) */ static int tcl_channel_add(Tcl_Interp *irp, char *newname, char *options) { - int items; + Tcl_Size items; int ret = TCL_OK; int join = 0; char buf[2048], buf2[256]; diff --git a/src/mod/irc.mod/tclirc.c b/src/mod/irc.mod/tclirc.c index b8a93b3cd..2e27744a8 100644 --- a/src/mod/irc.mod/tclirc.c +++ b/src/mod/irc.mod/tclirc.c @@ -980,7 +980,8 @@ static int tcl_account2nicks STDVAR struct chanset_t *chan, *thechan = NULL; Tcl_Obj *nicks; Tcl_Obj **nicksv = NULL; - int nicksc = 0, i, found; + Tcl_Size nicksc = 0, i; + int found; BADARGS(2, 3, " account ?channel?"); @@ -1026,7 +1027,8 @@ static int tcl_hand2nicks STDVAR struct userrec *u; Tcl_Obj *nicks; Tcl_Obj **nicksv = NULL; - int nicksc = 0, i, found; + Tcl_Size nicksc = 0, i; + int found; BADARGS(2, 3, " handle ?channel?"); diff --git a/src/mod/server.mod/server.c b/src/mod/server.mod/server.c index 80d0ad5f1..6aff0e488 100644 --- a/src/mod/server.mod/server.c +++ b/src/mod/server.mod/server.c @@ -1413,7 +1413,7 @@ static int server_raw STDVAR static int server_rawt STDVAR { - int unused; + Tcl_Size unused; Tcl_Obj *tagdict; Function F = (Function) cd; @@ -1809,7 +1809,8 @@ static char *tcl_eggserver(ClientData cdata, Tcl_Interp *irp, EGG_CONST char *name1, EGG_CONST char *name2, int flags) { - int lc, code, i; + Tcl_Size lc, i; + int code; char x[1024]; EGG_CONST char **list, *slist; struct server_list *q; diff --git a/src/mod/server.mod/tclisupport.c b/src/mod/server.mod/tclisupport.c index 6ac22d7b3..66fa72aae 100644 --- a/src/mod/server.mod/tclisupport.c +++ b/src/mod/server.mod/tclisupport.c @@ -67,7 +67,7 @@ int tcl_isupport STDOBJVAR static int tcl_isupport_get STDOBJVAR { - int keylen; + Tcl_Size keylen; const char *key, *value; Tcl_Obj *tclres; @@ -95,7 +95,7 @@ static int tcl_isupport_get STDOBJVAR static int tcl_isupport_isset STDOBJVAR { - int keylen; + Tcl_Size keylen; const char *key, *value; BADOBJARGS(3, 3, 2, "setting"); @@ -109,7 +109,7 @@ static int tcl_isupport_isset STDOBJVAR /* not exposed for now */ static int tcl_isupport_set STDOBJVAR { - int keylen, valuelen; + Tcl_Size keylen, valuelen; const char *key, *value; /* First one to check for type validity only */ @@ -126,7 +126,7 @@ static int tcl_isupport_set STDOBJVAR static int tcl_isupport_unset STDOBJVAR { struct isupport *data; - int keylen; + Tcl_Size keylen; const char *key; BADOBJARGS(3, 3, 2, "setting"); @@ -170,7 +170,7 @@ char *traced_isupport(ClientData cdata, Tcl_Interp *irp, } /* remove trailing space */ if (Tcl_DStringLength(&ds)) - Tcl_DStringTrunc(&ds, Tcl_DStringLength(&ds) - 1); + Tcl_DStringSetLength(&ds, Tcl_DStringLength(&ds) - 1); Tcl_SetVar2(interp, name1, name2, Tcl_DStringValue(&ds), TCL_GLOBAL_ONLY); Tcl_DStringFree(&ds); diff --git a/src/tcl.c b/src/tcl.c index 71fe6d9be..64409ee25 100644 --- a/src/tcl.c +++ b/src/tcl.c @@ -905,17 +905,10 @@ void init_unicodesup(void) } #endif /* TCL_WORKAROUND_UNICODESUP */ -/* Not going through Tcl's crazy main() system (what on earth was he - * smoking?!) so we gotta initialize the Tcl interpreter - */ -void init_tcl(int argc, char **argv) +void init_tcl0(int argc, char **argv) { Tcl_NotifierProcs notifierprocs; - - const char *encoding; - int i, j; - char *langEnv, pver[1024] = ""; - + egg_bzero(¬ifierprocs, sizeof(notifierprocs)); notifierprocs.initNotifierProc = tickle_InitNotifier; notifierprocs.createFileHandlerProc = tickle_CreateFileHandler; @@ -927,8 +920,8 @@ void init_tcl(int argc, char **argv) notifierprocs.serviceModeHookProc = tickle_ServiceModeHook; Tcl_SetNotifier(¬ifierprocs); - -/* This must be done *BEFORE* Tcl_SetSystemEncoding(), + + /* This must be done *BEFORE* Tcl_SetSystemEncoding(), * or Tcl_SetSystemEncoding() will cause a segfault. */ /* This is used for 'info nameofexecutable'. @@ -936,6 +929,19 @@ void init_tcl(int argc, char **argv) * the environment variable PATH for it to register anything. */ Tcl_FindExecutable(argv[0]); +#if TCL_MAJOR_VERSION >= 9 + Tcl_InitSubsystems(); +#endif +} + +/* Not going through Tcl's crazy main() system (what on earth was he + * smoking?!) so we gotta initialize the Tcl interpreter + */ +void init_tcl1(int argc, char **argv) +{ + const char *encoding; + int i, j; + char *langEnv, pver[1024] = ""; /* Initialize the interpreter */ interp = Tcl_CreateInterp(); diff --git a/src/userent.c b/src/userent.c index 3fde1f20a..a070995fd 100644 --- a/src/userent.c +++ b/src/userent.c @@ -1036,7 +1036,8 @@ static int xtra_pack(struct userrec *u, struct user_entry *e) static void xtra_display(int idx, struct user_entry *e) { - int code, lc, j; + int code; + Tcl_Size lc, j; EGG_CONST char **list; struct xtra_key *xk;