Skip to content

Commit 4ca6172

Browse files
author
jan.nijtmans
committed
Update Tcl_Time for 32-bit systems and win64, being able to handle time > 2038. Suggested in in ticket [86dd172271]
1 parent 4a4195d commit 4ca6172

File tree

8 files changed

+38
-30
lines changed

8 files changed

+38
-30
lines changed

generic/tcl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,8 +1295,16 @@ typedef enum {
12951295
*/
12961296

12971297
typedef struct Tcl_Time {
1298+
#if TCL_MAJOR_VERSION > 8
1299+
long long sec; /* Seconds. */
1300+
#else
12981301
long sec; /* Seconds. */
1302+
#endif
1303+
#if defined(_WIN32) && TCL_MAJOR_VERSION > 8
1304+
long long usec; /* Microseconds. */
1305+
#else
12991306
long usec; /* Microseconds. */
1307+
#endif
13001308
} Tcl_Time;
13011309

13021310
typedef void (Tcl_SetTimerProc) (const Tcl_Time *timePtr);

generic/tclClock.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1761,7 +1761,7 @@ ClockClicksObjCmd(
17611761
switch (index) {
17621762
case CLICKS_MILLIS:
17631763
Tcl_GetTime(&now);
1764-
clicks = (Tcl_WideInt)(unsigned long)now.sec * 1000 + now.usec / 1000;
1764+
clicks = (Tcl_WideInt)(unsigned long long)now.sec * 1000 + now.usec / 1000;
17651765
break;
17661766
case CLICKS_NATIVE:
17671767
#ifdef TCL_WIDE_CLICKS
@@ -2039,7 +2039,7 @@ TzsetIfNecessary(void)
20392039
{
20402040
static WCHAR* tzWas = (WCHAR *)INT2PTR(-1); /* Previous value of TZ, protected by
20412041
* clockMutex. */
2042-
static long tzLastRefresh = 0; /* Used for latency before next refresh */
2042+
static long long tzLastRefresh = 0; /* Used for latency before next refresh */
20432043
static size_t tzEnvEpoch = 0; /* Last env epoch, for faster signaling,
20442044
that TZ changed via TCL */
20452045
const WCHAR *tzIsNow; /* Current value of TZ */

generic/tclDecls.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3975,9 +3975,9 @@ extern const TclStubs *tclStubsPtr;
39753975
TCL_ENCODING_PROFILE_TCL8, (ds), NULL), Tcl_DStringValue(ds))
39763976

39773977
#if defined(USE_TCL_STUBS)
3978-
# if defined(_WIN32) && defined(_WIN64)
3978+
# if defined(_WIN32) && defined(_WIN64) && TCL_MAJOR_VERSION < 9
39793979
# undef Tcl_GetTime
3980-
/* Handle Win64 tk.dll being loaded in Cygwin64. */
3980+
/* Handle Win64 tk.dll being loaded in Cygwin64 (only needed for Tcl 8). */
39813981
# define Tcl_GetTime(t) \
39823982
do { \
39833983
struct { \

generic/tclInterp.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4831,14 +4831,14 @@ ChildTimeLimitCmd(
48314831
if (TclGetWideIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
48324832
return TCL_ERROR;
48334833
}
4834-
if (tmp < 0 || tmp > LONG_MAX) {
4835-
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
4836-
"milliseconds must be between 0 and %ld", LONG_MAX));
4834+
if (tmp < 0) {
4835+
Tcl_SetObjResult(interp, Tcl_NewStringObj(
4836+
"milliseconds must be non-negative", -1));
48374837
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
48384838
"BADVALUE", NULL);
48394839
return TCL_ERROR;
48404840
}
4841-
limitMoment.usec = ((long)tmp)*1000;
4841+
limitMoment.usec = tmp*1000;
48424842
break;
48434843
case OPT_SEC:
48444844
secObj = objv[i+1];
@@ -4849,14 +4849,14 @@ ChildTimeLimitCmd(
48494849
if (TclGetWideIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
48504850
return TCL_ERROR;
48514851
}
4852-
if (tmp < 0 || tmp > LONG_MAX) {
4853-
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
4854-
"seconds must be between 0 and %ld", LONG_MAX));
4852+
if (tmp < 0) {
4853+
Tcl_SetObjResult(interp, Tcl_NewStringObj(
4854+
"seconds must be non-negative", -1));
48554855
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
48564856
"BADVALUE", NULL);
48574857
return TCL_ERROR;
48584858
}
4859-
limitMoment.sec = (long)tmp;
4859+
limitMoment.sec = (long long)tmp;
48604860
break;
48614861
}
48624862
}

generic/tclTimer.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,19 +117,19 @@ static Tcl_ThreadDataKey dataKey;
117117
* side-effect free. The "prototypes" for these macros are:
118118
*
119119
* static int TCL_TIME_BEFORE(Tcl_Time t1, Tcl_Time t2);
120-
* static long TCL_TIME_DIFF_MS(Tcl_Time t1, Tcl_Time t2);
120+
* static Tcl_WideInt TCL_TIME_DIFF_MS(Tcl_Time t1, Tcl_Time t2);
121121
*/
122122

123123
#define TCL_TIME_BEFORE(t1, t2) \
124124
(((t1).sec<(t2).sec) || ((t1).sec==(t2).sec && (t1).usec<(t2).usec))
125125

