From 40512c351e1fad8f65bf2b3d3cb18680a101a33a Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Tue, 25 Aug 2026 16:44:27 +0000 Subject: [PATCH 01/14] Update configure.ac --- configure.ac | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index abbcfac..8f775ca 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ dnl to configure the system for the local environment. # so you can encode the package version directly into the source files. #----------------------------------------------------------------------- -AC_INIT([tclclockmod], [8.6.710]) +AC_INIT([tclclockmod],[9.0]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. @@ -36,13 +36,16 @@ AC_CONFIG_AUX_DIR(tclconfig) TEA_PATH_TCLCONFIG TEA_LOAD_TCLCONFIG -if test "${TCL_MAJOR_VERSION}" -ne 8 ; then - AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+ -Found config for Tcl ${TCL_VERSION}]) -fi -if test "${TCL_MINOR_VERSION}" -lt 6 ; then - AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+ +if test "${TCL_MAJOR_VERSION}" -eq 8 ; then + if test "${TCL_MINOR_VERSION}" -lt 6 ; then + AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+ + Found config for Tcl ${TCL_VERSION}]) + fi +else + if test "${TCL_MAJOR_VERSION}" -ne 9 ; then + AC_MSG_ERROR([${PACKAGE_NAME} ${PACKAGE_VERSION} requires Tcl 8.6+ Found config for Tcl ${TCL_VERSION}]) + fi fi #-------------------------------------------------------------------- @@ -232,4 +235,5 @@ TEA_PROG_TCLSH # which require substituting th AC variables in. Include these here. #-------------------------------------------------------------------- -AC_OUTPUT([Makefile pkgIndex.tcl lib/clock.tcl]) +AC_CONFIG_FILES([Makefile pkgIndex.tcl lib/clock.tcl]) +AC_OUTPUT From 54005137d03b99ad0fde45a7a2bc4a9a75c24bc7 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 14:53:18 +0000 Subject: [PATCH 02/14] Update Tcl_InitStubs --- generic/tclClockMod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclClockMod.c b/generic/tclClockMod.c index d519ac2..5f296a4 100644 --- a/generic/tclClockMod.c +++ b/generic/tclClockMod.c @@ -82,7 +82,7 @@ Tclclockmod_Init(interp) static int initialized = 0; if (!initialized) { - if (Tcl_InitStubs(interp, "8.6", 0) == NULL) { + if (Tcl_InitStubs(interp, "8.6+", 0) == NULL) { return TCL_ERROR; } _InitModTclInternals(interp); From a7f4e74b195edbd266a233305af03ad056fb5c52 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 14:57:58 +0000 Subject: [PATCH 03/14] Fix syntax for Tcl_InitStubs --- generic/tclClockMod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclClockMod.c b/generic/tclClockMod.c index 5f296a4..9830188 100644 --- a/generic/tclClockMod.c +++ b/generic/tclClockMod.c @@ -82,7 +82,7 @@ Tclclockmod_Init(interp) static int initialized = 0; if (!initialized) { - if (Tcl_InitStubs(interp, "8.6+", 0) == NULL) { + if (Tcl_InitStubs(interp, "8.6-", 0) == NULL) { return TCL_ERROR; } _InitModTclInternals(interp); From 569322e037eb986eed432d80417db4390f85ba18 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 15:17:22 +0000 Subject: [PATCH 04/14] Set up linux-ci-9.yml --- .../workflows/{ci-nix.yml => ci-nix-8.yml} | 0 .../{linux-ci.yml => linux-ci-8.yml} | 0 .github/workflows/linux-ci-9.yml | 65 +++++++++++++++++++ 3 files changed, 65 insertions(+) rename .github/workflows/{ci-nix.yml => ci-nix-8.yml} (100%) rename .github/workflows/{linux-ci.yml => linux-ci-8.yml} (100%) create mode 100644 .github/workflows/linux-ci-9.yml diff --git a/.github/workflows/ci-nix.yml b/.github/workflows/ci-nix-8.yml similarity index 100% rename from .github/workflows/ci-nix.yml rename to .github/workflows/ci-nix-8.yml diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci-8.yml similarity index 100% rename from .github/workflows/linux-ci.yml rename to .github/workflows/linux-ci-8.yml diff --git a/.github/workflows/linux-ci-9.yml b/.github/workflows/linux-ci-9.yml new file mode 100644 index 0000000..6204b11 --- /dev/null +++ b/.github/workflows/linux-ci-9.yml @@ -0,0 +1,65 @@ +# This is a basic workflow to help you get started with Actions + +name: Linux CI + +# Controls when the action will run. +on: + # Triggers the workflow on push or pull request events but only for the main branch + push: + branches: [ master ] + pull_request: + branches: [ master ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-26.04 + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v4 + + - name: Install dependencies + run: | + sudo apt-get update -qq + sudo apt-get install -y tcl9.0-dev + + - name: configure + run: | + autoconf + autoreconf -iv + cd unix + ../configure --with-tcl=/usr/lib/tcl9.0 + + - name: make + run: | + cd unix + make + + - name: unit tests + run: | + # current time and time-zone: + echo $TZ; timedatectl status + # load local library and execute local test cases: + cd unix + make test + + - name: install + run: | + cd unix + sudo make install + + - name: runtime test + run: | + echo 'if {[catch {package require tclclockmod; clock format -now} catchResult]} {puts stderr "ERROR! $catchResult"; exit 1} else {puts "OK."}' | tclsh + + - name: clean + run: | + cd unix + make clean From 57a293be5d251202882544d09f43e137b5ff934f Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 15:34:24 +0000 Subject: [PATCH 05/14] Add Tcl_Size, switch from TclOffset to offsetof --- generic/tclClock.c | 11 ++++++----- generic/tclDate.h | 2 +- generic/tclSize.h | 13 +++++++++++++ 3 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 generic/tclSize.h diff --git a/generic/tclClock.c b/generic/tclClock.c index c909096..0bd2e69 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -17,6 +17,7 @@ #include "tclInt.h" #include "tclStrIdxTree.h" #include "tclDate.h" +#include "tclSize.h" /* * Windows has mktime. The configurators do not check. @@ -1899,7 +1900,7 @@ ConvertLocalToUTC( { ClockClientData *dataPtr = clientData; Tcl_Obj *tzdata; /* Time zone data */ - int rowc; /* Number of rows in tzdata */ + Tcl_Size rowc; /* Number of rows in tzdata */ Tcl_Obj **rowv; /* Pointers to the rows */ Tcl_WideInt seconds; ClockLastTZOffs * ltzoc = NULL; @@ -2040,7 +2041,7 @@ ConvertLocalToUTCUsingTable( Tcl_WideInt *rangesVal) /* Return bounds for time period */ { Tcl_Obj *row; - int cellc; + Tcl_Size cellc; Tcl_Obj **cellv; struct { Tcl_Obj *tzName; @@ -2195,7 +2196,7 @@ ConvertUTCToLocal( { ClockClientData *dataPtr = clientData; Tcl_Obj *tzdata; /* Time zone data */ - int rowc; /* Number of rows in tzdata */ + Tcl_Size rowc; /* Number of rows in tzdata */ Tcl_Obj **rowv; /* Pointers to the rows */ ClockLastTZOffs * ltzoc = NULL; @@ -2327,7 +2328,7 @@ ConvertUTCToLocalUsingTable( Tcl_WideInt *rangesVal) /* Return bounds for time period */ { Tcl_Obj *row; /* Row containing the current information */ - int cellc; /* Count of cells in the row (must be 4) */ + Tcl_Size cellc; /* Count of cells in the row (must be 4) */ Tcl_Obj **cellv; /* Pointers to the cells */ /* @@ -3671,7 +3672,7 @@ ClockScanObjCmd( /* set CLC_UNX_ARGS for ::tcl::clock::unixtime command. */ if (1) { - const char *c; int len; + const char *c; Tcl_Size len; c = Tcl_GetStringFromObj(objv[0], &len); if (len > 18 && c[14] == 'u') { paflags |= CLC_UNX_ARGS; }; } diff --git a/generic/tclDate.h b/generic/tclDate.h index aed67a5..aa07dd6 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -225,7 +225,7 @@ typedef struct TclDateFields { } TclDateFields; #define ClockCacheableDateFieldsSize \ - TclOffset(TclDateFields, tzName) + offsetof(TclDateFields, tzName) /* * Structure contains return parsed fields. diff --git a/generic/tclSize.h b/generic/tclSize.h new file mode 100644 index 0000000..b8ac19b --- /dev/null +++ b/generic/tclSize.h @@ -0,0 +1,13 @@ +/* + * Tcl_Size was introduced in Tcl 9. tclclockmod still supports building against + * Tcl 8.6, where Tcl object and list sizes are int-sized. + */ +#ifndef TCL_SIZE_MAX +# define Tcl_GetSizeIntFromObj Tcl_GetIntFromObj +# define TCL_SIZE_MAX INT_MAX +# ifndef Tcl_Size + typedef int Tcl_Size; +# endif +# define TCL_SIZE_MODIFIER "" +#endif + From 824b57b8c23a35b43f3cd3315651f8824e5cfc99 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 15:38:27 +0000 Subject: [PATCH 06/14] Tag CI with associated TCL version, define TclOffset as offsetof --- .github/workflows/ci-nix-8.yml | 2 +- .github/workflows/linux-ci-8.yml | 2 +- .github/workflows/linux-ci-9.yml | 2 +- generic/tclClockFmt.c | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-nix-8.yml b/.github/workflows/ci-nix-8.yml index 461c3d6..52c1c2a 100644 --- a/.github/workflows/ci-nix-8.yml +++ b/.github/workflows/ci-nix-8.yml @@ -1,4 +1,4 @@ -name: CI-nix +name: CI-nix tcl8 # Controls when the action will run. Triggers the workflow on push or pull request # events but only for the master branch diff --git a/.github/workflows/linux-ci-8.yml b/.github/workflows/linux-ci-8.yml index 347b482..2a19e1f 100644 --- a/.github/workflows/linux-ci-8.yml +++ b/.github/workflows/linux-ci-8.yml @@ -1,6 +1,6 @@ # This is a basic workflow to help you get started with Actions -name: Linux CI +name: Linux CI tcl8 # Controls when the action will run. on: diff --git a/.github/workflows/linux-ci-9.yml b/.github/workflows/linux-ci-9.yml index 6204b11..78c4b7b 100644 --- a/.github/workflows/linux-ci-9.yml +++ b/.github/workflows/linux-ci-9.yml @@ -1,6 +1,6 @@ # This is a basic workflow to help you get started with Actions -name: Linux CI +name: Linux CI tcl9 # Controls when the action will run. on: diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 851a78d..97b66a5 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -13,6 +13,9 @@ #include "tclInt.h" #include "tclStrIdxTree.h" #include "tclDate.h" +#include "tclSize.h" + +#define TclOffset offsetof /* * Miscellaneous forward declarations and functions used within this file From fc48aa0d9492c84ff2753daaf2c736456497ab19 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 15:49:04 +0000 Subject: [PATCH 07/14] Fix old style functions, add Tcl_Size, and remove TclOffset. --- generic/tclClockFmt.c | 142 ++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 75 deletions(-) diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 97b66a5..db60243 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -15,8 +15,6 @@ #include "tclDate.h" #include "tclSize.h" -#define TclOffset offsetof - /* * Miscellaneous forward declarations and functions used within this file */ @@ -612,9 +610,7 @@ Tcl_ObjType ClockFmtObjType = { (*((Tcl_Obj **)&(objPtr)->internalRep.twoPtrValue.ptr2)) static void -ClockFmtObj_DupInternalRep(srcPtr, copyPtr) - Tcl_Obj *srcPtr; - Tcl_Obj *copyPtr; +ClockFmtObj_DupInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr) { ClockFmtScnStorage *fss = ObjClockFmtScn(srcPtr); @@ -643,8 +639,7 @@ ClockFmtObj_DupInternalRep(srcPtr, copyPtr) } static void -ClockFmtObj_FreeInternalRep(objPtr) - Tcl_Obj *objPtr; +ClockFmtObj_FreeInternalRep(Tcl_Obj *objPtr) { ClockFmtScnStorage *fss = ObjClockFmtScn(objPtr); if (fss != NULL && initialized) { @@ -671,9 +666,7 @@ ClockFmtObj_FreeInternalRep(objPtr) }; static int -ClockFmtObj_SetFromAny(interp, objPtr) - Tcl_Interp *interp; - Tcl_Obj *objPtr; +ClockFmtObj_SetFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr) { /* validate string representation before free old internal represenation */ (void)TclGetString(objPtr); @@ -691,8 +684,7 @@ ClockFmtObj_SetFromAny(interp, objPtr) }; static void -ClockFmtObj_UpdateString(objPtr) - Tcl_Obj *objPtr; +ClockFmtObj_UpdateString(Tcl_Obj *objPtr) { const char *name = "UNKNOWN"; int len; @@ -1260,7 +1252,7 @@ ClockMCGetListIdxTree( /* build new index */ Tcl_Obj **lstv; - int lstc; + Tcl_Size lstc; Tcl_Obj *valObj; objPtr = TclStrIdxTreeNewObj(); @@ -1333,7 +1325,7 @@ ClockMCGetMultiListIdxTree( /* build new index */ Tcl_Obj **lstv; - int lstc; + Tcl_Size lstc; Tcl_Obj *valObj; objPtr = TclStrIdxTreeNewObj(); @@ -1917,49 +1909,49 @@ static const char *ScnSTokenMapIndex = "dmbyYHMSpJjCgGVazUsntQ"; static ClockScanTokenMap ScnSTokenMap[] = { /* %d %e */ - {CTOKT_INT, CLF_DAYOFMONTH, 0, 1, 2, TclOffset(DateInfo, date.dayOfMonth), + {CTOKT_INT, CLF_DAYOFMONTH, 0, 1, 2, offsetof(DateInfo, date.dayOfMonth), NULL}, /* %m %N */ - {CTOKT_INT, CLF_MONTH, 0, 1, 2, TclOffset(DateInfo, date.month), + {CTOKT_INT, CLF_MONTH, 0, 1, 2, offsetof(DateInfo, date.month), NULL}, /* %b %B %h */ {CTOKT_PARSER, CLF_MONTH, 0, 0, 0xffff, 0, ClockScnToken_Month_Proc, NULL}, /* %y */ - {CTOKT_INT, CLF_YEAR, 0, 1, 2, TclOffset(DateInfo, date.year), + {CTOKT_INT, CLF_YEAR, 0, 1, 2, offsetof(DateInfo, date.year), NULL}, /* %Y */ - {CTOKT_INT, CLF_YEAR | CLF_CENTURY, 0, 4, 4, TclOffset(DateInfo, date.year), + {CTOKT_INT, CLF_YEAR | CLF_CENTURY, 0, 4, 4, offsetof(DateInfo, date.year), NULL}, /* %H %k %I %l */ - {CTOKT_INT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.hour), + {CTOKT_INT, CLF_TIME, 0, 1, 2, offsetof(DateInfo, date.hour), NULL}, /* %M */ - {CTOKT_INT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.minutes), + {CTOKT_INT, CLF_TIME, 0, 1, 2, offsetof(DateInfo, date.minutes), NULL}, /* %S */ - {CTOKT_INT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.secondOfMin), + {CTOKT_INT, CLF_TIME, 0, 1, 2, offsetof(DateInfo, date.secondOfMin), NULL}, /* %p %P */ {CTOKT_PARSER, 0, 0, 0, 0xffff, 0, ClockScnToken_amPmInd_Proc, NULL}, /* %J */ - {CTOKT_WIDE, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, TclOffset(DateInfo, date.julianDay), + {CTOKT_WIDE, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, offsetof(DateInfo, date.julianDay), NULL}, /* %j */ - {CTOKT_INT, CLF_DAYOFYEAR, 0, 1, 3, TclOffset(DateInfo, date.dayOfYear), + {CTOKT_INT, CLF_DAYOFYEAR, 0, 1, 3, offsetof(DateInfo, date.dayOfYear), NULL}, /* %C */ - {CTOKT_INT, CLF_CENTURY|CLF_ISO8601CENTURY, 0, 1, 2, TclOffset(DateInfo, dateCentury), + {CTOKT_INT, CLF_CENTURY|CLF_ISO8601CENTURY, 0, 1, 2, offsetof(DateInfo, dateCentury), NULL}, /* %g */ - {CTOKT_INT, CLF_ISO8601YEAR, 0, 2, 2, TclOffset(DateInfo, date.iso8601Year), + {CTOKT_INT, CLF_ISO8601YEAR, 0, 2, 2, offsetof(DateInfo, date.iso8601Year), NULL}, /* %G */ - {CTOKT_INT, CLF_ISO8601YEAR | CLF_ISO8601CENTURY, 0, 4, 4, TclOffset(DateInfo, date.iso8601Year), + {CTOKT_INT, CLF_ISO8601YEAR | CLF_ISO8601CENTURY, 0, 4, 4, offsetof(DateInfo, date.iso8601Year), NULL}, /* %V */ - {CTOKT_INT, CLF_ISO8601WEAK, 0, 1, 2, TclOffset(DateInfo, date.iso8601Week), + {CTOKT_INT, CLF_ISO8601WEAK, 0, 1, 2, offsetof(DateInfo, date.iso8601Week), NULL}, /* %a %A %u %w */ {CTOKT_PARSER, CLF_DAYOFWEEK, 0, 0, 0xffff, 0, @@ -1971,7 +1963,7 @@ static ClockScanTokenMap ScnSTokenMap[] = { {CTOKT_INT, CLF_OPTIONAL, 0, 1, 2, 0, /* currently no capture, parse only token */ NULL}, /* %s */ - {CTOKT_WIDE, CLF_POSIXSEC | CLF_SIGNED, 0, 1, 0xffff, TclOffset(DateInfo, date.seconds), + {CTOKT_WIDE, CLF_POSIXSEC | CLF_SIGNED, 0, 1, 0xffff, offsetof(DateInfo, date.seconds), NULL}, /* %n */ {CTOKT_CHAR, 0, 0, 1, 1, 0, NULL, "\n"}, @@ -1990,7 +1982,7 @@ static const char *ScnETokenMapIndex = "EJjys"; static ClockScanTokenMap ScnETokenMap[] = { /* %EE */ - {CTOKT_PARSER, 0, 0, 0, 0xffff, TclOffset(DateInfo, date.year), + {CTOKT_PARSER, 0, 0, 0, 0xffff, offsetof(DateInfo, date.year), ClockScnToken_LocaleERA_Proc, (void *)MCLIT_LOCALE_NUMERALS}, /* %EJ */ {CTOKT_PARSER, CLF_JULIANDAY | CLF_SIGNED, 0, 1, 0xffff, 0, /* calendar JDN starts at midnight */ @@ -2002,7 +1994,7 @@ static ClockScanTokenMap ScnETokenMap[] = { {CTOKT_PARSER, 0, 0, 0, 0xffff, 0, /* currently no capture, parse only token */ ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS}, /* %Es */ - {CTOKT_WIDE, CLF_LOCALSEC | CLF_SIGNED, 0, 1, 0xffff, TclOffset(DateInfo, date.localSeconds), + {CTOKT_WIDE, CLF_LOCALSEC | CLF_SIGNED, 0, 1, 0xffff, offsetof(DateInfo, date.localSeconds), NULL}, }; static const char *ScnETokenMapAliasIndex[2] = { @@ -2014,22 +2006,22 @@ static const char *ScnOTokenMapIndex = "dmyHMSu"; static ClockScanTokenMap ScnOTokenMap[] = { /* %Od %Oe */ - {CTOKT_PARSER, CLF_DAYOFMONTH, 0, 0, 0xffff, TclOffset(DateInfo, date.dayOfMonth), + {CTOKT_PARSER, CLF_DAYOFMONTH, 0, 0, 0xffff, offsetof(DateInfo, date.dayOfMonth), ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS}, /* %Om */ - {CTOKT_PARSER, CLF_MONTH, 0, 0, 0xffff, TclOffset(DateInfo, date.month), + {CTOKT_PARSER, CLF_MONTH, 0, 0, 0xffff, offsetof(DateInfo, date.month), ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS}, /* %Oy */ - {CTOKT_PARSER, CLF_YEAR, 0, 0, 0xffff, TclOffset(DateInfo, date.year), + {CTOKT_PARSER, CLF_YEAR, 0, 0, 0xffff, offsetof(DateInfo, date.year), ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS}, /* %OH %Ok %OI %Ol */ - {CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, TclOffset(DateInfo, date.hour), + {CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, offsetof(DateInfo, date.hour), ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS}, /* %OM */ - {CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, TclOffset(DateInfo, date.minutes), + {CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, offsetof(DateInfo, date.minutes), ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS}, /* %OS */ - {CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, TclOffset(DateInfo, date.secondOfMin), + {CTOKT_PARSER, CLF_TIME, 0, 0, 0xffff, offsetof(DateInfo, date.secondOfMin), ClockScnToken_LocaleListMatcher_Proc, (void *)MCLIT_LOCALE_NUMERALS}, /* %Ou Ow */ {CTOKT_PARSER, CLF_DAYOFWEEK, 0, 0, 0xffff, 0, @@ -2930,7 +2922,7 @@ ClockFmtToken_LocaleERAYear_Proc( ClockFormatToken *tok, int *val) { - int rowc; + Tcl_Size rowc; Tcl_Obj **rowv; if (dateFmt->localeEra == NULL) { @@ -3012,70 +3004,70 @@ static const char *FmtSTokenMapIndex = "demNbByYCHMSIklpaAuwUVzgGjJsntQ"; static ClockFormatTokenMap FmtSTokenMap[] = { /* %d */ - {CTOKT_INT, "0", 2, 0, 0, 0, TclOffset(DateFormat, date.dayOfMonth), NULL}, + {CTOKT_INT, "0", 2, 0, 0, 0, offsetof(DateFormat, date.dayOfMonth), NULL}, /* %e */ - {CTOKT_INT, " ", 2, 0, 0, 0, TclOffset(DateFormat, date.dayOfMonth), NULL}, + {CTOKT_INT, " ", 2, 0, 0, 0, offsetof(DateFormat, date.dayOfMonth), NULL}, /* %m */ - {CTOKT_INT, "0", 2, 0, 0, 0, TclOffset(DateFormat, date.month), NULL}, + {CTOKT_INT, "0", 2, 0, 0, 0, offsetof(DateFormat, date.month), NULL}, /* %N */ - {CTOKT_INT, " ", 2, 0, 0, 0, TclOffset(DateFormat, date.month), NULL}, + {CTOKT_INT, " ", 2, 0, 0, 0, offsetof(DateFormat, date.month), NULL}, /* %b %h */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX | CLFMT_DECR, 0, 12, TclOffset(DateFormat, date.month), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX | CLFMT_DECR, 0, 12, offsetof(DateFormat, date.month), NULL, (void *)MCLIT_MONTHS_ABBREV}, /* %B */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX | CLFMT_DECR, 0, 12, TclOffset(DateFormat, date.month), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX | CLFMT_DECR, 0, 12, offsetof(DateFormat, date.month), NULL, (void *)MCLIT_MONTHS_FULL}, /* %y */ - {CTOKT_INT, "0", 2, 0, 0, 100, TclOffset(DateFormat, date.year), NULL}, + {CTOKT_INT, "0", 2, 0, 0, 100, offsetof(DateFormat, date.year), NULL}, /* %Y */ - {CTOKT_INT, "0", 4, 0, 0, 0, TclOffset(DateFormat, date.year), NULL}, + {CTOKT_INT, "0", 4, 0, 0, 0, offsetof(DateFormat, date.year), NULL}, /* %C */ - {CTOKT_INT, "0", 2, 0, 100, 0, TclOffset(DateFormat, date.year), NULL}, + {CTOKT_INT, "0", 2, 0, 100, 0, offsetof(DateFormat, date.year), NULL}, /* %H */ - {CTOKT_INT, "0", 2, 0, 3600, 24, TclOffset(DateFormat, date.secondOfDay), NULL}, + {CTOKT_INT, "0", 2, 0, 3600, 24, offsetof(DateFormat, date.secondOfDay), NULL}, /* %M */ - {CTOKT_INT, "0", 2, 0, 60, 60, TclOffset(DateFormat, date.secondOfDay), NULL}, + {CTOKT_INT, "0", 2, 0, 60, 60, offsetof(DateFormat, date.secondOfDay), NULL}, /* %S */ - {CTOKT_INT, "0", 2, 0, 0, 60, TclOffset(DateFormat, date.secondOfDay), NULL}, + {CTOKT_INT, "0", 2, 0, 0, 60, offsetof(DateFormat, date.secondOfDay), NULL}, /* %I */ - {CTOKT_INT, "0", 2, CLFMT_CALC, 0, 0, TclOffset(DateFormat, date.secondOfDay), + {CTOKT_INT, "0", 2, CLFMT_CALC, 0, 0, offsetof(DateFormat, date.secondOfDay), ClockFmtToken_HourAMPM_Proc, NULL}, /* %k */ - {CTOKT_INT, " ", 2, 0, 3600, 24, TclOffset(DateFormat, date.secondOfDay), NULL}, + {CTOKT_INT, " ", 2, 0, 3600, 24, offsetof(DateFormat, date.secondOfDay), NULL}, /* %l */ - {CTOKT_INT, " ", 2, CLFMT_CALC, 0, 0, TclOffset(DateFormat, date.secondOfDay), + {CTOKT_INT, " ", 2, CLFMT_CALC, 0, 0, offsetof(DateFormat, date.secondOfDay), ClockFmtToken_HourAMPM_Proc, NULL}, /* %p %P */ - {CTOKT_INT, NULL, 0, 0, 0, 0, TclOffset(DateFormat, date.secondOfDay), + {CTOKT_INT, NULL, 0, 0, 0, 0, offsetof(DateFormat, date.secondOfDay), ClockFmtToken_AMPM_Proc, NULL}, /* %a */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, TclOffset(DateFormat, date.dayOfWeek), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, offsetof(DateFormat, date.dayOfWeek), NULL, (void *)MCLIT_DAYS_OF_WEEK_ABBREV}, /* %A */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, TclOffset(DateFormat, date.dayOfWeek), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, offsetof(DateFormat, date.dayOfWeek), NULL, (void *)MCLIT_DAYS_OF_WEEK_FULL}, /* %u */ - {CTOKT_INT, " ", 1, 0, 0, 0, TclOffset(DateFormat, date.dayOfWeek), NULL}, + {CTOKT_INT, " ", 1, 0, 0, 0, offsetof(DateFormat, date.dayOfWeek), NULL}, /* %w */ - {CTOKT_INT, " ", 1, 0, 0, 7, TclOffset(DateFormat, date.dayOfWeek), NULL}, + {CTOKT_INT, " ", 1, 0, 0, 7, offsetof(DateFormat, date.dayOfWeek), NULL}, /* %U %W */ - {CTOKT_INT, "0", 2, CLFMT_CALC, 0, 0, TclOffset(DateFormat, date.dayOfYear), + {CTOKT_INT, "0", 2, CLFMT_CALC, 0, 0, offsetof(DateFormat, date.dayOfYear), ClockFmtToken_WeekOfYear_Proc, NULL}, /* %V */ - {CTOKT_INT, "0", 2, 0, 0, 0, TclOffset(DateFormat, date.iso8601Week), NULL}, + {CTOKT_INT, "0", 2, 0, 0, 0, offsetof(DateFormat, date.iso8601Week), NULL}, /* %z %Z */ {CFMTT_PROC, NULL, 0, 0, 0, 0, 0, ClockFmtToken_TimeZone_Proc, NULL}, /* %g */ - {CTOKT_INT, "0", 2, 0, 0, 100, TclOffset(DateFormat, date.iso8601Year), NULL}, + {CTOKT_INT, "0", 2, 0, 0, 100, offsetof(DateFormat, date.iso8601Year), NULL}, /* %G */ - {CTOKT_INT, "0", 4, 0, 0, 0, TclOffset(DateFormat, date.iso8601Year), NULL}, + {CTOKT_INT, "0", 4, 0, 0, 0, offsetof(DateFormat, date.iso8601Year), NULL}, /* %j */ - {CTOKT_INT, "0", 3, 0, 0, 0, TclOffset(DateFormat, date.dayOfYear), NULL}, + {CTOKT_INT, "0", 3, 0, 0, 0, offsetof(DateFormat, date.dayOfYear), NULL}, /* %J */ - {CTOKT_WIDE, "0", 7, 0, 0, 0, TclOffset(DateFormat, date.julianDay), NULL}, + {CTOKT_WIDE, "0", 7, 0, 0, 0, offsetof(DateFormat, date.julianDay), NULL}, /* %s */ - {CTOKT_WIDE, "0", 1, 0, 0, 0, TclOffset(DateFormat, date.seconds), NULL}, + {CTOKT_WIDE, "0", 1, 0, 0, 0, offsetof(DateFormat, date.seconds), NULL}, /* %n */ {CTOKT_CHAR, "\n", 0, 0, 0, 0, 0, NULL}, /* %t */ @@ -3102,10 +3094,10 @@ static ClockFormatTokenMap FmtETokenMap[] = { {CFMTT_PROC, NULL, 0, 0, 0, 0, (SECONDS_PER_DAY/2), /* astro JDN starts at noon */ ClockFmtToken_JDN_Proc, NULL}, /* %Ey %EC */ - {CTOKT_INT, NULL, 0, 0, 0, 0, TclOffset(DateFormat, date.year), + {CTOKT_INT, NULL, 0, 0, 0, 0, offsetof(DateFormat, date.year), ClockFmtToken_LocaleERAYear_Proc, NULL}, /* %Es */ - {CTOKT_WIDE, "0", 1, 0, 0, 0, TclOffset(DateFormat, date.localSeconds), NULL}, + {CTOKT_WIDE, "0", 1, 0, 0, 0, offsetof(DateFormat, date.localSeconds), NULL}, }; static const char *FmtETokenMapAliasIndex[2] = { "C", @@ -3116,31 +3108,31 @@ static const char *FmtOTokenMapIndex = "dmyHIMSuw"; static ClockFormatTokenMap FmtOTokenMap[] = { /* %Od %Oe */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.dayOfMonth), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.dayOfMonth), NULL, (void *)MCLIT_LOCALE_NUMERALS}, /* %Om */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.month), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.month), NULL, (void *)MCLIT_LOCALE_NUMERALS}, /* %Oy */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.year), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.year), NULL, (void *)MCLIT_LOCALE_NUMERALS}, /* %OH %Ok */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 3600, 24, TclOffset(DateFormat, date.secondOfDay), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 3600, 24, offsetof(DateFormat, date.secondOfDay), NULL, (void *)MCLIT_LOCALE_NUMERALS}, /* %OI %Ol */ - {CTOKT_INT, NULL, 0, CLFMT_CALC | CLFMT_LOCALE_INDX, 0, 0, TclOffset(DateFormat, date.secondOfDay), + {CTOKT_INT, NULL, 0, CLFMT_CALC | CLFMT_LOCALE_INDX, 0, 0, offsetof(DateFormat, date.secondOfDay), ClockFmtToken_HourAMPM_Proc, (void *)MCLIT_LOCALE_NUMERALS}, /* %OM */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 60, 60, TclOffset(DateFormat, date.secondOfDay), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 60, 60, offsetof(DateFormat, date.secondOfDay), NULL, (void *)MCLIT_LOCALE_NUMERALS}, /* %OS */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 60, TclOffset(DateFormat, date.secondOfDay), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 60, offsetof(DateFormat, date.secondOfDay), NULL, (void *)MCLIT_LOCALE_NUMERALS}, /* %Ou */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.dayOfWeek), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, offsetof(DateFormat, date.dayOfWeek), NULL, (void *)MCLIT_LOCALE_NUMERALS}, /* %Ow */ - {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, TclOffset(DateFormat, date.dayOfWeek), + {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, offsetof(DateFormat, date.dayOfWeek), NULL, (void *)MCLIT_LOCALE_NUMERALS}, }; static const char *FmtOTokenMapAliasIndex[2] = { From 873097bf9f0748c04e0e1078f81d07c05593adcd Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 16:16:10 +0000 Subject: [PATCH 08/14] Workaround for missing tclEmptyStringRep --- generic/tclStrIdxTree.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/generic/tclStrIdxTree.c b/generic/tclStrIdxTree.c index 3ded291..6f6ed8b 100644 --- a/generic/tclStrIdxTree.c +++ b/generic/tclStrIdxTree.c @@ -400,6 +400,10 @@ StrIdxTreeObj_FreeIntRepProc(Tcl_Obj *objPtr) objPtr->typePtr = NULL; }; +#if TCL_MAJOR_VERSION == 9 +static char *tclEmptyStringRep = &tclEmptyString; +#endif + static void StrIdxTreeObj_UpdateStringProc(Tcl_Obj *objPtr) { From a83fa2e3d239d7e06a5e750c14cd7897d3429c23 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 16:19:41 +0000 Subject: [PATCH 09/14] TclUtfNext seems to be official; in Tcl9, so don't try and fake it. --- generic/tclClockModInt.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/generic/tclClockModInt.h b/generic/tclClockModInt.h index 82c252d..af72ae3 100644 --- a/generic/tclClockModInt.h +++ b/generic/tclClockModInt.h @@ -25,10 +25,12 @@ * several tclInt.h internals (tcl8.6 version depending): */ +#if TCL_MAJOR_VERSION < 9 #ifndef TclUtfNext #define TclUtfNext(src) \ ( (((unsigned char) *(src)) < 0xC0) ? src + 1 : Tcl_UtfNext(src) ) #endif +#endif /* * Signal using modified tcl version (dict smartref's, etc.) From 139bc78f56edcb54e8bd25cbba20f1a06c5c2e80 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 16:21:00 +0000 Subject: [PATCH 10/14] Another old-style function definition. --- generic/tclClockMod.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/generic/tclClockMod.c b/generic/tclClockMod.c index 9830188..53b9190 100644 --- a/generic/tclClockMod.c +++ b/generic/tclClockMod.c @@ -76,8 +76,7 @@ void _InitModTclInternals(Tcl_Interp *interp) { */ DLLEXPORT int -Tclclockmod_Init(interp) - Tcl_Interp *interp; /* The current Tcl interpreter */ +Tclclockmod_Init(Tcl_Interp *interp) { static int initialized = 0; From e3e719c067331462b52a6243047e9a1c29b3d74b Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 16:39:06 +0000 Subject: [PATCH 11/14] DOn't try and redefine TclUtfNext before includeing tclInt.h --- configure.ac | 2 ++ generic/tclClockMod.c | 1 + generic/tclClockModInt.c | 1 + generic/tclClockModInt.h | 11 ----------- generic/tclDate.h | 1 + generic/tclStrIdxTree.h | 1 + generic/tclUtfInt.h | 24 ++++++++++++++++++++++++ 7 files changed, 30 insertions(+), 11 deletions(-) create mode 100644 generic/tclUtfInt.h diff --git a/configure.ac b/configure.ac index 8f775ca..9dcfb6f 100644 --- a/configure.ac +++ b/configure.ac @@ -128,6 +128,8 @@ TEA_ADD_SOURCES([generic/tclClock.c \ #TEA_ADD_HEADERS([generic/tclDate.h \ # generic/tclStrIdxTree.h \ # generic/tclClockModInt.h \ +# generic/tclUtfInt.h \ +# generic/tclSize.h \ #]) #TEA_ADD_STUB_SOURCES([]) diff --git a/generic/tclClockMod.c b/generic/tclClockMod.c index 53b9190..72e861d 100644 --- a/generic/tclClockMod.c +++ b/generic/tclClockMod.c @@ -12,6 +12,7 @@ #include "tclClockModInt.h" #include "tcl.h" +#include "TclUtfInt.h" const Tcl_ObjType* tclIntTypePtr; const Tcl_ObjType* tclWideIntTypePtr; diff --git a/generic/tclClockModInt.c b/generic/tclClockModInt.c index 91c1f56..a2c8633 100644 --- a/generic/tclClockModInt.c +++ b/generic/tclClockModInt.c @@ -12,6 +12,7 @@ #include "tclClockModInt.h" #include "tclInt.h" +#include "TclUtfInt.h" CompileProc *_TclCompileBasicMin0ArgCmd; CompileProc *_TclCompileBasicMin1ArgCmd; diff --git a/generic/tclClockModInt.h b/generic/tclClockModInt.h index af72ae3..78c4432 100644 --- a/generic/tclClockModInt.h +++ b/generic/tclClockModInt.h @@ -21,17 +21,6 @@ # define inline __inline #endif -/* - * several tclInt.h internals (tcl8.6 version depending): - */ - -#if TCL_MAJOR_VERSION < 9 -#ifndef TclUtfNext -#define TclUtfNext(src) \ - ( (((unsigned char) *(src)) < 0xC0) ? src + 1 : Tcl_UtfNext(src) ) -#endif -#endif - /* * Signal using modified tcl version (dict smartref's, etc.) */ diff --git a/generic/tclDate.h b/generic/tclDate.h index aa07dd6..43cb194 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -15,6 +15,7 @@ /* Internals compatibilities (tclInt.h) - remove after merge to core */ #include "tclClockModInt.h" +#include "tclUtfInt.h" #if !TCL_AVAIL_SBMOD MODULE_SCOPE Tcl_Obj * Tcl_DictObjSmartRef(Tcl_Interp *interp, Tcl_Obj *dictPtr); #ifdef TclListObjGetElements diff --git a/generic/tclStrIdxTree.h b/generic/tclStrIdxTree.h index 1ec3799..3e6b1a1 100644 --- a/generic/tclStrIdxTree.h +++ b/generic/tclStrIdxTree.h @@ -14,6 +14,7 @@ #define _TCLSTRIDXTREE_H #include "tclClockModInt.h" +#include "tclUtfInt.h" /* * Main structures declarations of index tree and entry diff --git a/generic/tclUtfInt.h b/generic/tclUtfInt.h new file mode 100644 index 0000000..5fc7278 --- /dev/null +++ b/generic/tclUtfInt.h @@ -0,0 +1,24 @@ +/* + * tclUtfInt.h -- + * + * Internal declarations of fast tcl clock module. + * + * This needs to be after tclInt.h + * + * Copyright (c) 2017 Serg G. Brester (aka sebres) + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#ifndef _TCLUTFINT_H +#define _TCLUTFINT_H + +#if TCL_MAJOR_VERSION < 9 +#ifndef TclUtfNext +#define TclUtfNext(src) \ + ( (((unsigned char) *(src)) < 0xC0) ? src + 1 : Tcl_UtfNext(src) ) +#endif +#endif + +#endif /* _TCLUTFINT_H */ From f8c372af1ede9ad61f7581528013e4f42f9d1adc Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 16:43:11 +0000 Subject: [PATCH 12/14] Case typo --- generic/tclClockMod.c | 2 +- generic/tclClockModInt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/generic/tclClockMod.c b/generic/tclClockMod.c index 72e861d..c62d63c 100644 --- a/generic/tclClockMod.c +++ b/generic/tclClockMod.c @@ -12,7 +12,7 @@ #include "tclClockModInt.h" #include "tcl.h" -#include "TclUtfInt.h" +#include "tclUtfInt.h" const Tcl_ObjType* tclIntTypePtr; const Tcl_ObjType* tclWideIntTypePtr; diff --git a/generic/tclClockModInt.c b/generic/tclClockModInt.c index a2c8633..d00e818 100644 --- a/generic/tclClockModInt.c +++ b/generic/tclClockModInt.c @@ -12,7 +12,7 @@ #include "tclClockModInt.h" #include "tclInt.h" -#include "TclUtfInt.h" +#include "tclUtfInt.h" CompileProc *_TclCompileBasicMin0ArgCmd; CompileProc *_TclCompileBasicMin1ArgCmd; From fbcd1b3cb6fd75d5ca642bbd578a26d7d0ca8ddd Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 18:20:29 +0000 Subject: [PATCH 13/14] Change return from Tcl_HashKeyType member. --- generic/tclClockModInt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tclClockModInt.c b/generic/tclClockModInt.c index d00e818..a39ca3b 100644 --- a/generic/tclClockModInt.c +++ b/generic/tclClockModInt.c @@ -79,7 +79,7 @@ int Tcl_CatchObjCmd(ClientData dummy, Tcl_Interp *interp, /* Currently no external declaration for tclStringHashKeyType */ -static unsigned +static size_t HashStringKey( Tcl_HashTable *tablePtr, /* Hash table. */ void *keyPtr) /* Key from which to compute hash value. */ From 7a08deb4f389b5d8fe041d8d69c04214dec0aa78 Mon Sep 17 00:00:00 2001 From: Peter da Silva Date: Wed, 30 Sep 2026 18:24:13 +0000 Subject: [PATCH 14/14] They actually changed the return type for the hash key proc. --- generic/tclClockModInt.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/generic/tclClockModInt.c b/generic/tclClockModInt.c index a39ca3b..79eed53 100644 --- a/generic/tclClockModInt.c +++ b/generic/tclClockModInt.c @@ -79,7 +79,13 @@ int Tcl_CatchObjCmd(ClientData dummy, Tcl_Interp *interp, /* Currently no external declaration for tclStringHashKeyType */ -static size_t +#if TCL_MAJOR_VERSION >= 9 +#define HASHKEYRETURNTYPE size_t +#else +#define HASHKEYRETURNTYPE unsigned +#endif + +static HASHKEYRETURNTYPE HashStringKey( Tcl_HashTable *tablePtr, /* Hash table. */ void *keyPtr) /* Key from which to compute hash value. */