summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2017-01-10 21:58:33 (GMT)
committersebres <sebres@users.sourceforge.net>2017-01-10 21:58:33 (GMT)
commit58f947e48be58a2371a0d24f957244796306d2ba (patch)
tree3d33434ea4d17840e060eb16d05f43717ce157a0
parent4cc1178952c2e7eef686282007f5046adceb1ec1 (diff)
downloadtcl-58f947e48be58a2371a0d24f957244796306d2ba.zip
tcl-58f947e48be58a2371a0d24f957244796306d2ba.tar.gz
tcl-58f947e48be58a2371a0d24f957244796306d2ba.tar.bz2
[temp-commit]: clock scan with several optimization porting, still not-ready
-rw-r--r--generic/tclClock.c520
-rw-r--r--generic/tclDate.c497
-rw-r--r--generic/tclDate.h77
-rw-r--r--generic/tclGetDate.y134
-rwxr-xr-xlibrary/clock.tcl19
-rw-r--r--library/init.tcl2
-rw-r--r--win/makefile.vc4
7 files changed, 870 insertions, 383 deletions
diff --git a/generic/tclClock.c b/generic/tclClock.c
index e9a59f3..24ed095 100644
--- a/generic/tclClock.c
+++ b/generic/tclClock.c
@@ -14,6 +14,7 @@
*/
#include "tclInt.h"
+#include "tclDate.h"
/*
* Windows has mktime. The configurators do not check.
@@ -28,6 +29,7 @@
*/
#define JULIAN_DAY_POSIX_EPOCH 2440588
+#define GREGORIAN_CHANGE_DATE 2361222
#define SECONDS_PER_DAY 86400
#define JULIAN_SEC_POSIX_EPOCH (((Tcl_WideInt) JULIAN_DAY_POSIX_EPOCH) \
* SECONDS_PER_DAY)
@@ -69,7 +71,14 @@ typedef enum ClockLiteral {
LIT_MONTH,
LIT_SECONDS, LIT_TZNAME, LIT_TZOFFSET,
LIT_YEAR,
+ LIT_CURRENTYEARCENTURY,
+ LIT_YEAROFCENTURYSWITCH,
+ LIT_TZDATA,
+ LIT_GETSYSTEMTIMEZONE,
+ LIT_SETUPTIMEZONE,
+#if 0
LIT_FREESCAN,
+#endif
LIT__END
} ClockLiteral;
static const char *const literals[] = {
@@ -86,9 +95,18 @@ static const char *const literals[] = {
"month",
"seconds", "tzName", "tzOffset",
"year",
+ "::tcl::clock::CurrentYearCentury",
+ "::tcl::clock::YearOfCenturySwitch",
+ "::tcl::clock::TZData",
+ "::tcl::clock::GetSystemTimeZone",
+ "::tcl::clock::SetupTimeZone",
+#if 0
"::tcl::clock::FreeScan"
+#endif
};
+#define CurrentYearCentury 2000
+
/*
* Structure containing the client data for [clock]
*/
@@ -168,6 +186,10 @@ static int ClockClicksObjCmd(
static int ClockConvertlocaltoutcObjCmd(
ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
+
+static int ClockGetDateFields(Tcl_Interp *interp,
+ TclDateFields *fields, Tcl_Obj *tzdata,
+ int changeover);
static int ClockGetdatefieldsObjCmd(
ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
@@ -195,6 +217,10 @@ static int ClockSecondsObjCmd(
static int ClockScanObjCmd(
ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *const objv[]);
+static int ClockFreeScan(
+ ClientData clientData, Tcl_Interp *interp,
+ Tcl_Obj *strObj, Tcl_WideInt baseVal,
+ Tcl_Obj *timezoneObj, Tcl_Obj *locale);
static struct tm * ThreadSafeLocalTime(const time_t *);
static void TzsetIfNecessary(void);
static void ClockDeleteCmdProc(ClientData);
@@ -296,6 +322,123 @@ TclClockInit(
/*
*----------------------------------------------------------------------
+ */
+inline Tcl_Obj*
+ClockGetTZData(
+ ClientData clientData, /* Opaque pointer to literal pool, etc. */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ Tcl_Obj *timezoneObj) /* Name of the timezone */
+{
+ ClockClientData *dataPtr = clientData;
+ Tcl_Obj **literals = dataPtr->literals;
+
+ return Tcl_ObjGetVar2(interp, literals[LIT_TZDATA],
+ timezoneObj, TCL_LEAVE_ERR_MSG);
+}
+/*
+ *----------------------------------------------------------------------
+ */
+static Tcl_Obj *
+ClockGetSystemTimeZone(
+ ClientData clientData, /* Opaque pointer to literal pool, etc. */
+ Tcl_Interp *interp) /* Tcl interpreter */
+{
+ ClockClientData *dataPtr = clientData;
+ Tcl_Obj **literals = dataPtr->literals;
+
+ if (Tcl_EvalObjv(interp, 1, &literals[LIT_GETSYSTEMTIMEZONE], 0) != TCL_OK) {
+ return NULL;
+ }
+ return Tcl_GetObjResult(interp);
+}
+/*
+ *----------------------------------------------------------------------
+ */
+static int
+ClockSetupTimeZone(
+ ClientData clientData, /* Opaque pointer to literal pool, etc. */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ Tcl_Obj *timezoneObj)
+{
+ ClockClientData *dataPtr = clientData;
+ Tcl_Obj **literals = dataPtr->literals;
+ Tcl_Obj *callargs[2];
+
+ callargs[0] = literals[LIT_SETUPTIMEZONE];
+ callargs[1] = timezoneObj;
+ return Tcl_EvalObjv(interp, 2, callargs, 0);
+}
+/*
+ *----------------------------------------------------------------------
+ * ClockFormatNumericTimeZone -
+ *
+ * Formats a time zone as +hhmmss
+ *
+ * Parameters:
+ * z - Time zone in seconds east of Greenwich
+ *
+ * Results:
+ * Returns the time zone object (formatted in a numeric form)
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+ClockFormatNumericTimeZone(int z) {
+ char sign = '+';
+ int h, m;
+ if ( z < 0 ) {
+ z = -z;
+ sign = '-';
+ }
+ h = z / 3600;
+ z %= 3600;
+ m = z / 60;
+ z %= 60;
+ if (z != 0) {
+ return Tcl_ObjPrintf("%c%02d%02d%02d", sign, h, m, z);
+ }
+ return Tcl_ObjPrintf("%c%02d%02d", sign, h, m);
+}
+
+/*
+ *----------------------------------------------------------------------
+ * [SB] TODO: make constans cacheable (once per second, etc.) ...
+ */
+inline int
+ClockCurrentYearCentury(
+ ClientData clientData, /* Opaque pointer to literal pool, etc. */
+ Tcl_Interp *interp) /* Tcl interpreter */
+{
+ ClockClientData *dataPtr = clientData;
+ Tcl_Obj **literals = dataPtr->literals;
+ int year = 2000;
+
+ Tcl_Obj * yearObj = Tcl_ObjGetVar2(interp,
+ literals[LIT_CURRENTYEARCENTURY], NULL, TCL_LEAVE_ERR_MSG);
+ Tcl_GetIntFromObj(NULL, yearObj, &year);
+ return year;
+}
+inline int
+ClockGetYearOfCenturySwitch(
+ ClientData clientData, /* Opaque pointer to literal pool, etc. */
+ Tcl_Interp *interp) /* Tcl interpreter */
+{
+ ClockClientData *dataPtr = clientData;
+ Tcl_Obj **literals = dataPtr->literals;
+ int year = 37;
+
+ Tcl_Obj * yearObj = Tcl_ObjGetVar2(interp,
+ literals[LIT_YEAROFCENTURYSWITCH], NULL, TCL_LEAVE_ERR_MSG);
+ Tcl_GetIntFromObj(NULL, yearObj, &year);
+ return year;
+}
+
+/*
+ *----------------------------------------------------------------------
*
* ClockConvertlocaltoutcObjCmd --
*
@@ -426,6 +569,8 @@ ClockGetdatefieldsObjCmd(
Tcl_Obj *const *literals = data->literals;
int changeover;
+ fields.tzName = NULL;
+
/*
* Check params.
*/
@@ -449,31 +594,14 @@ ClockGetdatefieldsObjCmd(
return TCL_ERROR;
}
- /*
- * Convert UTC time to local.
- */
+ /* Extract fields */
- if (ConvertUTCToLocal(interp, &fields, objv[2], changeover) != TCL_OK) {
+ if (ClockGetDateFields(interp, &fields, objv[2], changeover)
+ != TCL_OK) {
return TCL_ERROR;
}
- /*
- * Extract Julian day.
- */
-
- fields.julianDay = (int) ((fields.localSeconds + JULIAN_SEC_POSIX_EPOCH)
- / SECONDS_PER_DAY);
-
- /*
- * Convert to Julian or Gregorian calendar.
- */
-
- GetGregorianEraYearDay(&fields, changeover);
- GetMonthDay(&fields);
- GetYearWeekDay(&fields, changeover);
-
-
-/************* split to use structured version from here ************/
+ /* Make dict of fields */
dict = Tcl_NewDictObj();
Tcl_DictObjPut(NULL, dict, literals[LIT_LOCALSECONDS],
@@ -511,6 +639,59 @@ ClockGetdatefieldsObjCmd(
/*
*----------------------------------------------------------------------
+ */
+int
+ClockGetDateFields(
+ Tcl_Interp *interp, /* Tcl interpreter */
+ TclDateFields *fields, /* Pointer to result fields, where
+ * fields->seconds contains date to extract */
+ Tcl_Obj *tzdata, /* Time zone data object or NULL for gmt */
+ int changeover) /* Julian Day Number */
+{
+ /*
+ * Convert UTC time to local.
+ */
+
+ if (ConvertUTCToLocal(interp, fields, tzdata, changeover) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Extract Julian day.
+ */
+
+ fields->julianDay = (int) ((fields->localSeconds + JULIAN_SEC_POSIX_EPOCH)
+ / SECONDS_PER_DAY);
+
+ /*
+ * Convert to Julian or Gregorian calendar.
+ */
+
+ GetGregorianEraYearDay(fields, changeover);
+ GetMonthDay(fields);
+ GetYearWeekDay(fields, changeover);
+
+ return TCL_OK;
+}
+
+inline
+SetDateFieldsTimeZone(
+ TclDateFields *fields,
+ Tcl_Obj *timezoneObj)
+{
+ if (fields->tzName != timezoneObj) {
+ if (timezoneObj) {
+ Tcl_IncrRefCount(timezoneObj);
+ }
+ if (fields->tzName != NULL) {
+ Tcl_DecrRefCount(fields->tzName);
+ }
+ fields->tzName = timezoneObj;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
*
* ClockGetjuliandayfromerayearmonthdayObjCmd --
*
@@ -1013,8 +1194,7 @@ ConvertUTCToLocalUsingTable(
* Convert the time.
*/
- fields->tzName = cellv[3];
- Tcl_IncrRefCount(fields->tzName);
+ SetDateFieldsTimeZone(fields, cellv[3]);
fields->localSeconds = fields->seconds + fields->tzOffset;
return TCL_OK;
}
@@ -1107,8 +1287,7 @@ ConvertUTCToLocalUsingC(
if (diff > 0) {
sprintf(buffer+5, "%02d", diff);
}
- fields->tzName = Tcl_NewStringObj(buffer, -1);
- Tcl_IncrRefCount(fields->tzName);
+ SetDateFieldsTimeZone(fields, Tcl_NewStringObj(buffer, -1));
return TCL_OK;
}
@@ -1968,7 +2147,7 @@ ClockParseformatargsObjCmd(
Tcl_Obj *const objv[]) /* Parameter vector */
{
ClockClientData *dataPtr = clientData;
- Tcl_Obj **litPtr = dataPtr->literals;
+ Tcl_Obj **literals = dataPtr->literals;
_ClockFmtScnArgs resOpts; /* Format, locale and timezone */
Tcl_WideInt clockVal; /* Clock value - just used to parse. */
int ret;
@@ -2003,11 +2182,11 @@ ClockParseformatargsObjCmd(
return TCL_ERROR;
}
if (resOpts.formatObj == NULL)
- resOpts.formatObj = litPtr[LIT__DEFAULT_FORMAT];
+ resOpts.formatObj = literals[LIT__DEFAULT_FORMAT];
if (resOpts.localeObj == NULL)
- resOpts.localeObj = litPtr[LIT_C];
+ resOpts.localeObj = literals[LIT_C];
if (resOpts.timezoneObj == NULL)
- resOpts.timezoneObj = litPtr[LIT__NIL];
+ resOpts.timezoneObj = literals[LIT__NIL];
/*
* Return options as a list.
@@ -2032,7 +2211,7 @@ ClockScanObjCmd(
Tcl_Obj *const objv[]) /* Parameter values */
{
ClockClientData *dataPtr = clientData;
- Tcl_Obj **litPtr = dataPtr->literals;
+ Tcl_Obj **literals = dataPtr->literals;
Tcl_Time retClock;
char *string, *format = NULL;
@@ -2071,8 +2250,10 @@ ClockScanObjCmd(
baseVal = (Tcl_WideInt) now.sec;
}
- /* if free scan */
+ /* If free scan */
if (opts.formatObj == NULL) {
+#if 0
+ /* Tcled FreeScan proc - */
Tcl_Obj *callargs[5];
/* [SB] TODO: Perhaps someday we'll localize the legacy code. Right now, it's not localized. */
if (opts.localeObj != NULL) {
@@ -2081,18 +2262,287 @@ ClockScanObjCmd(
Tcl_SetErrorCode(interp, "CLOCK", "flagWithLegacyFormat", NULL);
return TCL_ERROR;
}
- callargs[0] = litPtr[LIT_FREESCAN];
+ callargs[0] = literals[LIT_FREESCAN];
callargs[1] = objv[1];
callargs[2] = opts.baseObj != NULL ? opts.baseObj : Tcl_NewWideIntObj(baseVal);
- callargs[3] = opts.timezoneObj != NULL ? opts.timezoneObj : litPtr[LIT__NIL];
- callargs[4] = opts.localeObj != NULL ? opts.localeObj : litPtr[LIT_C];
+ callargs[3] = opts.timezoneObj != NULL ? opts.timezoneObj : literals[LIT__NIL];
+ callargs[4] = opts.localeObj != NULL ? opts.localeObj : literals[LIT_C];
return Tcl_EvalObjv(interp, 5, callargs, 0);
+#else
+ /* Use compiled version of FreeScan - */
+
+
+ /* [SB] TODO: Perhaps someday we'll localize the legacy code. Right now, it's not localized. */
+ if (opts.localeObj != NULL) {
+ Tcl_SetResult(interp,
+ "legacy [clock scan] does not support -locale", TCL_STATIC);
+ Tcl_SetErrorCode(interp, "CLOCK", "flagWithLegacyFormat", NULL);
+ return TCL_ERROR;
+ }
+ return ClockFreeScan(clientData, interp, objv[1], baseVal,
+ opts.timezoneObj, opts.localeObj);
+#endif
}
+
// ****
string = TclGetString(objv[1]);
- // **** timezone = GetSystemTimeZone()
+ // **** timezone = ClockGetSystemTimeZone(clientData, interp)
+ /*
+ if (timezoneObj == NULL) {
+ goto done;
+ }
+ */
+
+ return TCL_OK;
+}
+
+/*----------------------------------------------------------------------
+ */
+int
+ClockFreeScan(
+ ClientData clientData, /* Client data containing literal pool */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ Tcl_Obj *strObj, /* String containing the time to scan */
+ Tcl_WideInt baseVal, /* Base time, expressed in seconds from the Epoch */
+ Tcl_Obj *timezoneObj, /* Default time zone in which the time will be expressed */
+ Tcl_Obj *locale) /* (Unused) Name of the locale where the time will be scanned. */
+{
+ ClockClientData *dataPtr = clientData;
+ Tcl_Obj **literals = dataPtr->literals;
+
+ DateInfo yy; /* parse structure of TclClockFreeScan */
+ TclDateFields date; /* date fields used for converting from seconds */
+ Tcl_Obj *tzdata;
+ int secondOfDay; /* Seconds of day (time only calculation) */
+ Tcl_WideInt seconds;
+ int ret = TCL_ERROR;
+ Tcl_Obj *cleanUpList = Tcl_NewObj();
+
+ date.tzName = NULL;
+
+ /* If time zone not specified use system time zone */
+ if (timezoneObj == NULL ||
+ TclGetString(timezoneObj) == NULL || timezoneObj->length == 0) {
+ timezoneObj = ClockGetSystemTimeZone(clientData, interp);
+ if (timezoneObj == NULL) {
+ goto done;
+ }
+ Tcl_ListObjAppendElement(NULL, cleanUpList, timezoneObj);
+ }
+
+ /* Get the data for time changes in the given zone */
+
+ if (ClockSetupTimeZone(clientData, interp, timezoneObj) != TCL_OK) {
+ goto done;
+ }
+
+ /*
+ * Extract year, month and day from the base time for the parser to use as
+ * defaults
+ */
+
+ tzdata = ClockGetTZData(clientData, interp, timezoneObj);
+ if (tzdata == NULL) {
+ goto done;
+ }
+ date.seconds = baseVal;
+ if (ClockGetDateFields(interp, &date, tzdata, GREGORIAN_CHANGE_DATE)
+ != TCL_OK) {
+ goto done;
+ }
+
+ secondOfDay = date.localSeconds % 86400;
+
+ /*
+ * Parse the date. The parser will fill a structure "yy" with date, time,
+ * time zone, relative month/day/seconds, relative weekday, ordinal month.
+ */
+ yy.dateInput = Tcl_GetString(strObj);
+
+ yy.dateYear = date.year;
+ yy.dateMonth = date.month;
+ yy.dateDay = date.dayOfMonth;
+
+ if (TclClockFreeScan(interp, &yy) != TCL_OK) {
+ Tcl_Obj *msg = Tcl_NewObj();
+ Tcl_AppendPrintfToObj(msg, "unable to convert date-time string \"",
+ yy.dateInput, "\":",
+ TclGetString(Tcl_GetObjResult(interp)));
+ Tcl_SetObjResult(interp, msg);
+ goto done;
+ }
+
+ /*
+ * If the caller supplied a date in the string, update the date with
+ * the value. If the caller didn't specify a time with the date, default to
+ * midnight.
+ */
+
+ if (yy.dateHaveDate) {
+ if (yy.dateYear < 100) {
+ yy.dateYear += ClockCurrentYearCentury(clientData, interp);
+ if (yy.dateYear > ClockGetYearOfCenturySwitch(clientData, interp)) {
+ yy.dateYear -= 100;
+ }
+ }
+ date.era = CE;
+ date.year = yy.dateYear;
+ date.month = yy.dateMonth;
+ date.dayOfMonth = yy.dateDay;
+ if (yy.dateHaveTime == 0) {
+ yy.dateHaveTime = -1;
+ }
+ }
+
+ /*
+ * If the caller supplied a time zone in the string, make it into a time
+ * zone indicator of +-hhmm and setup this time zone.
+ */
+
+ if (yy.dateHaveZone) {
+ int minEast = -yy.dateTimezone;
+ int dstFlag = 1 - yy.dateDSTmode;
+ timezoneObj = ClockFormatNumericTimeZone(
+ 60 * minEast + 3600 * dstFlag);
+ Tcl_ListObjAppendElement(NULL, cleanUpList, timezoneObj);
+ if (ClockSetupTimeZone(clientData, interp, timezoneObj) != TCL_OK) {
+ goto done;
+ }
+ tzdata = ClockGetTZData(clientData, interp, timezoneObj);
+ if (tzdata == NULL) {
+ goto done;
+ }
+ }
+
+ SetDateFieldsTimeZone(&date, timezoneObj);
+
+ /* Assemble date, time, zone into seconds-from-epoch */
+
+ GetJulianDayFromEraYearMonthDay(&date, GREGORIAN_CHANGE_DATE);
+
+ if (yy.dateHaveTime == -1) {
+ secondOfDay = 0;
+ }
+ else
+ if (yy.dateHaveTime) {
+ secondOfDay = ToSeconds(yy.dateHour, yy.dateMinutes,
+ yy.dateSeconds, yy.dateMeridian);
+ }
+ else
+ if ( (yy.dateHaveDay && !yy.dateHaveDate)
+ || yy.dateHaveOrdinalMonth
+ || ( yy.dateHaveRel
+ && ( yy.dateRelMonth != 0
+ || yy.dateRelDay != 0 ) )
+ ) {
+ secondOfDay = 0;
+ }
+
+ date.localSeconds =
+ -210866803200L
+ + ( 86400 * (Tcl_WideInt)date.julianDay )
+ + secondOfDay;
+
+ SetDateFieldsTimeZone(&date, timezoneObj);
+ if (ConvertLocalToUTC(interp, &date, tzdata, GREGORIAN_CHANGE_DATE)
+ != TCL_OK) {
+ goto done;
+ }
+
+ seconds = date.seconds;
+
+ /*
+ * Do relative times
+ */
+
+ if (yy.dateHaveRel) {
+
+ /* [SB] TODO: rewrite it in C: * /
+ seconds = [add $seconds \
+ yy.dateRelMonth months yy.dateRelDay days yy.dateRelMonthSecond seconds \
+ -timezone $timezone -locale $locale]
+ */
+ }
+
+ /*
+ * Do relative weekday
+ */
+
+ if (yy.dateHaveDay && !yy.dateHaveDate) {
+ TclDateFields date2;
+ date2.tzName = NULL;
+
+ SetDateFieldsTimeZone(&date2, timezoneObj);
+
+ date2.seconds = date.seconds;
+ if (ClockGetDateFields(interp, &date2, tzdata, GREGORIAN_CHANGE_DATE)
+ != TCL_OK) {
+ SetDateFieldsTimeZone(&date2, NULL);
+ goto done;
+ }
+ date2.era = CE;
+ date2.julianDay = WeekdayOnOrBefore(yy.dateDayNumber, date2.julianDay + 6)
+ + 7 * yy.dateDayOrdinal;
+ if (yy.dateDayOrdinal > 0) {
+ date2.julianDay -= 7;
+ }
+ secondOfDay = date2.localSeconds % 86400;
+ date2.localSeconds =
+ -210866803200
+ + ( 86400 * (Tcl_WideInt)date2.julianDay )
+ + secondOfDay;
+
+ SetDateFieldsTimeZone(&date2, timezoneObj);
+ if (ConvertLocalToUTC(interp, &date2, tzdata, GREGORIAN_CHANGE_DATE)
+ != TCL_OK) {
+ SetDateFieldsTimeZone(&date2, NULL);
+ goto done;
+ }
+ SetDateFieldsTimeZone(&date2, NULL);
+
+ seconds = date2.seconds;
+ }
+
+ /*
+ * Do relative month
+ */
+
+ if (yy.dateHaveOrdinalMonth) {
+ int monthDiff;
+ if (yy.dateMonthOrdinal > 0) {
+ monthDiff = yy.dateMonth - date.month;
+ if (monthDiff <= 0) {
+ monthDiff += 12;
+ }
+ yy.dateMonthOrdinal--;
+ } else {
+ monthDiff = date.month - yy.dateMonth;
+ if (monthDiff >= 0) {
+ monthDiff -= 12;
+ }
+ yy.dateMonthOrdinal++;
+ }
+ /* [SB] TODO: rewrite it in C: * /
+ seconds = [add $seconds $yy.dateMonthOrdinal years $monthDiff months \
+ -timezone $timezone -locale $locale]
+ */
+ }
+
+ ret = TCL_OK;
+
+done:
+
+ if (date.tzName != NULL) {
+ Tcl_DecrRefCount(date.tzName);
+ }
+ Tcl_DecrRefCount(cleanUpList);
+
+ if (ret != TCL_OK) {
+ return ret;
+ }
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(seconds));
return TCL_OK;
}
diff --git a/generic/tclDate.c b/generic/tclDate.c
index e4dd000..a31e0fc 100644
--- a/generic/tclDate.c
+++ b/generic/tclDate.c
@@ -1,24 +1,22 @@
-/* A Bison parser, made by GNU Bison 2.3. */
+/* A Bison parser, made by GNU Bison 2.4.2. */
/* Skeleton implementation for Bison's Yacc-like parsers in C
-
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
+
+ Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
+ Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* As a special exception, you may create a larger work that contains
part or all of the Bison parser skeleton and distribute that work
@@ -29,7 +27,7 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
@@ -47,7 +45,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.3"
+#define YYBISON_VERSION "2.4.2"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -55,65 +53,24 @@
/* Pure parsers. */
#define YYPURE 1
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
/* Using locations. */
#define YYLSP_NEEDED 1
/* Substitute the variable and function names. */
-#define yyparse TclDateparse
-#define yylex TclDatelex
-#define yyerror TclDateerror
-#define yylval TclDatelval
-#define yychar TclDatechar
-#define yydebug TclDatedebug
-#define yynerrs TclDatenerrs
-#define yylloc TclDatelloc
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- tAGO = 258,
- tDAY = 259,
- tDAYZONE = 260,
- tID = 261,
- tMERIDIAN = 262,
- tMONTH = 263,
- tMONTH_UNIT = 264,
- tSTARDATE = 265,
- tSEC_UNIT = 266,
- tSNUMBER = 267,
- tUNUMBER = 268,
- tZONE = 269,
- tEPOCH = 270,
- tDST = 271,
- tISOBASE = 272,
- tDAY_UNIT = 273,
- tNEXT = 274
- };
-#endif
-/* Tokens. */
-#define tAGO 258
-#define tDAY 259
-#define tDAYZONE 260
-#define tID 261
-#define tMERIDIAN 262
-#define tMONTH 263
-#define tMONTH_UNIT 264
-#define tSTARDATE 265
-#define tSEC_UNIT 266
-#define tSNUMBER 267
-#define tUNUMBER 268
-#define tZONE 269
-#define tEPOCH 270
-#define tDST 271
-#define tISOBASE 272
-#define tDAY_UNIT 273
-#define tNEXT 274
-
-
-
+#define yyparse TclDateparse
+#define yylex TclDatelex
+#define yyerror TclDateerror
+#define yylval TclDatelval
+#define yychar TclDatechar
+#define yydebug TclDatedebug
+#define yynerrs TclDatenerrs
+#define yylloc TclDatelloc
/* Copy the first part of user declarations. */
@@ -129,6 +86,7 @@
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
*/
#include "tclInt.h"
@@ -146,44 +104,7 @@
* parsed fields will be returned.
*/
-typedef struct DateInfo {
-
- Tcl_Obj* messages; /* Error messages */
- const char* separatrix; /* String separating messages */
-
- time_t dateYear;
- time_t dateMonth;
- time_t dateDay;
- int dateHaveDate;
-
- time_t dateHour;
- time_t dateMinutes;
- time_t dateSeconds;
- int dateMeridian;
- int dateHaveTime;
-
- time_t dateTimezone;
- int dateDSTmode;
- int dateHaveZone;
-
- time_t dateRelMonth;
- time_t dateRelDay;
- time_t dateRelSeconds;
- int dateHaveRel;
-
- time_t dateMonthOrdinal;
- int dateHaveOrdinalMonth;
-
- time_t dateDayOrdinal;
- time_t dateDayNumber;
- int dateHaveDay;
-
- const char *dateStart;
- const char *dateInput;
- time_t *dateRelPointer;
-
- int dateDigitCount;
-} DateInfo;
+#include "tclDate.h"
#define YYMALLOC ckalloc
#define YYFREE(x) (ckfree((void*) (x)))
@@ -246,13 +167,6 @@ typedef enum _DSTMODE {
DSTon, DSToff, DSTmaybe
} DSTMODE;
-/*
- * Meridian: am, pm, or 24-hour style.
- */
-
-typedef enum _MERIDIAN {
- MERam, MERpm, MER24
-} MERIDIAN;
@@ -274,19 +188,49 @@ typedef enum _MERIDIAN {
# define YYTOKEN_TABLE 0
#endif
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ tAGO = 258,
+ tDAY = 259,
+ tDAYZONE = 260,
+ tID = 261,
+ tMERIDIAN = 262,
+ tMONTH = 263,
+ tMONTH_UNIT = 264,
+ tSTARDATE = 265,
+ tSEC_UNIT = 266,
+ tSNUMBER = 267,
+ tUNUMBER = 268,
+ tZONE = 269,
+ tEPOCH = 270,
+ tDST = 271,
+ tISOBASE = 272,
+ tDAY_UNIT = 273,
+ tNEXT = 274
+ };
+#endif
+
+
+
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE
-
{
+
+
time_t Number;
enum _MERIDIAN Meridian;
-}
-/* Line 187 of yacc.c. */
- YYSTYPE;
+
+
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
#endif
#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
@@ -316,14 +260,10 @@ static int LookupWord(YYSTYPE* yylvalPtr, char *buff);
DateInfo* info, const char *s);
static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
DateInfo* info);
-static time_t ToSeconds(time_t Hours, time_t Minutes,
- time_t Seconds, MERIDIAN Meridian);
MODULE_SCOPE int yyparse(DateInfo*);
-/* Line 216 of yacc.c. */
-
#ifdef short
# undef short
@@ -359,15 +299,21 @@ typedef short int yytype_int16;
#ifndef YYSIZE_T
# ifdef __SIZE_TYPE__
# define YYSIZE_T __SIZE_TYPE__
-# else
+# elif defined size_t
# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
# endif
#endif
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#ifndef YY_
-# if YYENABLE_NLS
+# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -392,14 +338,14 @@ typedef short int yytype_int16;
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static int
-YYID (int i)
+YYID (int yyi)
#else
static int
-YYID (i)
- int i;
+YYID (yyi)
+ int yyi;
#endif
{
- return i;
+ return yyi;
}
#endif
@@ -481,9 +427,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
/* A type that is properly aligned for any stack member. */
union yyalloc
{
- yytype_int16 yyss;
- YYSTYPE yyvs;
- YYLTYPE yyls;
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+ YYLTYPE yyls_alloc;
};
/* The size of the maximum gap between one aligned stack and the next. */
@@ -518,12 +464,12 @@ union yyalloc
elements in the stack, and YYPTR gives the new location of the
stack. Advance YYPTR to a properly aligned location for the next
stack. */
-# define YYSTACK_RELOCATE(Stack) \
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
do \
{ \
YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack, Stack, yysize); \
- Stack = &yyptr->Stack; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
yyptr += yynewbytes / sizeof (*yyptr); \
} \
@@ -624,12 +570,12 @@ static const yytype_int8 yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 225, 225, 226, 229, 232, 235, 238, 241, 244,
- 247, 251, 256, 259, 265, 271, 279, 285, 296, 300,
- 304, 310, 314, 318, 322, 326, 332, 336, 341, 346,
- 351, 356, 360, 365, 369, 374, 381, 385, 391, 400,
- 409, 419, 433, 438, 441, 444, 447, 450, 453, 458,
- 461, 466, 470, 474, 480, 498, 501
+ 0, 176, 176, 177, 180, 183, 186, 189, 192, 195,
+ 198, 202, 207, 210, 216, 222, 230, 236, 247, 251,
+ 255, 261, 265, 269, 273, 277, 283, 287, 292, 297,
+ 302, 307, 311, 316, 320, 325, 332, 336, 342, 351,
+ 360, 370, 384, 389, 392, 395, 398, 401, 404, 409,
+ 412, 417, 421, 425, 431, 449, 452
};
#endif
@@ -783,9 +729,18 @@ static const yytype_uint8 yystos[] =
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
+ Once GCC version 2 has supplanted version 1, this can go. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
#define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
#define YYRECOVERING() (!!yyerrstatus)
@@ -842,7 +797,7 @@ while (YYID (0))
we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
+# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
(Loc).first_line, (Loc).first_column, \
@@ -961,17 +916,20 @@ yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, info)
#if (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
#else
static void
-yy_stack_print (bottom, top)
- yytype_int16 *bottom;
- yytype_int16 *top;
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
#endif
{
YYFPRINTF (stderr, "Stack now");
- for (; bottom <= top; ++bottom)
- YYFPRINTF (stderr, " %d", *bottom);
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
YYFPRINTF (stderr, "\n");
}
@@ -1007,11 +965,11 @@ yy_reduce_print (yyvsp, yylsp, yyrule, info)
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
- fprintf (stderr, " $%d = ", yyi + 1);
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
&(yyvsp[(yyi + 1) - (yynrhs)])
, &(yylsp[(yyi + 1) - (yynrhs)]) , info);
- fprintf (stderr, "\n");
+ YYFPRINTF (stderr, "\n");
}
}
@@ -1295,10 +1253,8 @@ yydestruct (yymsg, yytype, yyvaluep, yylocationp, info)
break;
}
}
-
/* Prevent warnings from -Wmissing-prototypes. */
-
#ifdef YYPARSE_PARAM
#if defined __STDC__ || defined __cplusplus
int yyparse (void *YYPARSE_PARAM);
@@ -1317,10 +1273,9 @@ int yyparse ();
-
-/*----------.
-| yyparse. |
-`----------*/
+/*-------------------------.
+| yyparse or yypush_parse. |
+`-------------------------*/
#ifdef YYPARSE_PARAM
#if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1344,88 +1299,97 @@ yyparse (info)
#endif
#endif
{
- /* The look-ahead symbol. */
+/* The lookahead symbol. */
int yychar;
-/* The semantic value of the look-ahead symbol. */
+/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;
-/* Number of syntax errors so far. */
-int yynerrs;
-/* Location data for the look-ahead symbol. */
+/* Location data for the lookahead symbol. */
YYLTYPE yylloc;
- int yystate;
- int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Look-ahead token as an internal (translated) token number. */
- int yytoken = 0;
-#if YYERROR_VERBOSE
- /* Buffer for error messages, and its allocated size. */
- char yymsgbuf[128];
- char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
- /* Three stacks and their tools:
- `yyss': related to states,
- `yyvs': related to semantic values,
- `yyls': related to locations.
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+ `yyls': related to locations.
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss = yyssa;
- yytype_int16 *yyssp;
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- YYSTYPE *yyvsp;
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
- /* The location stack. */
- YYLTYPE yylsa[YYINITDEPTH];
- YYLTYPE *yyls = yylsa;
- YYLTYPE *yylsp;
- /* The locations where the error started and ended. */
- YYLTYPE yyerror_range[2];
+ /* The location stack. */
+ YYLTYPE yylsa[YYINITDEPTH];
+ YYLTYPE *yyls;
+ YYLTYPE *yylsp;
-#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+ /* The locations where the error started and ended. */
+ YYLTYPE yyerror_range[2];
- YYSIZE_T yystacksize = YYINITDEPTH;
+ YYSIZE_T yystacksize;
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
YYLTYPE yyloc;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
/* The number of symbols on the RHS of the reduced rule.
Keep to zero when no symbol should be popped. */
int yylen = 0;
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yyls = yylsa;
+ yystacksize = YYINITDEPTH;
+
YYDPRINTF ((stderr, "Starting parse\n"));
yystate = 0;
yyerrstatus = 0;
yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
+ yychar = YYEMPTY; /* Cause a token to be read. */
/* Initialize stack pointers.
Waste one element of value and location stack
so that they stay on the same level as the state stack.
The wasted elements are never initialized. */
-
yyssp = yyss;
yyvsp = yyvs;
yylsp = yyls;
-#if YYLTYPE_IS_TRIVIAL
+
+#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
/* Initialize the default location before parsing starts. */
yylloc.first_line = yylloc.last_line = 1;
- yylloc.first_column = yylloc.last_column = 0;
+ yylloc.first_column = yylloc.last_column = 1;
#endif
goto yysetstate;
@@ -1464,6 +1428,7 @@ YYLTYPE yylloc;
&yyvs1, yysize * sizeof (*yyvsp),
&yyls1, yysize * sizeof (*yylsp),
&yystacksize);
+
yyls = yyls1;
yyss = yyss1;
yyvs = yyvs1;
@@ -1485,9 +1450,9 @@ YYLTYPE yylloc;
(union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
if (! yyptr)
goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss);
- YYSTACK_RELOCATE (yyvs);
- YYSTACK_RELOCATE (yyls);
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ YYSTACK_RELOCATE (yyls_alloc, yyls);
# undef YYSTACK_RELOCATE
if (yyss1 != yyssa)
YYSTACK_FREE (yyss1);
@@ -1508,6 +1473,9 @@ YYLTYPE yylloc;
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
goto yybackup;
/*-----------.
@@ -1516,16 +1484,16 @@ YYLTYPE yylloc;
yybackup:
/* Do appropriate processing given the current state. Read a
- look-ahead token if we need one and don't already have one. */
+ lookahead token if we need one and don't already have one. */
- /* First try to decide what to do without reference to look-ahead token. */
+ /* First try to decide what to do without reference to lookahead token. */
yyn = yypact[yystate];
if (yyn == YYPACT_NINF)
goto yydefault;
- /* Not known => get a look-ahead token if don't already have one. */
+ /* Not known => get a lookahead token if don't already have one. */
- /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
@@ -1557,20 +1525,16 @@ yybackup:
goto yyreduce;
}
- if (yyn == YYFINAL)
- YYACCEPT;
-
/* Count tokens shifted since error; after three, turn off error
status. */
if (yyerrstatus)
yyerrstatus--;
- /* Shift the look-ahead token. */
+ /* Shift the lookahead token. */
YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
- /* Discard the shifted token unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
yystate = yyn;
*++yyvsp = yylval;
@@ -2062,7 +2026,6 @@ yyreduce:
break;
-/* Line 1267 of yacc.c. */
default: break;
}
@@ -2139,7 +2102,7 @@ yyerrlab:
if (yyerrstatus == 3)
{
- /* If just tried and failed to reuse look-ahead token after an
+ /* If just tried and failed to reuse lookahead token after an
error, discard it. */
if (yychar <= YYEOF)
@@ -2156,7 +2119,7 @@ yyerrlab:
}
}
- /* Else will try to reuse look-ahead token after shifting the error
+ /* Else will try to reuse lookahead token after shifting the error
token. */
goto yyerrlab1;
@@ -2214,14 +2177,11 @@ yyerrlab1:
YY_STACK_PRINT (yyss, yyssp);
}
- if (yyn == YYFINAL)
- YYACCEPT;
-
*++yyvsp = yylval;
yyerror_range[1] = yylloc;
/* Using YYLLOC is tempting, but would change the location of
- the look-ahead. YYLOC is available though. */
+ the lookahead. YYLOC is available though. */
YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
*++yylsp = yyloc;
@@ -2246,7 +2206,7 @@ yyabortlab:
yyresult = 1;
goto yyreturn;
-#ifndef yyoverflow
+#if !defined(yyoverflow) || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here. |
`-------------------------------------------------*/
@@ -2257,7 +2217,7 @@ yyexhaustedlab:
#endif
yyreturn:
- if (yychar != YYEOF && yychar != YYEMPTY)
+ if (yychar != YYEMPTY)
yydestruct ("Cleanup: discarding lookahead",
yytoken, &yylval, &yylloc, info);
/* Do not reclaim the symbols of the rule which action triggered
@@ -2513,7 +2473,7 @@ TclDateerror(
infoPtr->separatrix = "\n";
}
-static time_t
+time_t
ToSeconds(
time_t Hours,
time_t Minutes,
@@ -2680,7 +2640,7 @@ TclDatelex(
location->first_column = yyInput - info->dateStart;
for ( ; ; ) {
- while (TclIsSpaceProc(*yyInput)) {
+ while (isspace(UCHAR(*yyInput))) {
yyInput++;
}
@@ -2740,36 +2700,20 @@ TclDatelex(
} while (Count > 0);
}
}
-
+
int
-TclClockOldscanObjCmd(
- ClientData clientData, /* Unused */
+TclClockFreeScan(
Tcl_Interp *interp, /* Tcl interpreter */
- int objc, /* Count of paraneters */
- Tcl_Obj *const *objv) /* Parameters */
+ DateInfo *info) /* Input and result parameters */
{
- Tcl_Obj *result, *resultElement;
- int yr, mo, da;
- DateInfo dateInfo;
- DateInfo* info = &dateInfo;
int status;
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "stringToParse baseYear baseMonth baseDay" );
- return TCL_ERROR;
- }
-
- yyInput = Tcl_GetString( objv[1] );
- dateInfo.dateStart = yyInput;
+ /*
+ * yyInput = stringToParse;
+ * yyYear = baseYear; yyMonth = baseMonth; yyDay = baseDay;
+ */
yyHaveDate = 0;
- if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
- || Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
- || Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
- return TCL_ERROR;
- }
- yyYear = yr; yyMonth = mo; yyDay = da;
yyHaveTime = 0;
yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24;
@@ -2786,19 +2730,20 @@ TclClockOldscanObjCmd(
yyHaveRel = 0;
yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;
- dateInfo.messages = Tcl_NewObj();
- dateInfo.separatrix = "";
- Tcl_IncrRefCount(dateInfo.messages);
+ info->messages = Tcl_NewObj();
+ info->separatrix = "";
+ Tcl_IncrRefCount(info->messages);
- status = yyparse(&dateInfo);
+ info->dateStart = yyInput;
+ status = yyparse(info);
if (status == 1) {
- Tcl_SetObjResult(interp, dateInfo.messages);
- Tcl_DecrRefCount(dateInfo.messages);
+ Tcl_SetObjResult(interp, info->messages);
+ Tcl_DecrRefCount(info->messages);
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL);
return TCL_ERROR;
} else if (status == 2) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
- Tcl_DecrRefCount(dateInfo.messages);
+ Tcl_DecrRefCount(info->messages);
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
return TCL_ERROR;
} else if (status != 0) {
@@ -2806,11 +2751,11 @@ TclClockOldscanObjCmd(
"from date parser. Please "
"report this error as a "
"bug in Tcl.", -1));
- Tcl_DecrRefCount(dateInfo.messages);
+ Tcl_DecrRefCount(info->messages);
Tcl_SetErrorCode(interp, "TCL", "BUG", NULL);
return TCL_ERROR;
}
- Tcl_DecrRefCount(dateInfo.messages);
+ Tcl_DecrRefCount(info->messages);
if (yyHaveDate > 1) {
Tcl_SetObjResult(interp,
@@ -2843,6 +2788,40 @@ TclClockOldscanObjCmd(
return TCL_ERROR;
}
+ return TCL_OK;
+}
+
+int
+TclClockOldscanObjCmd(
+ ClientData clientData, /* Unused */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ int objc, /* Count of paraneters */
+ Tcl_Obj *const *objv) /* Parameters */
+{
+ Tcl_Obj *result, *resultElement;
+ int yr, mo, da;
+ DateInfo dateInfo;
+ DateInfo* info = &dateInfo;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "stringToParse baseYear baseMonth baseDay" );
+ return TCL_ERROR;
+ }
+
+ yyInput = Tcl_GetString( objv[1] );
+
+ if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ yyYear = yr; yyMonth = mo; yyDay = da;
+
+ if (TclClockFreeScan(interp, info) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
result = Tcl_NewObj();
resultElement = Tcl_NewObj();
if (yyHaveDate) {
diff --git a/generic/tclDate.h b/generic/tclDate.h
new file mode 100644
index 0000000..91e677f
--- /dev/null
+++ b/generic/tclDate.h
@@ -0,0 +1,77 @@
+/*
+ * tclDate.h --
+ *
+ * This header file handles common usage of clock primitives
+ * between tclDate.c (yacc) and tclClock.c.
+ *
+ * Copyright (c) 2014 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 _TCLCLOCK_H
+#define _TCLCLOCK_H
+
+/*
+ * Structure contains return parsed fields.
+ */
+
+typedef struct DateInfo {
+
+ Tcl_Obj* messages; /* Error messages */
+ const char* separatrix; /* String separating messages */
+
+ time_t dateYear;
+ time_t dateMonth;
+ time_t dateDay;
+ int dateHaveDate;
+
+ time_t dateHour;
+ time_t dateMinutes;
+ time_t dateSeconds;
+ int dateMeridian;
+ int dateHaveTime;
+
+ time_t dateTimezone;
+ int dateDSTmode;
+ int dateHaveZone;
+
+ time_t dateRelMonth;
+ time_t dateRelDay;
+ time_t dateRelSeconds;
+ int dateHaveRel;
+
+ time_t dateMonthOrdinal;
+ int dateHaveOrdinalMonth;
+
+ time_t dateDayOrdinal;
+ time_t dateDayNumber;
+ int dateHaveDay;
+
+ const char *dateStart;
+ const char *dateInput;
+ time_t *dateRelPointer;
+
+ int dateDigitCount;
+} DateInfo;
+
+
+/*
+ * Meridian: am, pm, or 24-hour style.
+ */
+
+typedef enum _MERIDIAN {
+ MERam, MERpm, MER24
+} MERIDIAN;
+
+/*
+ * Prototypes of module functions.
+ */
+
+MODULE_SCOPE time_t ToSeconds(time_t Hours, time_t Minutes,
+ time_t Seconds, MERIDIAN Meridian);
+
+MODULE_SCOPE int TclClockFreeScan(Tcl_Interp *interp, DateInfo *info);
+
+#endif /* _TCLCLOCK_H */
diff --git a/generic/tclGetDate.y b/generic/tclGetDate.y
index da4c3fd..ac781ad 100644
--- a/generic/tclGetDate.y
+++ b/generic/tclGetDate.y
@@ -50,44 +50,7 @@
* parsed fields will be returned.
*/
-typedef struct DateInfo {
-
- Tcl_Obj* messages; /* Error messages */
- const char* separatrix; /* String separating messages */
-
- time_t dateYear;
- time_t dateMonth;
- time_t dateDay;
- int dateHaveDate;
-
- time_t dateHour;
- time_t dateMinutes;
- time_t dateSeconds;
- int dateMeridian;
- int dateHaveTime;
-
- time_t dateTimezone;
- int dateDSTmode;
- int dateHaveZone;
-
- time_t dateRelMonth;
- time_t dateRelDay;
- time_t dateRelSeconds;
- int dateHaveRel;
-
- time_t dateMonthOrdinal;
- int dateHaveOrdinalMonth;
-
- time_t dateDayOrdinal;
- time_t dateDayNumber;
- int dateHaveDay;
-
- const char *dateStart;
- const char *dateInput;
- time_t *dateRelPointer;
-
- int dateDigitCount;
-} DateInfo;
+#include "tclDate.h"
#define YYMALLOC ckalloc
#define YYFREE(x) (ckfree((void*) (x)))
@@ -150,14 +113,6 @@ typedef enum _DSTMODE {
DSTon, DSToff, DSTmaybe
} DSTMODE;
-/*
- * Meridian: am, pm, or 24-hour style.
- */
-
-typedef enum _MERIDIAN {
- MERam, MERpm, MER24
-} MERIDIAN;
-
%}
%union {
@@ -176,8 +131,6 @@ static int LookupWord(YYSTYPE* yylvalPtr, char *buff);
DateInfo* info, const char *s);
static int TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
DateInfo* info);
-static time_t ToSeconds(time_t Hours, time_t Minutes,
- time_t Seconds, MERIDIAN Meridian);
MODULE_SCOPE int yyparse(DateInfo*);
%}
@@ -730,7 +683,7 @@ TclDateerror(
infoPtr->separatrix = "\n";
}
-static time_t
+time_t
ToSeconds(
time_t Hours,
time_t Minutes,
@@ -957,36 +910,20 @@ TclDatelex(
} while (Count > 0);
}
}
-
+
int
-TclClockOldscanObjCmd(
- ClientData clientData, /* Unused */
+TclClockFreeScan(
Tcl_Interp *interp, /* Tcl interpreter */
- int objc, /* Count of paraneters */
- Tcl_Obj *const *objv) /* Parameters */
+ DateInfo *info) /* Input and result parameters */
{
- Tcl_Obj *result, *resultElement;
- int yr, mo, da;
- DateInfo dateInfo;
- DateInfo* info = &dateInfo;
int status;
- if (objc != 5) {
- Tcl_WrongNumArgs(interp, 1, objv,
- "stringToParse baseYear baseMonth baseDay" );
- return TCL_ERROR;
- }
-
- yyInput = Tcl_GetString( objv[1] );
- dateInfo.dateStart = yyInput;
+ /*
+ * yyInput = stringToParse;
+ * yyYear = baseYear; yyMonth = baseMonth; yyDay = baseDay;
+ */
yyHaveDate = 0;
- if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
- || Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
- || Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
- return TCL_ERROR;
- }
- yyYear = yr; yyMonth = mo; yyDay = da;
yyHaveTime = 0;
yyHour = 0; yyMinutes = 0; yySeconds = 0; yyMeridian = MER24;
@@ -1003,19 +940,20 @@ TclClockOldscanObjCmd(
yyHaveRel = 0;
yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;
- dateInfo.messages = Tcl_NewObj();
- dateInfo.separatrix = "";
- Tcl_IncrRefCount(dateInfo.messages);
+ info->messages = Tcl_NewObj();
+ info->separatrix = "";
+ Tcl_IncrRefCount(info->messages);
- status = yyparse(&dateInfo);
+ info->dateStart = yyInput;
+ status = yyparse(info);
if (status == 1) {
- Tcl_SetObjResult(interp, dateInfo.messages);
- Tcl_DecrRefCount(dateInfo.messages);
+ Tcl_SetObjResult(interp, info->messages);
+ Tcl_DecrRefCount(info->messages);
Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL);
return TCL_ERROR;
} else if (status == 2) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("memory exhausted", -1));
- Tcl_DecrRefCount(dateInfo.messages);
+ Tcl_DecrRefCount(info->messages);
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
return TCL_ERROR;
} else if (status != 0) {
@@ -1023,11 +961,11 @@ TclClockOldscanObjCmd(
"from date parser. Please "
"report this error as a "
"bug in Tcl.", -1));
- Tcl_DecrRefCount(dateInfo.messages);
+ Tcl_DecrRefCount(info->messages);
Tcl_SetErrorCode(interp, "TCL", "BUG", NULL);
return TCL_ERROR;
}
- Tcl_DecrRefCount(dateInfo.messages);
+ Tcl_DecrRefCount(info->messages);
if (yyHaveDate > 1) {
Tcl_SetObjResult(interp,
@@ -1060,6 +998,40 @@ TclClockOldscanObjCmd(
return TCL_ERROR;
}
+ return TCL_OK;
+}
+
+int
+TclClockOldscanObjCmd(
+ ClientData clientData, /* Unused */
+ Tcl_Interp *interp, /* Tcl interpreter */
+ int objc, /* Count of paraneters */
+ Tcl_Obj *const *objv) /* Parameters */
+{
+ Tcl_Obj *result, *resultElement;
+ int yr, mo, da;
+ DateInfo dateInfo;
+ DateInfo* info = &dateInfo;
+
+ if (objc != 5) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "stringToParse baseYear baseMonth baseDay" );
+ return TCL_ERROR;
+ }
+
+ yyInput = Tcl_GetString( objv[1] );
+
+ if (Tcl_GetIntFromObj(interp, objv[2], &yr) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[3], &mo) != TCL_OK
+ || Tcl_GetIntFromObj(interp, objv[4], &da) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ yyYear = yr; yyMonth = mo; yyDay = da;
+
+ if (TclClockFreeScan(interp, info) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
result = Tcl_NewObj();
resultElement = Tcl_NewObj();
if (yyHaveDate) {
diff --git a/library/clock.tcl b/library/clock.tcl
index 5b48eb3..9c3f95c 100755
--- a/library/clock.tcl
+++ b/library/clock.tcl
@@ -287,6 +287,10 @@ proc ::tcl::clock::Initialize {} {
variable FEB_28 58
+ # Current year century and year of century switch
+ variable CurrentYearCentury 2000
+ variable YearOfCenturySwitch 37
+
# Translation table to map Windows TZI onto cities, so that the Olson
# rules can apply. In some cases the mapping is ambiguous, so it's wise
# to specify $::env(TCL_TZ) rather than simply depending on the system
@@ -1295,7 +1299,7 @@ proc ::tcl::clock::__org_scan { args } {
#
#----------------------------------------------------------------------
-proc ::tcl::clock::FreeScan { string base timezone locale } {
+proc ::tcl::clock::__org_FreeScan { string base timezone locale } {
variable TZData
@@ -1341,7 +1345,8 @@ proc ::tcl::clock::FreeScan { string base timezone locale } {
if { [llength $parseDate] > 0 } {
lassign $parseDate y m d
if { $y < 100 } {
- if { $y >= 39 } {
+ variable YearOfCenturySwitch
+ if { $y > $YearOfCenturySwitch } {
incr y 1900
} else {
incr y 2000
@@ -2719,12 +2724,14 @@ proc ::tcl::clock::ScanWide { str } {
proc ::tcl::clock::InterpretTwoDigitYear { date baseTime
{ twoDigitField yearOfCentury }
{ fourDigitField year } } {
+ variable CurrentYearCentury
+ variable YearOfCenturySwitch
set yr [dict get $date $twoDigitField]
- if { $yr <= 37 } {
- dict set date $fourDigitField [expr { $yr + 2000 }]
- } else {
- dict set date $fourDigitField [expr { $yr + 1900 }]
+ incr yr $CurrentYearCentury
+ if { $yr <= $YearOfCenturySwitch } {
+ incr yr -100
}
+ dict set date $fourDigitField $yr
return $date
}
diff --git a/library/init.tcl b/library/init.tcl
index e6df12b..4bbce51 100644
--- a/library/init.tcl
+++ b/library/init.tcl
@@ -178,7 +178,7 @@ if {[interp issafe]} {
# Auto-loading stubs for 'clock.tcl'
- foreach cmd {add format FreeScan} {
+ foreach cmd {add format} {
proc ::tcl::clock::$cmd args {
variable TclLibDir
source -encoding utf-8 [file join $TclLibDir clock.tcl]
diff --git a/win/makefile.vc b/win/makefile.vc
index d6de5e1..26ee669 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -482,7 +482,9 @@ cdebug = $(cdebug) -Zi
### Warnings are too many, can't support warnings into errors.
cdebug = -Zi -Od $(DEBUGFLAGS)
!else
-cdebug = -Zi -WX $(DEBUGFLAGS)
+# no -WX option here (error C2220: warning treated as error):
+#cdebug = -Zi -WX $(DEBUGFLAGS)
+cdebug = -Zi $(DEBUGFLAGS)
!endif
### Declarations common to all compiler options