126126
#define TCL_TIME_DIFF_MS(t1, t2) \
127127
(1000*((Tcl_WideInt)(t1).sec - (Tcl_WideInt)(t2).sec) + \
128-
((long)(t1).usec - (long)(t2).usec)/1000)
128+
((t1).usec - (t2).usec)/1000)
129129

130130
#define TCL_TIME_DIFF_MS_CEILING(t1, t2) \
131131
(1000*((Tcl_WideInt)(t1).sec - (Tcl_WideInt)(t2).sec) + \
132-
((long)(t1).usec - (long)(t2).usec + 999)/1000)
132+
((t1).usec - (t2).usec + 999)/1000)
133133

134134
/*
135135
* Sleeps under that number of milliseconds don't get double-checked
@@ -866,8 +866,8 @@ Tcl_AfterObjCmd(
866866
afterPtr->id = tsdPtr->afterId;
867867
tsdPtr->afterId += 1;
868868
Tcl_GetTime(&wakeup);
869-
wakeup.sec += (long)(ms / 1000);
870-
wakeup.usec += ((long)(ms % 1000)) * 1000;
869+
wakeup.sec += ms / 1000;
870+
wakeup.usec += ms % 1000 * 1000;
871871
if (wakeup.usec > 1000000) {
872872
wakeup.sec++;
873873
wakeup.usec -= 1000000;
@@ -1014,8 +1014,8 @@ AfterDelay(
10141014

10151015
Tcl_GetTime(&now);
10161016
endTime = now;
1017-
endTime.sec += (long)(ms / 1000);
1018-
endTime.usec += ((int)(ms % 1000)) * 1000;
1017+
endTime.sec += (ms / 1000);
1018+
endTime.usec += (ms % 1000) * 1000;
10191019
if (endTime.usec >= 1000000) {
10201020
endTime.sec++;
10211021
endTime.usec -= 1000000;
@@ -1047,7 +1047,7 @@ AfterDelay(
10471047
diff = 1;
10481048
}
10491049
if (diff > 0) {
1050-
Tcl_Sleep((long) diff);
1050+
Tcl_Sleep((int) diff);
10511051
if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) {
10521052
break;
10531053
}

tests/interp.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3524,7 +3524,7 @@ test interp-35.19 {interp limit syntax} -body {
35243524
interp limit $i time -seconds -1
35253525
} -cleanup {
35263526
interp delete $i
3527-
} -match glob -returnCodes error -result {seconds must be between 0 and *}
3527+
} -returnCodes error -result {seconds must be non-negative}
35283528
test interp-35.20 {interp limit syntax} -body {
35293529
set i [interp create]
35303530
interp limit $i time -millis foobar
@@ -3536,7 +3536,7 @@ test interp-35.21 {interp limit syntax} -body {
35363536
interp limit $i time -millis -1
35373537
} -cleanup {
35383538
interp delete $i
3539-
} -match glob -returnCodes error -result {milliseconds must be between 0 and *}
3539+
} -returnCodes error -result {milliseconds must be non-negative}
35403540
test interp-35.22 {interp time limits normalize milliseconds} -body {
35413541
set i [interp create]
35423542
interp limit $i time -seconds 1 -millis 1500

unix/tclUnixTime.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ TclpGetMicroseconds(void)
9595
Tcl_Time time;
9696

9797
GetTime(&time);
98-
return ((long long)(unsigned long) time.sec)*1000000 + time.usec;
98+
return time.sec * 1000000 + time.usec;
9999
}
100100

101101
/*

win/tclWinTime.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ TclpGetSeconds(void)
178178
Tcl_Time t;
179179

180180
GetTime(&t);
181-
return (unsigned long long)(unsigned long) t.sec;
181+
return (unsigned long long)t.sec;
182182
}
183183
}
184184

@@ -347,7 +347,7 @@ TclpGetMicroseconds(void)
347347
Tcl_Time now;
348348

349349
GetTime(&now);
350-
return (((long long) now.sec) * 1000000) + now.usec;
350+
return now.sec * 1000000 + now.usec;
351351
}
352352
}
353353

@@ -384,8 +384,8 @@ Tcl_GetTime(
384384
*/
385385

386386
if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) {
387-
timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
388-
timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
387+
timePtr->sec = usecSincePosixEpoch / 1000000;
388+
timePtr->usec = usecSincePosixEpoch % 1000000;
389389
} else {
390390
GetTime(timePtr);
391391
}
@@ -687,8 +687,8 @@ NativeGetTime(
687687

688688
usecSincePosixEpoch = NativeGetMicroseconds();
689689
if (usecSincePosixEpoch) {
690-
timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
691-
timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
690+
timePtr->sec = usecSincePosixEpoch / 1000000;
691+
timePtr->usec = usecSincePosixEpoch % 1000000;
692692
} else {
693693
/*
694694
* High resolution timer is not available. Just use ftime.
@@ -697,7 +697,7 @@ NativeGetTime(
697697
struct _timeb t;
698698

699699
_ftime(&t);
700-
timePtr->sec = (long) t.time;
700+
timePtr->sec = t.time;
701701
timePtr->usec = t.millitm * 1000;
702702
}
703703
}

0 commit comments

Comments
 (0)