Skip to content

Commit 6c80da1

Browse files
committed
restore backwards compatibility (see clock-44.3) - spaces between tokens are optional, repaired greedy search (minLen), which find start next token or space now;
it is also more consistent than old engine now (covered by clock-44.4)
1 parent 84db392 commit 6c80da1

File tree

2 files changed

+47
-21
lines changed

2 files changed

+47
-21
lines changed

generic/tclClockFmt.c

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ TCL_DECLARE_MUTEX(ClockFmtMutex); /* Serializes access to common format list. */
2828
static void ClockFmtScnStorageDelete(ClockFmtScnStorage *fss);
2929
static void ClockFrmScnFinalize(void *);
3030

31+
#ifndef TCL_CLOCK_FULL_COMPAT
32+
#define TCL_CLOCK_FULL_COMPAT 1
33+
#endif
34+
3135
/*
3236
* Derivation of tclStringHashKeyType with another allocEntryProc
3337
*/
@@ -1018,7 +1022,8 @@ static const char *
10181022
FindTokenBegin(
10191023
const char *p,
10201024
const char *end,
1021-
ClockScanToken *tok)
1025+
ClockScanToken *tok,
1026+
int flags)
10221027
{
10231028
if (p < end) {
10241029
char c;
@@ -1027,23 +1032,35 @@ FindTokenBegin(
10271032
switch (tok->map->type) {
10281033
case CTOKT_INT:
10291034
case CTOKT_WIDE:
1030-
/* should match at least one digit */
1031-
while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {}
1035+
if (!(flags & CLF_STRICT)) {
1036+
/* should match at least one digit or space */
1037+
while (!isdigit(UCHAR(*p)) && !isspace(UCHAR(*p)) &&
1038+
(p = Tcl_UtfNext(p)) < end) {}
1039+
} else {
1040+
/* should match at least one digit */
1041+
while (!isdigit(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {}
1042+
}
10321043
return p;
10331044

10341045
case CTOKT_WORD:
10351046
c = *(tok->tokWord.start);
1036-
/* should match at least to the first char of this word */
1037-
while (*p != c && (p = Tcl_UtfNext(p)) < end) {}
1038-
return p;
1047+
goto findChar;
10391048

10401049
case CTOKT_SPACE:
10411050
while (!isspace(UCHAR(*p)) && (p = Tcl_UtfNext(p)) < end) {}
10421051
return p;
10431052

10441053
case CTOKT_CHAR:
10451054
c = *((char *)tok->map->data);
1046-
while (*p != c && (p = Tcl_UtfNext(p)) < end) {}
1055+
findChar:
1056+
if (!(flags & CLF_STRICT)) {
1057+
/* should match the char or space */
1058+
while (*p != c && !isspace(UCHAR(*p)) &&
1059+
(p = Tcl_UtfNext(p)) < end) {}
1060+
} else {
1061+
/* should match the char */
1062+
while (*p != c && (p = Tcl_UtfNext(p)) < end) {}
1063+
}
10471064
return p;
10481065
}
10491066
}
@@ -1068,6 +1085,7 @@ FindTokenBegin(
10681085

10691086
static void
10701087
DetermineGreedySearchLen(
1088+
ClockFmtScnCmdArgs *opts,
10711089
DateInfo *info,
10721090
ClockScanToken *tok,
10731091
int *minLenPtr,
@@ -1082,7 +1100,8 @@ DetermineGreedySearchLen(
10821100
if ((tok + 1)->map) {
10831101
end -= tok->endDistance + yySpaceCount;
10841102
/* find position of next known token */
1085-
p = FindTokenBegin(p, end, tok + 1);
1103+
p = FindTokenBegin(p, end, tok + 1,
1104+
TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT);
10861105
if (p < end) {
10871106
minLen = p - yyInput;
10881107
}
@@ -1133,7 +1152,8 @@ DetermineGreedySearchLen(
11331152

11341153
/* try to find laTok between [lookAhMin, lookAhMax] */
11351154
while (minLen < maxLen) {
1136-
const char *f = FindTokenBegin(p, end, laTok);
1155+
const char *f = FindTokenBegin(p, end, laTok,
1156+
TCL_CLOCK_FULL_COMPAT ? opts->flags : CLF_STRICT);
11371157
/* if found (not below lookAhMax) */
11381158
if (f < end) {
11391159
break;
@@ -1517,7 +1537,7 @@ ClockScnToken_Month_Proc(
15171537
int minLen, maxLen;
15181538
TclStrIdxTree *idxTree;
15191539

1520-
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
1540+
DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);
15211541

15221542
/* get or create tree in msgcat dict */
15231543

@@ -1549,7 +1569,7 @@ ClockScnToken_DayOfWeek_Proc(
15491569
char curTok = *tok->tokWord.start;
15501570
TclStrIdxTree *idxTree;
15511571

1552-
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
1572+
DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);
15531573

15541574
/* %u %w %Ou %Ow */
15551575
if (curTok != 'a' && curTok != 'A'
@@ -1620,7 +1640,7 @@ ClockScnToken_amPmInd_Proc(
16201640
int minLen, maxLen;
16211641
Tcl_Obj *amPmObj[2];
16221642

1623-
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
1643+
DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);
16241644

16251645
amPmObj[0] = ClockMCGet(opts, MCLIT_AM);
16261646
amPmObj[1] = ClockMCGet(opts, MCLIT_PM);
@@ -1655,7 +1675,7 @@ ClockScnToken_LocaleERA_Proc(
16551675
int minLen, maxLen;
16561676
Tcl_Obj *eraObj[6];
16571677

1658-
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
1678+
DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);
16591679

16601680
eraObj[0] = ClockMCGet(opts, MCLIT_BCE);
16611681
eraObj[1] = ClockMCGet(opts, MCLIT_CE);
@@ -1692,7 +1712,7 @@ ClockScnToken_LocaleListMatcher_Proc(
16921712
int minLen, maxLen;
16931713
TclStrIdxTree *idxTree;
16941714

1695-
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
1715+
DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);
16961716

16971717
/* get or create tree in msgcat dict */
16981718

@@ -1715,7 +1735,7 @@ ClockScnToken_LocaleListMatcher_Proc(
17151735

17161736
static int
17171737
ClockScnToken_JDN_Proc(
1718-
TCL_UNUSED(ClockFmtScnCmdArgs *),
1738+
ClockFmtScnCmdArgs *opts,
17191739
DateInfo *info,
17201740
ClockScanToken *tok)
17211741
{
@@ -1724,7 +1744,7 @@ ClockScnToken_JDN_Proc(
17241744
Tcl_WideInt intJD;
17251745
int fractJD = 0, fractJDDiv = 1;
17261746

1727-
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
1747+
DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);
17281748

17291749
end = yyInput + maxLen;
17301750

@@ -1795,7 +1815,7 @@ ClockScnToken_TimeZone_Proc(
17951815
const char *p = yyInput;
17961816
Tcl_Obj *tzObjStor = NULL;
17971817

1798-
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
1818+
DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);
17991819

18001820
/* numeric timezone */
18011821
if (*p == '+' || *p == '-') {
@@ -1878,7 +1898,7 @@ ClockScnToken_TimeZone_Proc(
18781898

18791899
static int
18801900
ClockScnToken_StarDate_Proc(
1881-
TCL_UNUSED(ClockFmtScnCmdArgs *),
1901+
ClockFmtScnCmdArgs *opts,
18821902
DateInfo *info,
18831903
ClockScanToken *tok)
18841904
{
@@ -1887,7 +1907,7 @@ ClockScnToken_StarDate_Proc(
18871907
int year, fractYear, fractDayDiv, fractDay;
18881908
static const char *stardatePref = "stardate ";
18891909

1890-
DetermineGreedySearchLen(info, tok, &minLen, &maxLen);
1910+
DetermineGreedySearchLen(opts, info, tok, &minLen, &maxLen);
18911911

18921912
end = yyInput + maxLen;
18931913

@@ -2435,7 +2455,7 @@ ClockScan(
24352455
}
24362456
}
24372457

2438-
DetermineGreedySearchLen(info, tok, &minLen, &size);
2458+
DetermineGreedySearchLen(opts, info, tok, &minLen, &size);
24392459

24402460
if (size < map->minSize) {
24412461
/* missing input -> error */

tests/clock.test

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37039,12 +37039,18 @@ test clock-44.2 {regression test - time zone containing only two digits} \
3703937039
} \
3704037040
-result 482134530
3704137041

37042-
test clock-44.3 {regression test - spaces between some scan tokens are optional} \
37042+
test clock-44.3 {regression test - spaces between some scan tokens are optional (TCL_CLOCK_FULL_COMPAT, no-strict only)} \
3704337043
-body {
3704437044
list [clock scan {9 Apr 2024} -format {%d %b%Y} -gmt 1] \
3704537045
[clock scan {Tue, 9 Apr 2024 00:00:00 +0000} -format {%a, %d %b%Y %H:%M:%S %Z} -gmt 1]
3704637046
} \
3704737047
-result {1712620800 1712620800}
37048+
test clock-44.4 {regression test - spaces between all scan tokens are optional (TCL_CLOCK_FULL_COMPAT, no-strict only)} \
37049+
-body {
37050+
list [clock scan {9 Apr 2024} -format {%d%b%Y} -gmt 1] \
37051+
[clock scan {Tue, 9 Apr 2024 00:00:00 +0000} -format {%a,%d%b%Y%H:%M:%S%Z} -gmt 1]
37052+
} \
37053+
-result {1712620800 1712620800}
3704837054

3704937055
test clock-45.1 {compat: scan regression on spaces (multiple spaces in format)} \
3705037056
-body {

0 commit comments

Comments
 (0)