summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2017-08-08 15:19:18 (GMT)
committersebres <sebres@users.sourceforge.net>2017-08-08 15:19:18 (GMT)
commit2f83828bcb5e15404b8100819f53a773804804bb (patch)
tree0eb46afcc195f1671bf2a81a463b77a469102418
parent94b19268b0430493dac73eeebf249eb4b7aeeacd (diff)
downloadtcl-sebres_8_6_clock_speedup_cr1.zip
tcl-sebres_8_6_clock_speedup_cr1.tar.gz
tcl-sebres_8_6_clock_speedup_cr1.tar.bz2
fixed overflow of year (resp. julianday), closes ticket [16e4fc3096]; test cases adjusted.sebres_8_6_clock_speedup_cr1
-rw-r--r--generic/tclClock.c46
-rw-r--r--generic/tclClockFmt.c130
-rw-r--r--generic/tclDate.h6
-rw-r--r--tests/clock.test19
4 files changed, 108 insertions, 93 deletions
diff --git a/generic/tclClock.c b/generic/tclClock.c
index dc82065..e4921ae 100644
--- a/generic/tclClock.c
+++ b/generic/tclClock.c
@@ -88,7 +88,7 @@ static int ClockConfigureObjCmd(ClientData clientData,
static void GetYearWeekDay(TclDateFields *, int);
static void GetGregorianEraYearDay(TclDateFields *, int);
static void GetMonthDay(TclDateFields *);
-static int WeekdayOnOrBefore(int, int);
+static Tcl_WideInt WeekdayOnOrBefore(int, Tcl_WideInt);
static int ClockClicksObjCmd(
ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
@@ -1543,8 +1543,8 @@ ClockGetDateFields(
* Extract Julian day.
*/
- fields->julianDay = (int) ((fields->localSeconds + JULIAN_SEC_POSIX_EPOCH)
- / SECONDS_PER_DAY);
+ fields->julianDay = (fields->localSeconds + JULIAN_SEC_POSIX_EPOCH)
+ / SECONDS_PER_DAY;
/*
* Convert to Julian or Gregorian calendar.
@@ -2031,7 +2031,7 @@ ConvertLocalToUTCUsingC(
*/
jsec = fields->localSeconds + JULIAN_SEC_POSIX_EPOCH;
- fields->julianDay = (int) (jsec / SECONDS_PER_DAY);
+ fields->julianDay = (jsec / SECONDS_PER_DAY);
secondOfDay = (int)(jsec % SECONDS_PER_DAY);
if (secondOfDay < 0) {
secondOfDay += SECONDS_PER_DAY;
@@ -2493,10 +2493,10 @@ GetGregorianEraYearDay(
TclDateFields *fields, /* Date fields containing 'julianDay' */
int changeover) /* Gregorian transition date */
{
- int jday = fields->julianDay;
- int day;
- int year;
- int n;
+ Tcl_WideInt jday = fields->julianDay;
+ Tcl_WideInt year;
+ Tcl_WideInt day;
+ Tcl_WideInt n;
if (jday >= changeover) {
/*
@@ -2580,12 +2580,12 @@ GetGregorianEraYearDay(
if (year <= 0) {
fields->era = BCE;
- fields->year = 1 - year;
+ fields->year = 1 - (int)year;
} else {
fields->era = CE;
- fields->year = year;
+ fields->year = (int)year;
}
- fields->dayOfYear = day + 1;
+ fields->dayOfYear = (int)(day + 1);
}
/*
@@ -2642,7 +2642,7 @@ GetJulianDayFromEraYearWeekDay(
int changeover) /* Julian Day Number of the Gregorian
* transition */
{
- int firstMonday; /* Julian day number of week 1, day 1 in the
+ Tcl_WideInt firstMonday; /* Julian day number of week 1, day 1 in the
* given year */
TclDateFields firstWeek;
@@ -2694,7 +2694,8 @@ GetJulianDayFromEraYearMonthDay(
TclDateFields *fields, /* Date to convert */
int changeover) /* Gregorian transition date as a Julian Day */
{
- int year, ym1, month, mm1, q, r, ym1o4, ym1o100, ym1o400;
+ Tcl_WideInt year, ym1, ym1o4, ym1o100, ym1o400;
+ int month, mm1, q, r;
if (fields->era == BCE) {
year = 1 - fields->year;
@@ -2805,7 +2806,7 @@ GetJulianDayFromEraYearDay(
TclDateFields *fields, /* Date to convert */
int changeover) /* Gregorian transition date as a Julian Day */
{
- int year, ym1;
+ Tcl_WideInt year, ym1;
/* Get absolute year number from the civil year */
if (fields->era == BCE) {
@@ -2855,7 +2856,7 @@ int
IsGregorianLeapYear(
TclDateFields *fields) /* Date to test */
{
- int year = fields->year;
+ Tcl_WideInt year = fields->year;
if (fields->era == BCE) {
year = 1 - year;
@@ -2887,10 +2888,10 @@ IsGregorianLeapYear(
*----------------------------------------------------------------------
*/
-static int
+static Tcl_WideInt
WeekdayOnOrBefore(
int dayOfWeek, /* Day of week; Sunday == 0 or 7 */
- int julianDay) /* Reference date */
+ Tcl_WideInt julianDay) /* Reference date */
{
int k = (dayOfWeek + 6) % 7;
if (k < 0) {
@@ -3308,11 +3309,16 @@ ClockParseFmtScnArgs(
goto badOption;
}
/*
- * seconds could be an unsigned number that overflowed. Make sure
- * that it isn't.
+ * Seconds could be an unsigned number that overflowed. Make sure
+ * that it isn't. Additionally it may be too complex to calculate
+ * julianday etc (forwards/backwards) by too large/small values, thus
+ * just let accept a bit shorter values to avoid overflow.
+ * Note the year is currently an integer, thus avoid to overflow it also.
*/
- if (baseObj->typePtr == &tclBignumType) {
+ if ( baseObj->typePtr == &tclBignumType
+ || baseVal < -0x00F0000000000000L || baseVal > 0x00F0000000000000L
+ ) {
Tcl_SetObjResult(interp, dataPtr->literals[LIT_INTEGER_VALUE_TOO_LARGE]);
return TCL_ERROR;
}
diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c
index 7213937..d68f819 100644
--- a/generic/tclClockFmt.c
+++ b/generic/tclClockFmt.c
@@ -904,7 +904,8 @@ FindTokenBegin(
if (p < end) {
/* next token a known token type */
switch (tok->map->type) {
- case CTOKT_DIGIT:
+ case CTOKT_INT:
+ case CTOKT_WIDE:
/* should match at least one digit */
while (!isdigit(UCHAR(*p)) && (p = TclUtfNext(p)) < end) {};
return p;
@@ -982,7 +983,7 @@ DetermineGreedySearchLen(ClockFmtScnCmdArgs *opts,
}
/* check digits rigth now */
- if (tok->map->type == CTOKT_DIGIT) {
+ if (tok->map->type == CTOKT_INT || tok->map->type == CTOKT_WIDE) {
p = yyInput;
end = p + maxLen;
if (end > info->dateEnd) { end = info->dateEnd; };
@@ -1734,7 +1735,7 @@ ClockScnToken_StarDate_Proc(ClockFmtScnCmdArgs *opts,
yydate.localSeconds =
-210866803200L
- + ( SECONDS_PER_DAY * (Tcl_WideInt)yydate.julianDay )
+ + ( SECONDS_PER_DAY * yydate.julianDay )
+ ( SECONDS_PER_DAY * fractDay / fractDayDiv );
return TCL_OK;
@@ -1744,49 +1745,49 @@ static const char *ScnSTokenMapIndex =
"dmbyYHMSpJjCgGVazUsntQ";
static ClockScanTokenMap ScnSTokenMap[] = {
/* %d %e */
- {CTOKT_DIGIT, CLF_DAYOFMONTH, 0, 1, 2, TclOffset(DateInfo, date.dayOfMonth),
+ {CTOKT_INT, CLF_DAYOFMONTH, 0, 1, 2, TclOffset(DateInfo, date.dayOfMonth),
NULL},
/* %m %N */
- {CTOKT_DIGIT, CLF_MONTH, 0, 1, 2, TclOffset(DateInfo, date.month),
+ {CTOKT_INT, CLF_MONTH, 0, 1, 2, TclOffset(DateInfo, date.month),
NULL},
/* %b %B %h */
{CTOKT_PARSER, CLF_MONTH, 0, 0, 0xffff, 0,
ClockScnToken_Month_Proc},
/* %y */
- {CTOKT_DIGIT, CLF_YEAR, 0, 1, 2, TclOffset(DateInfo, date.year),
+ {CTOKT_INT, CLF_YEAR, 0, 1, 2, TclOffset(DateInfo, date.year),
NULL},
/* %Y */
- {CTOKT_DIGIT, CLF_YEAR | CLF_CENTURY, 0, 4, 4, TclOffset(DateInfo, date.year),
+ {CTOKT_INT, CLF_YEAR | CLF_CENTURY, 0, 4, 4, TclOffset(DateInfo, date.year),
NULL},
/* %H %k %I %l */
- {CTOKT_DIGIT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.hour),
+ {CTOKT_INT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.hour),
NULL},
/* %M */
- {CTOKT_DIGIT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.minutes),
+ {CTOKT_INT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.minutes),
NULL},
/* %S */
- {CTOKT_DIGIT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.secondOfDay),
+ {CTOKT_INT, CLF_TIME, 0, 1, 2, TclOffset(DateInfo, date.secondOfDay),
NULL},
/* %p %P */
{CTOKT_PARSER, CLF_ISO8601, 0, 0, 0xffff, 0,
ClockScnToken_amPmInd_Proc, NULL},
/* %J */
- {CTOKT_DIGIT, CLF_JULIANDAY, 0, 1, 0xffff, TclOffset(DateInfo, date.julianDay),
+ {CTOKT_WIDE, CLF_JULIANDAY, 0, 1, 0xffff, TclOffset(DateInfo, date.julianDay),
NULL},
/* %j */
- {CTOKT_DIGIT, CLF_DAYOFYEAR, 0, 1, 3, TclOffset(DateInfo, date.dayOfYear),
+ {CTOKT_INT, CLF_DAYOFYEAR, 0, 1, 3, TclOffset(DateInfo, date.dayOfYear),
NULL},
/* %C */
- {CTOKT_DIGIT, CLF_CENTURY|CLF_ISO8601CENTURY, 0, 1, 2, TclOffset(DateInfo, dateCentury),
+ {CTOKT_INT, CLF_CENTURY|CLF_ISO8601CENTURY, 0, 1, 2, TclOffset(DateInfo, dateCentury),
NULL},
/* %g */
- {CTOKT_DIGIT, CLF_ISO8601YEAR | CLF_ISO8601, 0, 2, 2, TclOffset(DateInfo, date.iso8601Year),
+ {CTOKT_INT, CLF_ISO8601YEAR | CLF_ISO8601, 0, 2, 2, TclOffset(DateInfo, date.iso8601Year),
NULL},
/* %G */
- {CTOKT_DIGIT, CLF_ISO8601YEAR | CLF_ISO8601 | CLF_ISO8601CENTURY, 0, 4, 4, TclOffset(DateInfo, date.iso8601Year),
+ {CTOKT_INT, CLF_ISO8601YEAR | CLF_ISO8601 | CLF_ISO8601CENTURY, 0, 4, 4, TclOffset(DateInfo, date.iso8601Year),
NULL},
/* %V */
- {CTOKT_DIGIT, CLF_ISO8601, 0, 1, 2, TclOffset(DateInfo, date.iso8601Week),
+ {CTOKT_INT, CLF_ISO8601, 0, 1, 2, TclOffset(DateInfo, date.iso8601Week),
NULL},
/* %a %A %u %w */
{CTOKT_PARSER, CLF_ISO8601, 0, 0, 0xffff, 0,
@@ -1795,10 +1796,10 @@ static ClockScanTokenMap ScnSTokenMap[] = {
{CTOKT_PARSER, CLF_OPTIONAL, 0, 0, 0xffff, 0,
ClockScnToken_TimeZone_Proc, NULL},
/* %U %W */
- {CTOKT_DIGIT, CLF_OPTIONAL, 0, 1, 2, 0, /* currently no capture, parse only token */
+ {CTOKT_INT, CLF_OPTIONAL, 0, 1, 2, 0, /* currently no capture, parse only token */
NULL},
/* %s */
- {CTOKT_DIGIT, CLF_POSIXSEC | CLF_SIGNED, 0, 1, 0xffff, TclOffset(DateInfo, date.seconds),
+ {CTOKT_WIDE, CLF_POSIXSEC | CLF_SIGNED, 0, 1, 0xffff, TclOffset(DateInfo, date.seconds),
NULL},
/* %n */
{CTOKT_CHAR, 0, 0, 1, 1, 0, NULL, "\n"},
@@ -1823,7 +1824,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_DIGIT, CLF_LOCALSEC | CLF_SIGNED, 0, 1, 0xffff, TclOffset(DateInfo, date.localSeconds),
+ {CTOKT_WIDE, CLF_LOCALSEC | CLF_SIGNED, 0, 1, 0xffff, TclOffset(DateInfo, date.localSeconds),
NULL},
};
static const char *ScnETokenMapAliasIndex[2] = {
@@ -2182,7 +2183,8 @@ ClockScan(
}
switch (map->type)
{
- case CTOKT_DIGIT:
+ case CTOKT_INT:
+ case CTOKT_WIDE:
if (1) {
int minLen, size;
int sign = 1;
@@ -2204,7 +2206,7 @@ ClockScan(
/* string 2 number, put number into info structure by offset */
if (map->offs) {
p = yyInput; x = p + size;
- if (!(map->flags & (CLF_LOCALSEC|CLF_POSIXSEC))) {
+ if (map->type == CTOKT_INT) {
if (_str2int((int *)(((char *)info) + map->offs),
p, x, sign) != TCL_OK) {
goto overflow;
@@ -2685,76 +2687,76 @@ static const char *FmtSTokenMapIndex =
"demNbByYCHMSIklpaAuwUVzgGjJsntQ";
static ClockFormatTokenMap FmtSTokenMap[] = {
/* %d */
- {CFMTT_INT, "0", 2, 0, 0, 0, TclOffset(DateFormat, date.dayOfMonth), NULL},
+ {CTOKT_INT, "0", 2, 0, 0, 0, TclOffset(DateFormat, date.dayOfMonth), NULL},
/* %e */
- {CFMTT_INT, " ", 2, 0, 0, 0, TclOffset(DateFormat, date.dayOfMonth), NULL},
+ {CTOKT_INT, " ", 2, 0, 0, 0, TclOffset(DateFormat, date.dayOfMonth), NULL},
/* %m */
- {CFMTT_INT, "0", 2, 0, 0, 0, TclOffset(DateFormat, date.month), NULL},
+ {CTOKT_INT, "0", 2, 0, 0, 0, TclOffset(DateFormat, date.month), NULL},
/* %N */
- {CFMTT_INT, " ", 2, 0, 0, 0, TclOffset(DateFormat, date.month), NULL},
+ {CTOKT_INT, " ", 2, 0, 0, 0, TclOffset(DateFormat, date.month), NULL},
/* %b %h */
- {CFMTT_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, TclOffset(DateFormat, date.month),
NULL, (void *)MCLIT_MONTHS_ABBREV},
/* %B */
- {CFMTT_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, TclOffset(DateFormat, date.month),
NULL, (void *)MCLIT_MONTHS_FULL},
/* %y */
- {CFMTT_INT, "0", 2, 0, 0, 100, TclOffset(DateFormat, date.year), NULL},
+ {CTOKT_INT, "0", 2, 0, 0, 100, TclOffset(DateFormat, date.year), NULL},
/* %Y */
- {CFMTT_INT, "0", 4, 0, 0, 0, TclOffset(DateFormat, date.year), NULL},
+ {CTOKT_INT, "0", 4, 0, 0, 0, TclOffset(DateFormat, date.year), NULL},
/* %C */
- {CFMTT_INT, "0", 2, 0, 100, 0, TclOffset(DateFormat, date.year), NULL},
+ {CTOKT_INT, "0", 2, 0, 100, 0, TclOffset(DateFormat, date.year), NULL},
/* %H */
- {CFMTT_INT, "0", 2, 0, 3600, 24, TclOffset(DateFormat, date.secondOfDay), NULL},
+ {CTOKT_INT, "0", 2, 0, 3600, 24, TclOffset(DateFormat, date.secondOfDay), NULL},
/* %M */
- {CFMTT_INT, "0", 2, 0, 60, 60, TclOffset(DateFormat, date.secondOfDay), NULL},
+ {CTOKT_INT, "0", 2, 0, 60, 60, TclOffset(DateFormat, date.secondOfDay), NULL},
/* %S */
- {CFMTT_INT, "0", 2, 0, 0, 60, TclOffset(DateFormat, date.secondOfDay), NULL},
+ {CTOKT_INT, "0", 2, 0, 0, 60, TclOffset(DateFormat, date.secondOfDay), NULL},
/* %I */
- {CFMTT_INT, "0", 2, CLFMT_CALC, 0, 0, TclOffset(DateFormat, date.secondOfDay),
+ {CTOKT_INT, "0", 2, CLFMT_CALC, 0, 0, TclOffset(DateFormat, date.secondOfDay),
ClockFmtToken_HourAMPM_Proc, NULL},
/* %k */
- {CFMTT_INT, " ", 2, 0, 3600, 24, TclOffset(DateFormat, date.secondOfDay), NULL},
+ {CTOKT_INT, " ", 2, 0, 3600, 24, TclOffset(DateFormat, date.secondOfDay), NULL},
/* %l */
- {CFMTT_INT, " ", 2, CLFMT_CALC, 0, 0, TclOffset(DateFormat, date.secondOfDay),
+ {CTOKT_INT, " ", 2, CLFMT_CALC, 0, 0, TclOffset(DateFormat, date.secondOfDay),
ClockFmtToken_HourAMPM_Proc, NULL},
/* %p %P */
- {CFMTT_INT, NULL, 0, 0, 0, 0, TclOffset(DateFormat, date.secondOfDay),
+ {CTOKT_INT, NULL, 0, 0, 0, 0, TclOffset(DateFormat, date.secondOfDay),
ClockFmtToken_AMPM_Proc, NULL},
/* %a */
- {CFMTT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, TclOffset(DateFormat, date.dayOfWeek),
+ {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, TclOffset(DateFormat, date.dayOfWeek),
NULL, (void *)MCLIT_DAYS_OF_WEEK_ABBREV},
/* %A */
- {CFMTT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, TclOffset(DateFormat, date.dayOfWeek),
+ {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, TclOffset(DateFormat, date.dayOfWeek),
NULL, (void *)MCLIT_DAYS_OF_WEEK_FULL},
/* %u */
- {CFMTT_INT, " ", 1, 0, 0, 0, TclOffset(DateFormat, date.dayOfWeek), NULL},
+ {CTOKT_INT, " ", 1, 0, 0, 0, TclOffset(DateFormat, date.dayOfWeek), NULL},
/* %w */
- {CFMTT_INT, " ", 1, 0, 0, 7, TclOffset(DateFormat, date.dayOfWeek), NULL},
+ {CTOKT_INT, " ", 1, 0, 0, 7, TclOffset(DateFormat, date.dayOfWeek), NULL},
/* %U %W */
- {CFMTT_INT, "0", 2, CLFMT_CALC, 0, 0, TclOffset(DateFormat, date.dayOfYear),
+ {CTOKT_INT, "0", 2, CLFMT_CALC, 0, 0, TclOffset(DateFormat, date.dayOfYear),
ClockFmtToken_WeekOfYear_Proc, NULL},
/* %V */
- {CFMTT_INT, "0", 2, 0, 0, 0, TclOffset(DateFormat, date.iso8601Week), NULL},
+ {CTOKT_INT, "0", 2, 0, 0, 0, TclOffset(DateFormat, date.iso8601Week), NULL},
/* %z %Z */
- {CFMTT_INT, NULL, 0, 0, 0, 0, 0,
+ {CTOKT_INT, NULL, 0, 0, 0, 0, 0,
ClockFmtToken_TimeZone_Proc, NULL},
/* %g */
- {CFMTT_INT, "0", 2, 0, 0, 100, TclOffset(DateFormat, date.iso8601Year), NULL},
+ {CTOKT_INT, "0", 2, 0, 0, 100, TclOffset(DateFormat, date.iso8601Year), NULL},
/* %G */
- {CFMTT_INT, "0", 4, 0, 0, 0, TclOffset(DateFormat, date.iso8601Year), NULL},
+ {CTOKT_INT, "0", 4, 0, 0, 0, TclOffset(DateFormat, date.iso8601Year), NULL},
/* %j */
- {CFMTT_INT, "0", 3, 0, 0, 0, TclOffset(DateFormat, date.dayOfYear), NULL},
+ {CTOKT_INT, "0", 3, 0, 0, 0, TclOffset(DateFormat, date.dayOfYear), NULL},
/* %J */
- {CFMTT_INT, "0", 7, 0, 0, 0, TclOffset(DateFormat, date.julianDay), NULL},
+ {CTOKT_WIDE, "0", 1, 0, 0, 0, TclOffset(DateFormat, date.julianDay), NULL},
/* %s */
- {CFMTT_WIDE, "0", 1, 0, 0, 0, TclOffset(DateFormat, date.seconds), NULL},
+ {CTOKT_WIDE, "0", 1, 0, 0, 0, TclOffset(DateFormat, date.seconds), NULL},
/* %n */
{CTOKT_CHAR, "\n", 0, 0, 0, 0, 0, NULL},
/* %t */
{CTOKT_CHAR, "\t", 0, 0, 0, 0, 0, NULL},
/* %Q */
- {CFMTT_INT, NULL, 0, 0, 0, 0, 0,
+ {CTOKT_INT, NULL, 0, 0, 0, 0, 0,
ClockFmtToken_StarDate_Proc, NULL},
};
static const char *FmtSTokenMapAliasIndex[2] = {
@@ -2766,13 +2768,13 @@ static const char *FmtETokenMapIndex =
"Eys";
static ClockFormatTokenMap FmtETokenMap[] = {
/* %EE */
- {CFMTT_INT, NULL, 0, 0, 0, 0, TclOffset(DateFormat, date.era),
+ {CTOKT_INT, NULL, 0, 0, 0, 0, TclOffset(DateFormat, date.era),
ClockFmtToken_LocaleERA_Proc, NULL},
/* %Ey %EC */
- {CFMTT_INT, NULL, 0, 0, 0, 0, TclOffset(DateFormat, date.year),
+ {CTOKT_INT, NULL, 0, 0, 0, 0, TclOffset(DateFormat, date.year),
ClockFmtToken_LocaleERAYear_Proc, NULL},
/* %Es */
- {CFMTT_WIDE, "0", 1, 0, 0, 0, TclOffset(DateFormat, date.localSeconds), NULL},
+ {CTOKT_WIDE, "0", 1, 0, 0, 0, TclOffset(DateFormat, date.localSeconds), NULL},
};
static const char *FmtETokenMapAliasIndex[2] = {
"C",
@@ -2783,31 +2785,31 @@ static const char *FmtOTokenMapIndex =
"dmyHIMSuw";
static ClockFormatTokenMap FmtOTokenMap[] = {
/* %Od %Oe */
- {CFMTT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.dayOfMonth),
+ {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.dayOfMonth),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %Om */
- {CFMTT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.month),
+ {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.month),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %Oy */
- {CFMTT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.year),
+ {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.year),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %OH %Ok */
- {CFMTT_INT, NULL, 0, CLFMT_LOCALE_INDX, 3600, 24, TclOffset(DateFormat, date.secondOfDay),
+ {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 3600, 24, TclOffset(DateFormat, date.secondOfDay),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %OI %Ol */
- {CFMTT_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, TclOffset(DateFormat, date.secondOfDay),
ClockFmtToken_HourAMPM_Proc, (void *)MCLIT_LOCALE_NUMERALS},
/* %OM */
- {CFMTT_INT, NULL, 0, CLFMT_LOCALE_INDX, 60, 60, TclOffset(DateFormat, date.secondOfDay),
+ {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 60, 60, TclOffset(DateFormat, date.secondOfDay),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %OS */
- {CFMTT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 60, TclOffset(DateFormat, date.secondOfDay),
+ {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 60, TclOffset(DateFormat, date.secondOfDay),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %Ou */
- {CFMTT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.dayOfWeek),
+ {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 100, TclOffset(DateFormat, date.dayOfWeek),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
/* %Ow */
- {CFMTT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, TclOffset(DateFormat, date.dayOfWeek),
+ {CTOKT_INT, NULL, 0, CLFMT_LOCALE_INDX, 0, 7, TclOffset(DateFormat, date.dayOfWeek),
NULL, (void *)MCLIT_LOCALE_NUMERALS},
};
static const char *FmtOTokenMapAliasIndex[2] = {
@@ -2991,7 +2993,7 @@ ClockFormat(
map = tok->map;
switch (map->type)
{
- case CFMTT_INT:
+ case CTOKT_INT:
if (1) {
int val = (int)*(int *)(((char *)dateFmt) + map->offs);
if (map->fmtproc == NULL) {
@@ -3041,7 +3043,7 @@ ClockFormat(
}
}
break;
- case CFMTT_WIDE:
+ case CTOKT_WIDE:
if (1) {
Tcl_WideInt val = *(Tcl_WideInt *)(((char *)dateFmt) + map->offs);
if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { goto error; };
diff --git a/generic/tclDate.h b/generic/tclDate.h
index 0fcbd70..d5334b5 100644
--- a/generic/tclDate.h
+++ b/generic/tclDate.h
@@ -144,7 +144,7 @@ typedef struct TclDateFields {
* from the Posix epoch */
int tzOffset; /* Time zone offset in seconds east of
* Greenwich */
- int julianDay; /* Julian Day Number in local time zone */
+ Tcl_WideInt julianDay; /* Julian Day Number in local time zone */
enum {BCE=1, CE=0} era; /* Era */
int gregorian; /* Flag == 1 if the date is Gregorian */
int year; /* Year of the era */
@@ -368,8 +368,8 @@ typedef int ClockScanTokenProc(
typedef enum _CLCKTOK_TYPE {
- CTOKT_DIGIT = 1, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD, CTOKT_CHAR,
- CFMTT_INT, CFMTT_WIDE, CFMTT_PROC
+ CTOKT_INT = 1, CTOKT_WIDE, CTOKT_PARSER, CTOKT_SPACE, CTOKT_WORD, CTOKT_CHAR,
+ CFMTT_PROC
} CLCKTOK_TYPE;
typedef struct ClockScanTokenMap {
diff --git a/tests/clock.test b/tests/clock.test
index acc637c..c2955a5 100644
--- a/tests/clock.test
+++ b/tests/clock.test
@@ -37247,12 +37247,19 @@ test clock-61.2 {overflow of a wide integer on output} {*}{
-result {integer value too large to represent}
-returnCodes error
}
-test clock-61.3 {near-miss overflow of a wide integer on output} {
- clock format 0x7fffffffffffffff -format %s -gmt true
-} [expr 0x7fffffffffffffff]
-test clock-61.4 {near-miss overflow of a wide integer on output} {
- clock format -0x8000000000000000 -format %s -gmt true
-} [expr -0x8000000000000000]
+test clock-61.3 {near-miss overflow of a wide integer on output, very large datetime (upper range)} {
+ clock format 0x00F0000000000000 -format "%s %Y %EE" -gmt true
+} [list [expr 0x00F0000000000000] 2140702833 C.E.]
+test clock-61.4 {near-miss overflow of a wide integer on output, very small datetime (lower range)} {
+ clock format -0x00F0000000000000 -format "%s %Y %EE" -gmt true
+} [list [expr -0x00F0000000000000] 2140654939 B.C.E.]
+
+test clock-61.5 {overflow of possible date-time (upper range)} -body {
+ clock format 0x00F0000000000001 -gmt true
+} -returnCodes error -result {integer value too large to represent}
+test clock-61.6 {overflow of possible date-time (lower range)} -body {
+ clock format -0x00F0000000000001 -gmt true
+} -returnCodes error -result {integer value too large to represent}
test clock-62.1 {Bug 1902423} {*}{
-setup {::tcl::clock::ClearCaches}