diff --git a/generic/tclClock.c b/generic/tclClock.c index 617d7ca..c6a9cef 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -3796,14 +3796,14 @@ ClockValidDate( } /* first year (used later in hath / daysInPriorMonths) */ - if ((info->flags & (CLF_YEAR|CLF_ISO8601YEAR)) || yyHaveDate) { + if ((info->flags & (CLF_YEAR|CLF_ISO8601YEAR))) { if ((info->flags & CLF_ISO8601YEAR)) { if ( yydate.iso8601Year < dataPtr->validMinYear || yydate.iso8601Year > dataPtr->validMaxYear ) { errMsg = "invalid iso year"; errCode = "iso year"; goto error; } } - if ((info->flags & CLF_YEAR) || yyHaveDate) { + if (info->flags & CLF_YEAR) { if ( yyYear < dataPtr->validMinYear || yyYear > dataPtr->validMaxYear ) { errMsg = "invalid year"; errCode = "year"; goto error; @@ -3819,15 +3819,13 @@ ClockValidDate( } } /* and month (used later in hath) */ - if ((info->flags & CLF_MONTH) || yyHaveDate) { - info->flags |= CLF_MONTH; + if (info->flags & CLF_MONTH) { if ( yyMonth < 1 || yyMonth > 12 ) { errMsg = "invalid month"; errCode = "month"; goto error; } } /* day of month */ - if ((info->flags & CLF_DAYOFMONTH) || (yyHaveDate || yyHaveDay)) { - info->flags |= CLF_DAYOFMONTH; + if (info->flags & (CLF_DAYOFMONTH|CLF_DAYOFWEEK)) { if ( yyDay < 1 || yyDay > 31 ) { errMsg = "invalid day"; errCode = "day"; goto error; } @@ -3839,7 +3837,7 @@ ClockValidDate( } } } - if ((info->flags & CLF_DAYOFYEAR)) { + if (info->flags & CLF_DAYOFYEAR) { if ( yydate.dayOfYear < 1 || yydate.dayOfYear > daysInPriorMonths[IsGregorianLeapYear(&yydate)][12] ) { errMsg = "invalid day of year"; errCode = "day of year"; goto error; @@ -3859,7 +3857,7 @@ ClockValidDate( } } - if ((info->flags & CLF_TIME) || yyHaveTime) { + if (info->flags & CLF_TIME) { /* hour */ if ( yyHour < 0 || yyHour > ((yyMeridian == MER24) ? 23 : 12) ) { errMsg = "invalid time (hour)"; errCode = "hour"; goto error; @@ -3886,7 +3884,7 @@ ClockValidDate( /* time, regarding the modifications by the time-zone (looks for given time * in between DST-time hole, so does not exist in this time-zone) */ - if (((info->flags & CLF_TIME) || yyHaveTime)) { + if (info->flags & CLF_TIME) { /* * we don't need to do the backwards time-conversion (UTC to local) and * compare results, because the after conversion (local to UTC) we @@ -3973,7 +3971,7 @@ ClockFreeScan( * midnight. */ - if (yyHaveDate) { + if (info->flags & CLF_YEAR) { if (yyYear < 100) { if (yyYear >= dataPtr->yearOfCenturySwitch) { yyYear -= 100; @@ -3981,9 +3979,6 @@ ClockFreeScan( yyYear += dataPtr->currentYearCentury; } yydate.era = CE; - if (yyHaveTime == 0) { - yyHaveTime = -1; - } info->flags |= CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS; } @@ -3992,7 +3987,7 @@ ClockFreeScan( * zone indicator of +-hhmm and setup this time zone. */ - if (yyHaveZone) { + if (info->flags & CLF_ZONE) { Tcl_Obj *tzObjStor = NULL; int minEast = -yyTimezone; int dstFlag = 1 - yyDSTmode; @@ -4026,20 +4021,20 @@ ClockFreeScan( * Assemble date, time, zone into seconds-from-epoch */ - if (yyHaveTime == -1) { + if ((info->flags & (CLF_TIME|CLF_HAVEDATE)) == CLF_HAVEDATE) { yySecondOfDay = 0; info->flags |= CLF_ASSEMBLE_SECONDS; } else - if (yyHaveTime) { + if (info->flags & CLF_TIME) { yySecondOfDay = ToSeconds(yyHour, yyMinutes, yySeconds, yyMeridian); info->flags |= CLF_ASSEMBLE_SECONDS; } else - if ( (yyHaveDay && !yyHaveDate) - || yyHaveOrdinalMonth - || ( yyHaveRel + if ( (info->flags & (CLF_DAYOFWEEK|CLF_HAVEDATE)) == CLF_DAYOFWEEK + || (info->flags & CLF_ORDINALMONTH) + || ( (info->flags & CLF_RELCONV) && ( yyRelMonth != 0 || yyRelDay != 0 ) ) ) { @@ -4092,7 +4087,7 @@ ClockCalcRelTime( */ repeat_rel: - if (yyHaveRel) { + if (info->flags & CLF_RELCONV) { /* * Relative conversion normally possible in UTC time only, because @@ -4164,14 +4159,14 @@ ClockCalcRelTime( } } - yyHaveRel = 0; + info->flags &= ~CLF_RELCONV; } /* * Do relative (ordinal) month */ - if (yyHaveOrdinalMonth) { + if (info->flags & CLF_ORDINALMONTH) { int monthDiff; /* if needed extract year, month, etc. again */ @@ -4197,12 +4192,10 @@ ClockCalcRelTime( } /* process it further via relative times */ - yyHaveRel++; yyYear += yyMonthOrdinalIncr; yyRelMonth += monthDiff; - yyHaveOrdinalMonth = 0; - - info->flags |= CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS; + info->flags &= ~CLF_ORDINALMONTH; + info->flags |= CLF_RELCONV|CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS; goto repeat_rel; } @@ -4211,12 +4204,11 @@ ClockCalcRelTime( * Do relative weekday */ - if (yyHaveDay && !yyHaveDate) { + if ((info->flags & (CLF_DAYOFWEEK|CLF_HAVEDATE)) == CLF_DAYOFWEEK) { /* restore scanned day of week */ - if (info->flags & CLF_DAYOFWEEK) { - yyDayOfWeek = prevDayOfWeek; - } + yyDayOfWeek = prevDayOfWeek; + /* if needed assemble julianDay now */ if (info->flags & CLF_ASSEMBLE_JULIANDAY) { GetJulianDayFromEraYearMonthDay(&yydate, GREGORIAN_CHANGE_DATE); @@ -4422,7 +4414,7 @@ ClockAddObjCmd( * correct date info, because the date may be changed, * so refresh it now */ - if ( yyHaveRel + if ( (info->flags & CLF_RELCONV) && ( unitIndex == CLC_ADD_WEEKDAYS /* some months can be shorter as another */ || yyRelMonth || yyRelDay @@ -4437,7 +4429,7 @@ ClockAddObjCmd( } /* process increment by offset + unit */ - yyHaveRel++; + info->flags |= CLF_RELCONV; switch (unitIndex) { case CLC_ADD_YEARS: yyRelMonth += offs * 12; @@ -4474,7 +4466,7 @@ ClockAddObjCmd( * Do relative times (if not yet already processed interim): */ - if (yyHaveRel) { + if (info->flags & CLF_RELCONV) { if (ClockCalcRelTime(info, &opts) != TCL_OK) { goto done; } diff --git a/generic/tclDate.c b/generic/tclDate.c index 165f911..7c07d45 100644 --- a/generic/tclDate.c +++ b/generic/tclDate.c @@ -123,6 +123,13 @@ #define SECSPERDAY (24L * 60L * 60L) #define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) +#define yyIncrFlags(f) \ + do { \ + info->errFlags |= (info->flags & (f)); \ + if (info->errFlags) { YYABORT; } \ + info->flags |= (f); \ + } while (0); + /* * An entry in the lexical lookup table. */ @@ -551,13 +558,13 @@ static const yytype_uint8 yytranslate[] = /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 160, 160, 161, 162, 165, 168, 171, 174, 177, - 180, 183, 187, 192, 195, 201, 207, 215, 219, 223, - 227, 231, 235, 241, 242, 245, 250, 255, 260, 265, - 270, 277, 281, 286, 291, 296, 301, 305, 310, 314, - 319, 326, 330, 336, 345, 353, 361, 370, 380, 394, - 399, 402, 405, 408, 411, 414, 417, 422, 425, 430, - 434, 438, 444, 447, 452, 470, 473 + 0, 167, 167, 168, 169, 172, 175, 178, 181, 184, + 187, 190, 193, 197, 200, 206, 212, 220, 224, 228, + 232, 236, 240, 246, 247, 250, 254, 258, 262, 266, + 270, 276, 280, 285, 290, 295, 300, 304, 309, 313, + 318, 325, 329, 335, 344, 352, 360, 369, 379, 393, + 398, 401, 404, 407, 410, 413, 416, 421, 424, 429, + 433, 437, 443, 446, 451, 469, 472 }; #endif @@ -1501,7 +1508,7 @@ YYLTYPE yylloc = yyloc_default; case 5: { - yyHaveTime++; + yyIncrFlags(CLF_TIME); } break; @@ -1509,7 +1516,7 @@ YYLTYPE yylloc = yyloc_default; case 6: { - yyHaveZone++; + yyIncrFlags(CLF_ZONE); } break; @@ -1517,7 +1524,7 @@ YYLTYPE yylloc = yyloc_default; case 7: { - yyHaveDate++; + yyIncrFlags(CLF_HAVEDATE); } break; @@ -1525,7 +1532,7 @@ YYLTYPE yylloc = yyloc_default; case 8: { - yyHaveOrdinalMonth++; + yyIncrFlags(CLF_ORDINALMONTH); } break; @@ -1533,7 +1540,7 @@ YYLTYPE yylloc = yyloc_default; case 9: { - yyHaveDay++; + yyIncrFlags(CLF_DAYOFWEEK); } break; @@ -1541,7 +1548,7 @@ YYLTYPE yylloc = yyloc_default; case 10: { - yyHaveRel++; + info->flags |= CLF_RELCONV; } break; @@ -1549,8 +1556,7 @@ YYLTYPE yylloc = yyloc_default; case 11: { - yyHaveTime++; - yyHaveDate++; + yyIncrFlags(CLF_TIME|CLF_HAVEDATE); } break; @@ -1558,9 +1564,8 @@ YYLTYPE yylloc = yyloc_default; case 12: { - yyHaveTime++; - yyHaveDate++; - yyHaveRel++; + yyIncrFlags(CLF_TIME|CLF_HAVEDATE); + info->flags |= CLF_RELCONV; } break; @@ -1657,7 +1662,6 @@ YYLTYPE yylloc = yyloc_default; { yyDayOrdinal = 1; yyDayOfWeek = (yyvsp[0].Number); - info->flags |= CLF_DAYOFWEEK; } break; @@ -1667,7 +1671,6 @@ YYLTYPE yylloc = yyloc_default; { yyDayOrdinal = 1; yyDayOfWeek = (yyvsp[-1].Number); - info->flags |= CLF_DAYOFWEEK; } break; @@ -1677,7 +1680,6 @@ YYLTYPE yylloc = yyloc_default; { yyDayOrdinal = (yyvsp[-1].Number); yyDayOfWeek = (yyvsp[0].Number); - info->flags |= CLF_DAYOFWEEK; } break; @@ -1687,7 +1689,6 @@ YYLTYPE yylloc = yyloc_default; { yyDayOrdinal = (yyvsp[-3].Number) * (yyvsp[-1].Number); yyDayOfWeek = (yyvsp[0].Number); - info->flags |= CLF_DAYOFWEEK; } break; @@ -1697,7 +1698,6 @@ YYLTYPE yylloc = yyloc_default; { yyDayOrdinal = (yyvsp[-2].Number) * (yyvsp[-1].Number); yyDayOfWeek = (yyvsp[0].Number); - info->flags |= CLF_DAYOFWEEK; } break; @@ -1707,7 +1707,6 @@ YYLTYPE yylloc = yyloc_default; { yyDayOrdinal = 2; yyDayOfWeek = (yyvsp[0].Number); - info->flags |= CLF_DAYOFWEEK; } break; @@ -2031,10 +2030,10 @@ YYLTYPE yylloc = yyloc_default; case 64: { - if (yyHaveTime && yyHaveDate && !yyHaveRel) { + if ((info->flags & (CLF_TIME|CLF_HAVEDATE|CLF_RELCONV)) == (CLF_TIME|CLF_HAVEDATE)) { yyYear = (yyvsp[0].Number); } else { - yyHaveTime++; + yyIncrFlags(CLF_TIME); if (yyDigitCount <= 2) { yyHour = (yyvsp[0].Number); yyMinutes = 0; @@ -2528,6 +2527,9 @@ TclDateerror( const char *s) { Tcl_Obj* t; + if (!infoPtr->messages) { + infoPtr->messages = Tcl_NewObj(); + } Tcl_AppendToObj(infoPtr->messages, infoPtr->separatrix, -1); Tcl_AppendToObj(infoPtr->messages, s, -1); Tcl_AppendToObj(infoPtr->messages, " (characters ", -1); @@ -2825,9 +2827,7 @@ TclClockFreeScan( yyDSTmode = DSTmaybe; - info->messages = Tcl_NewObj(); info->separatrix = ""; - Tcl_IncrRefCount(info->messages); info->dateStart = yyInput; @@ -2837,58 +2837,44 @@ TclClockFreeScan( /* parse */ status = yyparse(info); if (status == 1) { - Tcl_SetObjResult(interp, info->messages); - Tcl_DecrRefCount(info->messages); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL); - return TCL_ERROR; + const char *msg = NULL; + if (info->errFlags & CLF_HAVEDATE) { + msg = "more than one date in string"; + } else if (info->errFlags & CLF_TIME) { + msg = "more than one time of day in string"; + } else if (info->errFlags & CLF_ZONE) { + msg = "more than one time zone in string"; + } else if (info->errFlags & CLF_DAYOFWEEK) { + msg = "more than one weekday in string"; + } else if (info->errFlags & CLF_ORDINALMONTH) { + msg = "more than one ordinal month in string"; + } + if (msg) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1)); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); + } else { + Tcl_SetObjResult(interp, + info->messages ? info->messages : Tcl_NewObj()); + info->messages = NULL; + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL); + } + status = TCL_ERROR; } else if (status == 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1)); - Tcl_DecrRefCount(info->messages); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); - return TCL_ERROR; + status = TCL_ERROR; } else if (status != 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj("Unknown status returned " "from date parser. Please " "report this error as a " "bug in Tcl.", -1)); - Tcl_DecrRefCount(info->messages); Tcl_SetErrorCode(interp, "TCL", "BUG", NULL); - return TCL_ERROR; + status = TCL_ERROR; } - Tcl_DecrRefCount(info->messages); - - if (yyHaveDate > 1) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("more than one date in string", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); - return TCL_ERROR; - } - if (yyHaveTime > 1) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("more than one time of day in string", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); - return TCL_ERROR; - } - if (yyHaveZone > 1) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("more than one time zone in string", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); - return TCL_ERROR; - } - if (yyHaveDay > 1) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("more than one weekday in string", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); - return TCL_ERROR; - } - if (yyHaveOrdinalMonth > 1) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("more than one ordinal month in string", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); - return TCL_ERROR; + if (info->messages) { + Tcl_DecrRefCount(info->messages); } - - return TCL_OK; + return status; } /* diff --git a/generic/tclDate.h b/generic/tclDate.h index 38edf0f..cf6670f 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -76,6 +76,7 @@ MODULE_SCOPE size_t TclEnvEpoch; /* Epoch of the tcl environment #define CLF_LOCALSEC (1 << 2) #define CLF_JULIANDAY (1 << 3) #define CLF_TIME (1 << 4) +#define CLF_ZONE (1 << 5) #define CLF_CENTURY (1 << 6) #define CLF_DAYOFMONTH (1 << 7) #define CLF_DAYOFYEAR (1 << 8) @@ -85,12 +86,19 @@ MODULE_SCOPE size_t TclEnvEpoch; /* Epoch of the tcl environment #define CLF_ISO8601YEAR (1 << 12) #define CLF_ISO8601WEAK (1 << 13) #define CLF_ISO8601CENTURY (1 << 14) + #define CLF_SIGNED (1 << 15) + +/* extra flags used outside of scan/format-tokens too (int, not a short int) */ +#define CLF_RELCONV (1 << 17) +#define CLF_ORDINALMONTH (1 << 18) + /* On demand (lazy) assemble flags */ #define CLF_ASSEMBLE_DATE (1 << 28) /* assemble year, month, etc. using julianDay */ #define CLF_ASSEMBLE_JULIANDAY (1 << 29) /* assemble julianDay using year, month, etc. */ #define CLF_ASSEMBLE_SECONDS (1 << 30) /* assemble localSeconds (and seconds at end) */ +#define CLF_HAVEDATE (CLF_DAYOFMONTH|CLF_MONTH|CLF_YEAR) #define CLF_DATE (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR | \ CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR | \ CLF_DAYOFWEEK | CLF_ISO8601WEAK) @@ -224,28 +232,22 @@ typedef struct DateInfo { TclDateFields date; - int flags; - - int dateHaveDate; + int flags; /* Signals parts of date/time get found */ + int errFlags; /* Signals error (part of date/time found twice) */ int dateMeridian; - int dateHaveTime; int dateTimezone; int dateDSTmode; - int dateHaveZone; int dateRelMonth; int dateRelDay; int dateRelSeconds; - int dateHaveRel; int dateMonthOrdinalIncr; int dateMonthOrdinal; - int dateHaveOrdinalMonth; int dateDayOrdinal; - int dateHaveDay; int *dateRelPointer; @@ -274,12 +276,6 @@ typedef struct DateInfo { #define yyDayOfWeek (info->date.dayOfWeek) #define yyMonthOrdinalIncr (info->dateMonthOrdinalIncr) #define yyMonthOrdinal (info->dateMonthOrdinal) -#define yyHaveDate (info->dateHaveDate) -#define yyHaveDay (info->dateHaveDay) -#define yyHaveOrdinalMonth (info->dateHaveOrdinalMonth) -#define yyHaveRel (info->dateHaveRel) -#define yyHaveTime (info->dateHaveTime) -#define yyHaveZone (info->dateHaveZone) #define yyTimezone (info->dateTimezone) #define yyMeridian (info->dateMeridian) #define yyRelMonth (info->dateRelMonth) diff --git a/generic/tclGetDate.y b/generic/tclGetDate.y index f25f45b..4ee18bc 100644 --- a/generic/tclGetDate.y +++ b/generic/tclGetDate.y @@ -75,6 +75,13 @@ #define SECSPERDAY (24L * 60L * 60L) #define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0)) +#define yyIncrFlags(f) \ + do { \ + info->errFlags |= (info->flags & (f)); \ + if (info->errFlags) { YYABORT; } \ + info->flags |= (f); \ + } while (0); + /* * An entry in the lexical lookup table. */ @@ -163,31 +170,29 @@ spec : /* NULL */ ; item : time { - yyHaveTime++; + yyIncrFlags(CLF_TIME); } | zone { - yyHaveZone++; + yyIncrFlags(CLF_ZONE); } | date { - yyHaveDate++; + yyIncrFlags(CLF_HAVEDATE); } | ordMonth { - yyHaveOrdinalMonth++; + yyIncrFlags(CLF_ORDINALMONTH); } | day { - yyHaveDay++; + yyIncrFlags(CLF_DAYOFWEEK); } | relspec { - yyHaveRel++; + info->flags |= CLF_RELCONV; } | iso { - yyHaveTime++; - yyHaveDate++; + yyIncrFlags(CLF_TIME|CLF_HAVEDATE); } | trek { - yyHaveTime++; - yyHaveDate++; - yyHaveRel++; + yyIncrFlags(CLF_TIME|CLF_HAVEDATE); + info->flags |= CLF_RELCONV; } | number ; @@ -245,32 +250,26 @@ comma : ',' day : tDAY { yyDayOrdinal = 1; yyDayOfWeek = $1; - info->flags |= CLF_DAYOFWEEK; } | tDAY comma { yyDayOrdinal = 1; yyDayOfWeek = $1; - info->flags |= CLF_DAYOFWEEK; } | tUNUMBER tDAY { yyDayOrdinal = $1; yyDayOfWeek = $2; - info->flags |= CLF_DAYOFWEEK; } | sign SP tUNUMBER tDAY { yyDayOrdinal = $1 * $3; yyDayOfWeek = $4; - info->flags |= CLF_DAYOFWEEK; } | sign tUNUMBER tDAY { yyDayOrdinal = $1 * $2; yyDayOfWeek = $3; - info->flags |= CLF_DAYOFWEEK; } | tNEXT tDAY { yyDayOrdinal = 2; yyDayOfWeek = $2; - info->flags |= CLF_DAYOFWEEK; } ; @@ -450,10 +449,10 @@ INTNUM : tUNUMBER { ; number : INTNUM { - if (yyHaveTime && yyHaveDate && !yyHaveRel) { + if ((info->flags & (CLF_TIME|CLF_HAVEDATE|CLF_RELCONV)) == (CLF_TIME|CLF_HAVEDATE)) { yyYear = $1; } else { - yyHaveTime++; + yyIncrFlags(CLF_TIME); if (yyDigitCount <= 2) { yyHour = $1; yyMinutes = 0; @@ -702,6 +701,9 @@ TclDateerror( const char *s) { Tcl_Obj* t; + if (!infoPtr->messages) { + infoPtr->messages = Tcl_NewObj(); + } Tcl_AppendToObj(infoPtr->messages, infoPtr->separatrix, -1); Tcl_AppendToObj(infoPtr->messages, s, -1); Tcl_AppendToObj(infoPtr->messages, " (characters ", -1); @@ -999,9 +1001,7 @@ TclClockFreeScan( yyDSTmode = DSTmaybe; - info->messages = Tcl_NewObj(); info->separatrix = ""; - Tcl_IncrRefCount(info->messages); info->dateStart = yyInput; @@ -1011,58 +1011,44 @@ TclClockFreeScan( /* parse */ status = yyparse(info); if (status == 1) { - Tcl_SetObjResult(interp, info->messages); - Tcl_DecrRefCount(info->messages); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL); - return TCL_ERROR; + const char *msg = NULL; + if (info->errFlags & CLF_HAVEDATE) { + msg = "more than one date in string"; + } else if (info->errFlags & CLF_TIME) { + msg = "more than one time of day in string"; + } else if (info->errFlags & CLF_ZONE) { + msg = "more than one time zone in string"; + } else if (info->errFlags & CLF_DAYOFWEEK) { + msg = "more than one weekday in string"; + } else if (info->errFlags & CLF_ORDINALMONTH) { + msg = "more than one ordinal month in string"; + } + if (msg) { + Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1)); + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); + } else { + Tcl_SetObjResult(interp, + info->messages ? info->messages : Tcl_NewObj()); + info->messages = NULL; + Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL); + } + status = TCL_ERROR; } else if (status == 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1)); - Tcl_DecrRefCount(info->messages); Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); - return TCL_ERROR; + status = TCL_ERROR; } else if (status != 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj("Unknown status returned " "from date parser. Please " "report this error as a " "bug in Tcl.", -1)); - Tcl_DecrRefCount(info->messages); Tcl_SetErrorCode(interp, "TCL", "BUG", NULL); - return TCL_ERROR; + status = TCL_ERROR; } - Tcl_DecrRefCount(info->messages); - - if (yyHaveDate > 1) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("more than one date in string", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); - return TCL_ERROR; - } - if (yyHaveTime > 1) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("more than one time of day in string", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); - return TCL_ERROR; - } - if (yyHaveZone > 1) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("more than one time zone in string", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); - return TCL_ERROR; - } - if (yyHaveDay > 1) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("more than one weekday in string", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); - return TCL_ERROR; - } - if (yyHaveOrdinalMonth > 1) { - Tcl_SetObjResult(interp, - Tcl_NewStringObj("more than one ordinal month in string", -1)); - Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "MULTIPLE", NULL); - return TCL_ERROR; + if (info->messages) { + Tcl_DecrRefCount(info->messages); } - - return TCL_OK; + return status; } /*