summaryrefslogtreecommitdiffstats
path: root/generic/tclClock.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclClock.c')
-rw-r--r--generic/tclClock.c878
1 files changed, 404 insertions, 474 deletions
diff --git a/generic/tclClock.c b/generic/tclClock.c
index dee6253..782c681 100644
--- a/generic/tclClock.c
+++ b/generic/tclClock.c
@@ -5,22 +5,21 @@
* the time and date facilities of TclX, by Mark Diekhans and Karl
* Lehenbauer.
*
- * Copyright © 1991-1995 Karl Lehenbauer & Mark Diekhans.
- * Copyright © 1995 Sun Microsystems, Inc.
- * Copyright © 2004 Kevin B. Kenny. All rights reserved.
+ * Copyright 1991-1995 Karl Lehenbauer and Mark Diekhans.
+ * Copyright (c) 1995 Sun Microsystems, Inc.
+ * Copyright (c) 2004 by Kevin B. Kenny. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclTomMath.h"
/*
* Windows has mktime. The configurators do not check.
*/
-#ifdef _WIN32
+#ifdef __WIN32__
#define HAVE_MKTIME 1
#endif
@@ -32,17 +31,21 @@
#define SECONDS_PER_DAY 86400
#define JULIAN_SEC_POSIX_EPOCH (((Tcl_WideInt) JULIAN_DAY_POSIX_EPOCH) \
* SECONDS_PER_DAY)
-#define FOUR_CENTURIES 146097 /* days */
+#define FOUR_CENTURIES 146097 /* days */
#define JDAY_1_JAN_1_CE_JULIAN 1721424
#define JDAY_1_JAN_1_CE_GREGORIAN 1721426
-#define ONE_CENTURY_GREGORIAN 36524 /* days */
-#define FOUR_YEARS 1461 /* days */
-#define ONE_YEAR 365 /* days */
+#define ONE_CENTURY_GREGORIAN 36524 /* days */
+#define FOUR_YEARS 1461 /* days */
+#define ONE_YEAR 365 /* days */
/*
* Table of the days in each month, leap and common years
*/
+static const int hath[2][12] = {
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+};
static const int daysInPriorMonths[2][13] = {
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
@@ -55,7 +58,7 @@ static const int daysInPriorMonths[2][13] = {
typedef enum ClockLiteral {
LIT__NIL,
LIT__DEFAULT_FORMAT,
- LIT_BCE, LIT_C,
+ LIT_BCE, LIT_C,
LIT_CANNOT_USE_GMT_AND_TIMEZONE,
LIT_CE,
LIT_DAYOFMONTH, LIT_DAYOFWEEK, LIT_DAYOFYEAR,
@@ -71,7 +74,7 @@ typedef enum ClockLiteral {
static const char *const literals[] = {
"",
"%a %b %d %H:%M:%S %Z %Y",
- "BCE", "C",
+ "BCE", "C",
"cannot use -gmt and -timezone in same call",
"CE",
"dayOfMonth", "dayOfWeek", "dayOfYear",
@@ -88,25 +91,25 @@ static const char *const literals[] = {
* Structure containing the client data for [clock]
*/
-typedef struct {
- size_t refCount; /* Number of live references. */
- Tcl_Obj **literals; /* Pool of object literals. */
+typedef struct ClockClientData {
+ int refCount; /* Number of live references */
+ Tcl_Obj** literals; /* Pool of object literals */
} ClockClientData;
/*
* Structure containing the fields used in [clock format] and [clock scan]
*/
-typedef struct {
+typedef struct TclDateFields {
Tcl_WideInt seconds; /* Time expressed in seconds from the Posix
* epoch */
Tcl_WideInt localSeconds; /* Local time expressed in nominal seconds
* from the Posix epoch */
int tzOffset; /* Time zone offset in seconds east of
* Greenwich */
- Tcl_Obj *tzName; /* Time zone name */
+ Tcl_Obj* tzName; /* Time zone name */
int julianDay; /* Julian Day Number in local time zone */
- int isBce; /* 1 if BCE */
+ enum {BCE=1, CE=0} era; /* Era */
int gregorian; /* Flag == 1 if the date is Gregorian */
int year; /* Year of the era */
int dayOfYear; /* Day of the year (1 January == 1) */
@@ -116,7 +119,7 @@ typedef struct {
int iso8601Week; /* ISO8601 week number */
int dayOfWeek; /* Day of the week */
} TclDateFields;
-static const char *const eras[] = { "CE", "BCE", NULL };
+static const char* eras[] = { "CE", "BCE", NULL };
/*
* Thread specific data block holding a 'struct tm' for the 'gmtime' and
@@ -136,40 +139,60 @@ TCL_DECLARE_MUTEX(clockMutex)
* Function prototypes for local procedures in this file:
*/
-static int ConvertUTCToLocal(Tcl_Interp *,
- TclDateFields *, Tcl_Obj *, int);
-static int ConvertUTCToLocalUsingTable(Tcl_Interp *,
- TclDateFields *, Tcl_Size, Tcl_Obj *const[]);
-static int ConvertUTCToLocalUsingC(Tcl_Interp *,
- TclDateFields *, int);
-static int ConvertLocalToUTC(Tcl_Interp *,
- TclDateFields *, Tcl_Obj *, int);
-static int ConvertLocalToUTCUsingTable(Tcl_Interp *,
- TclDateFields *, Tcl_Size, Tcl_Obj *const[]);
-static int ConvertLocalToUTCUsingC(Tcl_Interp *,
- TclDateFields *, int);
-static Tcl_Obj * LookupLastTransition(Tcl_Interp *, Tcl_WideInt,
- Tcl_Size, Tcl_Obj *const *);
-static void GetYearWeekDay(TclDateFields *, int);
-static void GetGregorianEraYearDay(TclDateFields *, int);
-static void GetMonthDay(TclDateFields *);
-static void GetJulianDayFromEraYearWeekDay(TclDateFields *, int);
-static void GetJulianDayFromEraYearMonthDay(TclDateFields *, int);
-static int IsGregorianLeapYear(TclDateFields *);
-static Tcl_WideInt WeekdayOnOrBefore(int, Tcl_WideInt);
-static Tcl_ObjCmdProc ClockClicksObjCmd;
-static Tcl_ObjCmdProc ClockConvertlocaltoutcObjCmd;
-static Tcl_ObjCmdProc ClockGetdatefieldsObjCmd;
-static Tcl_ObjCmdProc ClockGetjuliandayfromerayearmonthdayObjCmd;
-static Tcl_ObjCmdProc ClockGetjuliandayfromerayearweekdayObjCmd;
-static Tcl_ObjCmdProc ClockGetenvObjCmd;
-static Tcl_ObjCmdProc ClockMicrosecondsObjCmd;
-static Tcl_ObjCmdProc ClockMillisecondsObjCmd;
-static Tcl_ObjCmdProc ClockParseformatargsObjCmd;
-static Tcl_ObjCmdProc ClockSecondsObjCmd;
+static int ConvertUTCToLocal(Tcl_Interp*,
+ TclDateFields*, Tcl_Obj*, int);
+static int ConvertUTCToLocalUsingTable(Tcl_Interp*,
+ TclDateFields*, int, Tcl_Obj *const[]);
+static int ConvertUTCToLocalUsingC(Tcl_Interp*,
+ TclDateFields*, int);
+static int ConvertLocalToUTC(Tcl_Interp*,
+ TclDateFields*, Tcl_Obj*, int);
+static int ConvertLocalToUTCUsingTable(Tcl_Interp*,
+ TclDateFields*, int, Tcl_Obj *const[]);
+static int ConvertLocalToUTCUsingC(Tcl_Interp*,
+ TclDateFields*, int);
+static Tcl_Obj* LookupLastTransition(Tcl_Interp*, Tcl_WideInt,
+ int, Tcl_Obj *const *);
+static void GetYearWeekDay(TclDateFields*, int);
+static void GetGregorianEraYearDay(TclDateFields*, int);
+static void GetMonthDay(TclDateFields*);
+static void GetJulianDayFromEraYearWeekDay(TclDateFields*, int);
+static void GetJulianDayFromEraYearMonthDay(TclDateFields*, int);
+static int IsGregorianLeapYear(TclDateFields*);
+static int WeekdayOnOrBefore(int, int);
+static int ClockClicksObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockConvertlocaltoutcObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockGetdatefieldsObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockGetjuliandayfromerayearmonthdayObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockGetjuliandayfromerayearweekdayObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockGetenvObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockMicrosecondsObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockMillisecondsObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockParseformatargsObjCmd(
+ ClientData clientData, Tcl_Interp* interp,
+ int objc, Tcl_Obj *const objv[]);
+static int ClockSecondsObjCmd(
+ ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
static struct tm * ThreadSafeLocalTime(const time_t *);
static void TzsetIfNecessary(void);
-static void ClockDeleteCmdProc(void *);
+static void ClockDeleteCmdProc(ClientData);
/*
* Structure containing description of "native" clock commands to create.
@@ -185,16 +208,20 @@ struct ClockCommand {
};
static const struct ClockCommand clockCommands[] = {
- {"getenv", ClockGetenvObjCmd},
- {"Oldscan", TclClockOldscanObjCmd},
- {"ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd},
- {"GetDateFields", ClockGetdatefieldsObjCmd},
- {"GetJulianDayFromEraYearMonthDay",
- ClockGetjuliandayfromerayearmonthdayObjCmd},
- {"GetJulianDayFromEraYearWeekDay",
- ClockGetjuliandayfromerayearweekdayObjCmd},
- {"ParseFormatArgs", ClockParseformatargsObjCmd},
- {NULL, NULL}
+ { "clicks", ClockClicksObjCmd },
+ { "getenv", ClockGetenvObjCmd },
+ { "microseconds", ClockMicrosecondsObjCmd },
+ { "milliseconds", ClockMillisecondsObjCmd },
+ { "seconds", ClockSecondsObjCmd },
+ { "Oldscan", TclClockOldscanObjCmd },
+ { "ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd },
+ { "GetDateFields", ClockGetdatefieldsObjCmd },
+ { "GetJulianDayFromEraYearMonthDay",
+ ClockGetjuliandayfromerayearmonthdayObjCmd },
+ { "GetJulianDayFromEraYearWeekDay",
+ ClockGetjuliandayfromerayearweekdayObjCmd },
+ { "ParseFormatArgs", ClockParseformatargsObjCmd },
+ { NULL, NULL }
};
/*
@@ -222,25 +249,12 @@ TclClockInit(
const struct ClockCommand *clockCmdPtr;
char cmdName[50]; /* Buffer large enough to hold the string
*::tcl::clock::GetJulianDayFromEraYearMonthDay
- * plus a terminating NUL. */
+ * plus a terminating NULL. */
ClockClientData *data;
int i;
- /* Structure of the 'clock' ensemble */
-
- static const EnsembleImplMap clockImplMap[] = {
- {"add", NULL, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
- {"clicks", ClockClicksObjCmd, TclCompileClockClicksCmd, NULL, NULL, 0},
- {"format", NULL, TclCompileBasicMin1ArgCmd, NULL, NULL, 0},
- {"microseconds", ClockMicrosecondsObjCmd, TclCompileClockReadingCmd, NULL, INT2PTR(1), 0},
- {"milliseconds", ClockMillisecondsObjCmd, TclCompileClockReadingCmd, NULL, INT2PTR(2), 0},
- {"scan", NULL, TclCompileBasicMin1ArgCmd, NULL, NULL , 0},
- {"seconds", ClockSecondsObjCmd, TclCompileClockReadingCmd, NULL, INT2PTR(3), 0},
- {NULL, NULL, NULL, NULL, NULL, 0}
- };
-
/*
- * Safe interps get [::clock] as alias to a parent, so do not need their
+ * Safe interps get [::clock] as alias to a master, so do not need their
* own copies of the support routines.
*/
@@ -252,9 +266,9 @@ TclClockInit(
* Create the client data, which is a refcounted literal pool.
*/
- data = (ClockClientData *)ckalloc(sizeof(ClockClientData));
+ data = (ClockClientData *) ckalloc(sizeof(ClockClientData));
data->refCount = 0;
- data->literals = (Tcl_Obj **)ckalloc(LIT__END * sizeof(Tcl_Obj*));
+ data->literals = (Tcl_Obj**) ckalloc(LIT__END * sizeof(Tcl_Obj*));
for (i = 0; i < LIT__END; ++i) {
data->literals[i] = Tcl_NewStringObj(literals[i], -1);
Tcl_IncrRefCount(data->literals[i]);
@@ -262,21 +276,16 @@ TclClockInit(
/*
* Install the commands.
- * TODO - Let Tcl_MakeEnsemble do this?
*/
+ strcpy(cmdName, "::tcl::clock::");
#define TCL_CLOCK_PREFIX_LEN 14 /* == strlen("::tcl::clock::") */
- memcpy(cmdName, "::tcl::clock::", TCL_CLOCK_PREFIX_LEN);
for (clockCmdPtr=clockCommands ; clockCmdPtr->name!=NULL ; clockCmdPtr++) {
strcpy(cmdName + TCL_CLOCK_PREFIX_LEN, clockCmdPtr->name);
data->refCount++;
Tcl_CreateObjCommand(interp, cmdName, clockCmdPtr->objCmdProc, data,
ClockDeleteCmdProc);
}
-
- /* Make the clock ensemble */
-
- TclMakeEnsemble(interp, "clock", clockImplMap);
}
/*
@@ -308,14 +317,15 @@ TclClockInit(
static int
ClockConvertlocaltoutcObjCmd(
- void *clientData, /* Client data */
- Tcl_Interp *interp, /* Tcl interpreter */
+ ClientData clientData, /* Client data */
+ Tcl_Interp* interp, /* Tcl interpreter */
int objc, /* Parameter count */
Tcl_Obj *const *objv) /* Parameter vector */
{
- ClockClientData *data = (ClockClientData *)clientData;
- Tcl_Obj *secondsObj;
- Tcl_Obj *dict;
+ ClockClientData* data = (ClockClientData*) clientData;
+ Tcl_Obj* const * literals = data->literals;
+ Tcl_Obj* secondsObj;
+ Tcl_Obj* dict;
int changeover;
TclDateFields fields;
int created = 0;
@@ -330,17 +340,17 @@ ClockConvertlocaltoutcObjCmd(
return TCL_ERROR;
}
dict = objv[1];
- if (Tcl_DictObjGet(interp, dict, data->literals[LIT_LOCALSECONDS],
- &secondsObj)!= TCL_OK) {
+ if (Tcl_DictObjGet(interp, dict, literals[LIT_LOCALSECONDS],
+ &secondsObj)!= TCL_OK) {
return TCL_ERROR;
}
if (secondsObj == NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj("key \"localseconds\" not "
- "found in dictionary", -1));
+ "found in dictionary", -1));
return TCL_ERROR;
}
- if ((TclGetWideIntFromObj(interp, secondsObj,
- &fields.localSeconds) != TCL_OK)
+ if ((Tcl_GetWideIntFromObj(interp, secondsObj,
+ &(fields.localSeconds)) != TCL_OK)
|| (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK)
|| ConvertLocalToUTC(interp, &fields, objv[2], changeover)) {
return TCL_ERROR;
@@ -356,7 +366,7 @@ ClockConvertlocaltoutcObjCmd(
created = 1;
Tcl_IncrRefCount(dict);
}
- status = Tcl_DictObjPut(interp, dict, data->literals[LIT_SECONDS],
+ status = Tcl_DictObjPut(interp, dict, literals[LIT_SECONDS],
Tcl_NewWideIntObj(fields.seconds));
if (status == TCL_OK) {
Tcl_SetObjResult(interp, dict);
@@ -380,16 +390,16 @@ ClockConvertlocaltoutcObjCmd(
*
* Parameters:
* seconds - Time expressed in seconds from the Posix epoch.
- * tzdata - Time zone data of the time zone in which time is to be
- * expressed.
+ * tzdata - Time zone data of the time zone in which time is to
+ * be expressed.
* changeover - Julian Day Number at which the current locale adopted
* the Gregorian calendar
*
* Results:
* Returns a dictonary populated with the fields:
* seconds - Seconds from the Posix epoch
- * localSeconds - Nominal seconds from the Posix epoch in the
- * local time zone.
+ * localSeconds - Nominal seconds from the Posix epoch in
+ * the local time zone.
* tzOffset - Time zone offset in seconds east of Greenwich
* tzName - Time zone name
* julianDay - Julian Day Number in the local time zone
@@ -399,15 +409,15 @@ ClockConvertlocaltoutcObjCmd(
int
ClockGetdatefieldsObjCmd(
- void *clientData, /* Opaque pointer to literal pool, etc. */
- Tcl_Interp *interp, /* Tcl interpreter */
+ ClientData clientData, /* Opaque pointer to literal pool, etc. */
+ Tcl_Interp* interp, /* Tcl interpreter */
int objc, /* Parameter count */
Tcl_Obj *const *objv) /* Parameter vector */
{
TclDateFields fields;
- Tcl_Obj *dict;
- ClockClientData *data = (ClockClientData *)clientData;
- Tcl_Obj *const *lit = data->literals;
+ Tcl_Obj* dict;
+ ClockClientData* data = (ClockClientData*) clientData;
+ Tcl_Obj* const * literals = data->literals;
int changeover;
/*
@@ -418,18 +428,18 @@ ClockGetdatefieldsObjCmd(
Tcl_WrongNumArgs(interp, 1, objv, "seconds tzdata changeover");
return TCL_ERROR;
}
- if (TclGetWideIntFromObj(interp, objv[1], &fields.seconds) != TCL_OK
+ if (Tcl_GetWideIntFromObj(interp, objv[1], &(fields.seconds)) != TCL_OK
|| TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK) {
return TCL_ERROR;
}
- /*
- * fields.seconds could be an unsigned number that overflowed. Make sure
- * that it isn't.
+ /*
+ * fields.seconds could be an unsigned number that overflowed. Make
+ * sure that it isn't.
*/
- if (TclHasInternalRep(objv[1], &tclBignumType)) {
- Tcl_SetObjResult(interp, lit[LIT_INTEGER_VALUE_TOO_LARGE]);
+ if (objv[1]->typePtr == &tclBignumType) {
+ Tcl_SetObjResult(interp, literals[LIT_INTEGER_VALUE_TOO_LARGE]);
return TCL_ERROR;
}
@@ -442,13 +452,11 @@ ClockGetdatefieldsObjCmd(
}
/*
- * Extract Julian day. Always round the quotient down by subtracting 1
- * when the remainder is negative (i.e. if the quotient was rounded up).
+ * Extract Julian day.
*/
- fields.julianDay = (int) ((fields.localSeconds / SECONDS_PER_DAY) -
- ((fields.localSeconds % SECONDS_PER_DAY) < 0) +
- JULIAN_DAY_POSIX_EPOCH);
+ fields.julianDay = (int) ((fields.localSeconds + JULIAN_SEC_POSIX_EPOCH)
+ / SECONDS_PER_DAY);
/*
* Convert to Julian or Gregorian calendar.
@@ -459,34 +467,34 @@ ClockGetdatefieldsObjCmd(
GetYearWeekDay(&fields, changeover);
dict = Tcl_NewDictObj();
- Tcl_DictObjPut(NULL, dict, lit[LIT_LOCALSECONDS],
+ Tcl_DictObjPut(NULL, dict, literals[LIT_LOCALSECONDS],
Tcl_NewWideIntObj(fields.localSeconds));
- Tcl_DictObjPut(NULL, dict, lit[LIT_SECONDS],
+ Tcl_DictObjPut(NULL, dict, literals[LIT_SECONDS],
Tcl_NewWideIntObj(fields.seconds));
- Tcl_DictObjPut(NULL, dict, lit[LIT_TZNAME], fields.tzName);
+ Tcl_DictObjPut(NULL, dict, literals[LIT_TZNAME], fields.tzName);
Tcl_DecrRefCount(fields.tzName);
- Tcl_DictObjPut(NULL, dict, lit[LIT_TZOFFSET],
- Tcl_NewWideIntObj(fields.tzOffset));
- Tcl_DictObjPut(NULL, dict, lit[LIT_JULIANDAY],
- Tcl_NewWideIntObj(fields.julianDay));
- Tcl_DictObjPut(NULL, dict, lit[LIT_GREGORIAN],
- Tcl_NewWideIntObj(fields.gregorian));
- Tcl_DictObjPut(NULL, dict, lit[LIT_ERA],
- lit[fields.isBce ? LIT_BCE : LIT_CE]);
- Tcl_DictObjPut(NULL, dict, lit[LIT_YEAR],
- Tcl_NewWideIntObj(fields.year));
- Tcl_DictObjPut(NULL, dict, lit[LIT_DAYOFYEAR],
- Tcl_NewWideIntObj(fields.dayOfYear));
- Tcl_DictObjPut(NULL, dict, lit[LIT_MONTH],
- Tcl_NewWideIntObj(fields.month));
- Tcl_DictObjPut(NULL, dict, lit[LIT_DAYOFMONTH],
- Tcl_NewWideIntObj(fields.dayOfMonth));
- Tcl_DictObjPut(NULL, dict, lit[LIT_ISO8601YEAR],
- Tcl_NewWideIntObj(fields.iso8601Year));
- Tcl_DictObjPut(NULL, dict, lit[LIT_ISO8601WEEK],
- Tcl_NewWideIntObj(fields.iso8601Week));
- Tcl_DictObjPut(NULL, dict, lit[LIT_DAYOFWEEK],
- Tcl_NewWideIntObj(fields.dayOfWeek));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_TZOFFSET],
+ Tcl_NewIntObj(fields.tzOffset));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_JULIANDAY],
+ Tcl_NewIntObj(fields.julianDay));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_GREGORIAN],
+ Tcl_NewIntObj(fields.gregorian));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_ERA],
+ literals[fields.era ? LIT_BCE : LIT_CE]);
+ Tcl_DictObjPut(NULL, dict, literals[LIT_YEAR],
+ Tcl_NewIntObj(fields.year));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_DAYOFYEAR],
+ Tcl_NewIntObj(fields.dayOfYear));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_MONTH],
+ Tcl_NewIntObj(fields.month));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_DAYOFMONTH],
+ Tcl_NewIntObj(fields.dayOfMonth));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_ISO8601YEAR],
+ Tcl_NewIntObj(fields.iso8601Year));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_ISO8601WEEK],
+ Tcl_NewIntObj(fields.iso8601Week));
+ Tcl_DictObjPut(NULL, dict, literals[LIT_DAYOFWEEK],
+ Tcl_NewIntObj(fields.dayOfWeek));
Tcl_SetObjResult(interp, dict);
return TCL_OK;
@@ -514,60 +522,21 @@ ClockGetdatefieldsObjCmd(
*/
static int
-FetchEraField(
- Tcl_Interp *interp,
- Tcl_Obj *dict,
- Tcl_Obj *key,
- int *storePtr)
-{
- Tcl_Obj *value = NULL;
-
- if (Tcl_DictObjGet(interp, dict, key, &value) != TCL_OK) {
- return TCL_ERROR;
- }
- if (value == NULL) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "expected key(s) not found in dictionary", -1));
- return TCL_ERROR;
- }
- return Tcl_GetIndexFromObj(interp, value, eras, "era", TCL_EXACT, storePtr);
-}
-
-static int
-FetchIntField(
- Tcl_Interp *interp,
- Tcl_Obj *dict,
- Tcl_Obj *key,
- int *storePtr)
-{
- Tcl_Obj *value = NULL;
-
- if (Tcl_DictObjGet(interp, dict, key, &value) != TCL_OK) {
- return TCL_ERROR;
- }
- if (value == NULL) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "expected key(s) not found in dictionary", -1));
- return TCL_ERROR;
- }
- return TclGetIntFromObj(interp, value, storePtr);
-}
-
-static int
-ClockGetjuliandayfromerayearmonthdayObjCmd(
- void *clientData, /* Opaque pointer to literal pool, etc. */
- Tcl_Interp *interp, /* Tcl interpreter */
+ClockGetjuliandayfromerayearmonthdayObjCmd (
+ ClientData clientData, /* Opaque pointer to literal pool, etc. */
+ Tcl_Interp* interp, /* Tcl interpreter */
int objc, /* Parameter count */
Tcl_Obj *const *objv) /* Parameter vector */
{
TclDateFields fields;
- Tcl_Obj *dict;
- ClockClientData *data = (ClockClientData *)clientData;
- Tcl_Obj *const *lit = data->literals;
+ Tcl_Obj* dict;
+ ClockClientData* data = (ClockClientData*) clientData;
+ Tcl_Obj* const * literals = data->literals;
+ Tcl_Obj* fieldPtr;
int changeover;
int copied = 0;
int status;
- int isBce = 0;
+ int era = 0;
/*
* Check params.
@@ -578,17 +547,27 @@ ClockGetjuliandayfromerayearmonthdayObjCmd(
return TCL_ERROR;
}
dict = objv[1];
- if (FetchEraField(interp, dict, lit[LIT_ERA], &isBce) != TCL_OK
- || FetchIntField(interp, dict, lit[LIT_YEAR], &fields.year)
- != TCL_OK
- || FetchIntField(interp, dict, lit[LIT_MONTH], &fields.month)
- != TCL_OK
- || FetchIntField(interp, dict, lit[LIT_DAYOFMONTH],
- &fields.dayOfMonth) != TCL_OK
+ if (Tcl_DictObjGet(interp, dict, literals[LIT_ERA], &fieldPtr) != TCL_OK
+ || fieldPtr == NULL
+ || Tcl_GetIndexFromObj(interp, fieldPtr, eras, "era", TCL_EXACT,
+ &era) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_YEAR], &fieldPtr) != TCL_OK
+ || fieldPtr == NULL
+ || TclGetIntFromObj(interp, fieldPtr, &(fields.year)) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_MONTH], &fieldPtr) != TCL_OK
+ || fieldPtr == NULL
+ || TclGetIntFromObj(interp, fieldPtr, &(fields.month)) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_DAYOFMONTH], &fieldPtr) != TCL_OK
+ || fieldPtr == NULL
+ || TclGetIntFromObj(interp, fieldPtr,
+ &(fields.dayOfMonth)) != TCL_OK
|| TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) {
+ if (fieldPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("expected key(s) not found in dictionary", -1));
+ }
return TCL_ERROR;
}
- fields.isBce = isBce;
+ fields.era = era;
/*
* Get Julian day.
@@ -605,8 +584,8 @@ ClockGetjuliandayfromerayearmonthdayObjCmd(
Tcl_IncrRefCount(dict);
copied = 1;
}
- status = Tcl_DictObjPut(interp, dict, lit[LIT_JULIANDAY],
- Tcl_NewWideIntObj(fields.julianDay));
+ status = Tcl_DictObjPut(interp, dict, literals[LIT_JULIANDAY],
+ Tcl_NewIntObj(fields.julianDay));
if (status == TCL_OK) {
Tcl_SetObjResult(interp, dict);
}
@@ -638,20 +617,21 @@ ClockGetjuliandayfromerayearmonthdayObjCmd(
*/
static int
-ClockGetjuliandayfromerayearweekdayObjCmd(
- void *clientData, /* Opaque pointer to literal pool, etc. */
- Tcl_Interp *interp, /* Tcl interpreter */
+ClockGetjuliandayfromerayearweekdayObjCmd (
+ ClientData clientData, /* Opaque pointer to literal pool, etc. */
+ Tcl_Interp* interp, /* Tcl interpreter */
int objc, /* Parameter count */
Tcl_Obj *const *objv) /* Parameter vector */
{
TclDateFields fields;
- Tcl_Obj *dict;
- ClockClientData *data = (ClockClientData *)clientData;
- Tcl_Obj *const *lit = data->literals;
+ Tcl_Obj* dict;
+ ClockClientData* data = (ClockClientData*) clientData;
+ Tcl_Obj* const * literals = data->literals;
+ Tcl_Obj* fieldPtr;
int changeover;
int copied = 0;
int status;
- int isBce = 0;
+ int era = 0;
/*
* Check params.
@@ -662,17 +642,26 @@ ClockGetjuliandayfromerayearweekdayObjCmd(
return TCL_ERROR;
}
dict = objv[1];
- if (FetchEraField(interp, dict, lit[LIT_ERA], &isBce) != TCL_OK
- || FetchIntField(interp, dict, lit[LIT_ISO8601YEAR],
- &fields.iso8601Year) != TCL_OK
- || FetchIntField(interp, dict, lit[LIT_ISO8601WEEK],
- &fields.iso8601Week) != TCL_OK
- || FetchIntField(interp, dict, lit[LIT_DAYOFWEEK],
- &fields.dayOfWeek) != TCL_OK
+ if (Tcl_DictObjGet(interp, dict, literals[LIT_ERA], &fieldPtr) != TCL_OK
+ || fieldPtr == NULL
+ || Tcl_GetIndexFromObj(interp, fieldPtr, eras, "era", TCL_EXACT,
+ &era) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_ISO8601YEAR], &fieldPtr) != TCL_OK
+ || fieldPtr == NULL
+ || TclGetIntFromObj(interp, fieldPtr, &(fields.iso8601Year)) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_ISO8601WEEK], &fieldPtr) != TCL_OK
+ || fieldPtr == NULL
+ || TclGetIntFromObj(interp, fieldPtr, &(fields.iso8601Week)) != TCL_OK
+ || Tcl_DictObjGet(interp, dict, literals[LIT_DAYOFWEEK], &fieldPtr) != TCL_OK
+ || fieldPtr == NULL
+ || TclGetIntFromObj(interp, fieldPtr, &(fields.dayOfWeek)) != TCL_OK
|| TclGetIntFromObj(interp, objv[2], &changeover) != TCL_OK) {
+ if (fieldPtr == NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("expected key(s) not found in dictionary", -1));
+ }
return TCL_ERROR;
}
- fields.isBce = isBce;
+ fields.era = era;
/*
* Get Julian day.
@@ -689,8 +678,8 @@ ClockGetjuliandayfromerayearweekdayObjCmd(
Tcl_IncrRefCount(dict);
copied = 1;
}
- status = Tcl_DictObjPut(interp, dict, lit[LIT_JULIANDAY],
- Tcl_NewWideIntObj(fields.julianDay));
+ status = Tcl_DictObjPut(interp, dict, literals[LIT_JULIANDAY],
+ Tcl_NewIntObj(fields.julianDay));
if (status == TCL_OK) {
Tcl_SetObjResult(interp, dict);
}
@@ -720,13 +709,13 @@ ClockGetjuliandayfromerayearweekdayObjCmd(
static int
ConvertLocalToUTC(
- Tcl_Interp *interp, /* Tcl interpreter */
- TclDateFields *fields, /* Fields of the time */
- Tcl_Obj *tzdata, /* Time zone data */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Fields of the time */
+ Tcl_Obj* tzdata, /* Time zone data */
int changeover) /* Julian Day of the Gregorian transition */
{
- Tcl_Size rowc; /* Number of rows in tzdata */
- Tcl_Obj **rowv; /* Pointers to the rows */
+ int rowc; /* Number of rows in tzdata */
+ Tcl_Obj** rowv; /* Pointers to the rows */
/*
* Unpack the tz data.
@@ -768,14 +757,14 @@ ConvertLocalToUTC(
static int
ConvertLocalToUTCUsingTable(
- Tcl_Interp *interp, /* Tcl interpreter */
- TclDateFields *fields, /* Time to convert, with 'seconds' filled in */
- Tcl_Size rowc, /* Number of points at which time changes */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Time to convert, with 'seconds' filled in */
+ int rowc, /* Number of points at which time changes */
Tcl_Obj *const rowv[]) /* Points at which time changes */
{
- Tcl_Obj *row;
- Tcl_Size cellc;
- Tcl_Obj **cellv;
+ Tcl_Obj* row;
+ int cellc;
+ Tcl_Obj** cellv;
int have[8];
int nHave = 0;
int i;
@@ -800,7 +789,7 @@ ConvertLocalToUTCUsingTable(
|| TclListObjGetElements(interp, row, &cellc,
&cellv) != TCL_OK
|| TclGetIntFromObj(interp, cellv[1],
- &fields->tzOffset) != TCL_OK) {
+ &(fields->tzOffset)) != TCL_OK) {
return TCL_ERROR;
}
found = 0;
@@ -814,7 +803,8 @@ ConvertLocalToUTCUsingTable(
if (nHave == 8) {
Tcl_Panic("loop in ConvertLocalToUTCUsingTable");
}
- have[nHave++] = fields->tzOffset;
+ have[nHave] = fields->tzOffset;
+ ++nHave;
}
fields->seconds = fields->localSeconds - fields->tzOffset;
}
@@ -843,8 +833,8 @@ ConvertLocalToUTCUsingTable(
static int
ConvertLocalToUTCUsingC(
- Tcl_Interp *interp, /* Tcl interpreter */
- TclDateFields *fields, /* Time to convert, with 'seconds' filled in */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Time to convert, with 'seconds' filled in */
int changeover) /* Julian Day of the Gregorian transition */
{
struct tm timeVal;
@@ -861,7 +851,7 @@ ConvertLocalToUTCUsingC(
secondOfDay = (int)(jsec % SECONDS_PER_DAY);
if (secondOfDay < 0) {
secondOfDay += SECONDS_PER_DAY;
- fields->julianDay--;
+ --fields->julianDay;
}
GetGregorianEraYearDay(fields, changeover);
GetMonthDay(fields);
@@ -889,7 +879,7 @@ ConvertLocalToUTCUsingC(
Tcl_MutexLock(&clockMutex);
errno = 0;
fields->seconds = (Tcl_WideInt) mktime(&timeVal);
- localErrno = (fields->seconds == -1) ? errno : 0;
+ localErrno = errno;
Tcl_MutexUnlock(&clockMutex);
/*
@@ -898,8 +888,8 @@ ConvertLocalToUTCUsingC(
if (localErrno != 0
|| (fields->seconds == -1 && timeVal.tm_yday == -1)) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "time value too large/small to represent", -1));
+ Tcl_SetResult(interp, "time value too large/small to represent",
+ TCL_STATIC);
return TCL_ERROR;
}
return TCL_OK;
@@ -923,13 +913,13 @@ ConvertLocalToUTCUsingC(
static int
ConvertUTCToLocal(
- Tcl_Interp *interp, /* Tcl interpreter */
- TclDateFields *fields, /* Fields of the time */
- Tcl_Obj *tzdata, /* Time zone data */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Fields of the time */
+ Tcl_Obj* tzdata, /* Time zone data */
int changeover) /* Julian Day of the Gregorian transition */
{
- Tcl_Size rowc; /* Number of rows in tzdata */
- Tcl_Obj **rowv; /* Pointers to the rows */
+ int rowc; /* Number of rows in tzdata */
+ Tcl_Obj** rowv; /* Pointers to the rows */
/*
* Unpack the tz data.
@@ -971,15 +961,15 @@ ConvertUTCToLocal(
static int
ConvertUTCToLocalUsingTable(
- Tcl_Interp *interp, /* Tcl interpreter */
- TclDateFields *fields, /* Fields of the date */
- Tcl_Size rowc, /* Number of rows in the conversion table
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Fields of the date */
+ int rowc, /* Number of rows in the conversion table
* (>= 1) */
Tcl_Obj *const rowv[]) /* Rows of the conversion table */
{
- Tcl_Obj *row; /* Row containing the current information */
- Tcl_Size cellc; /* Count of cells in the row (must be 4) */
- Tcl_Obj **cellv; /* Pointers to the cells */
+ Tcl_Obj* row; /* Row containing the current information */
+ int cellc; /* Count of cells in the row (must be 4) */
+ Tcl_Obj** cellv; /* Pointers to the cells */
/*
* Look up the nearest transition time.
@@ -988,7 +978,7 @@ ConvertUTCToLocalUsingTable(
row = LookupLastTransition(interp, fields->seconds, rowc, rowv);
if (row == NULL ||
TclListObjGetElements(interp, row, &cellc, &cellv) != TCL_OK ||
- TclGetIntFromObj(interp, cellv[1], &fields->tzOffset) != TCL_OK) {
+ TclGetIntFromObj(interp,cellv[1],&(fields->tzOffset)) != TCL_OK) {
return TCL_ERROR;
}
@@ -1023,14 +1013,14 @@ ConvertUTCToLocalUsingTable(
static int
ConvertUTCToLocalUsingC(
- Tcl_Interp *interp, /* Tcl interpreter */
- TclDateFields *fields, /* Time to convert, with 'seconds' filled in */
+ Tcl_Interp* interp, /* Tcl interpreter */
+ TclDateFields* fields, /* Time to convert, with 'seconds' filled in */
int changeover) /* Julian Day of the Gregorian transition */
{
time_t tock;
- struct tm *timeVal; /* Time after conversion */
+ struct tm* timeVal; /* Time after conversion */
int diff; /* Time zone diff local-Greenwich */
- char buffer[16]; /* Buffer for time zone name */
+ char buffer[8]; /* Buffer for time zone name */
/*
* Use 'localtime' to determine local year, month, day, time of day.
@@ -1038,18 +1028,18 @@ ConvertUTCToLocalUsingC(
tock = (time_t) fields->seconds;
if ((Tcl_WideInt) tock != fields->seconds) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "number too large to represent as a Posix time", -1));
- Tcl_SetErrorCode(interp, "CLOCK", "argTooLarge", (char *)NULL);
+ Tcl_AppendResult(interp,
+ "number too large to represent as a Posix time", NULL);
+ Tcl_SetErrorCode(interp, "CLOCK", "argTooLarge", NULL);
return TCL_ERROR;
}
TzsetIfNecessary();
timeVal = ThreadSafeLocalTime(&tock);
if (timeVal == NULL) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ Tcl_AppendResult(interp,
"localtime failed (clock value may be too "
- "large/small to represent)", -1));
- Tcl_SetErrorCode(interp, "CLOCK", "localtimeFailed", (char *)NULL);
+ "large/small to represent)", NULL);
+ Tcl_SetErrorCode(interp, "CLOCK", "localtimeFailed", NULL);
return TCL_ERROR;
}
@@ -1057,7 +1047,7 @@ ConvertUTCToLocalUsingC(
* Fill in the date in 'fields' and use it to derive Julian Day.
*/
- fields->isBce = 0;
+ fields->era = CE;
fields->year = timeVal->tm_year + 1900;
fields->month = timeVal->tm_mon + 1;
fields->dayOfMonth = timeVal->tm_mday;
@@ -1083,12 +1073,12 @@ ConvertUTCToLocalUsingC(
} else {
*buffer = '+';
}
- snprintf(buffer+1, sizeof(buffer) - 1, "%02d", diff / 3600);
+ sprintf(buffer+1, "%02d", diff / 3600);
diff %= 3600;
- snprintf(buffer+3, sizeof(buffer) - 3, "%02d", diff / 60);
+ sprintf(buffer+3, "%02d", diff / 60);
diff %= 60;
if (diff > 0) {
- snprintf(buffer+5, sizeof(buffer) - 5, "%02d", diff);
+ sprintf(buffer+5, "%02d", diff);
}
fields->tzName = Tcl_NewStringObj(buffer, -1);
Tcl_IncrRefCount(fields->tzName);
@@ -1109,15 +1099,16 @@ ConvertUTCToLocalUsingC(
*----------------------------------------------------------------------
*/
-static Tcl_Obj *
+static Tcl_Obj*
LookupLastTransition(
- Tcl_Interp *interp, /* Interpreter for error messages */
+ Tcl_Interp* interp, /* Interpreter for error messages */
Tcl_WideInt tick, /* Time from the epoch */
- Tcl_Size rowc, /* Number of rows of tzdata */
+ int rowc, /* Number of rows of tzdata */
Tcl_Obj *const *rowv) /* Rows in tzdata */
{
- Tcl_Size l, u;
- Tcl_Obj *compObj;
+ int l;
+ int u;
+ Tcl_Obj* compObj;
Tcl_WideInt compVal;
/*
@@ -1125,7 +1116,7 @@ LookupLastTransition(
*/
if (Tcl_ListObjIndex(interp, rowv[0], 0, &compObj) != TCL_OK
- || TclGetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
+ || Tcl_GetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
return NULL;
}
@@ -1145,10 +1136,10 @@ LookupLastTransition(
l = 0;
u = rowc-1;
while (l < u) {
- Tcl_Size m = (l + u + 1) / 2;
+ int m = (l + u + 1) / 2;
if (Tcl_ListObjIndex(interp, rowv[m], 0, &compObj) != TCL_OK ||
- TclGetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
+ Tcl_GetWideIntFromObj(interp, compObj, &compVal) != TCL_OK) {
return NULL;
}
if (tick >= compVal) {
@@ -1180,7 +1171,7 @@ LookupLastTransition(
static void
GetYearWeekDay(
- TclDateFields *fields, /* Date to convert, must have 'julianDay' */
+ TclDateFields* fields, /* Date to convert, must have 'julianDay' */
int changeover) /* Julian Day Number of the Gregorian
* transition */
{
@@ -1194,7 +1185,7 @@ GetYearWeekDay(
temp.julianDay = fields->julianDay - 3;
GetGregorianEraYearDay(&temp, changeover);
- if (temp.isBce) {
+ if (temp.era == BCE) {
temp.iso8601Year = temp.year - 1;
} else {
temp.iso8601Year = temp.year + 1;
@@ -1210,7 +1201,7 @@ GetYearWeekDay(
*/
if (fields->julianDay < temp.julianDay) {
- if (temp.isBce) {
+ if (temp.era == BCE) {
temp.iso8601Year += 1;
} else {
temp.iso8601Year -= 1;
@@ -1247,13 +1238,13 @@ GetYearWeekDay(
static void
GetGregorianEraYearDay(
- TclDateFields *fields, /* Date fields containing 'julianDay' */
+ TclDateFields* fields, /* Date fields containing 'julianDay' */
int changeover) /* Gregorian transition date */
{
- Tcl_WideInt jday = fields->julianDay;
- Tcl_WideInt day;
- Tcl_WideInt year;
- Tcl_WideInt n;
+ int jday = fields->julianDay;
+ int day;
+ int year;
+ int n;
if (jday >= changeover) {
/*
@@ -1273,7 +1264,7 @@ GetGregorianEraYearDay(
day %= FOUR_CENTURIES;
if (day < 0) {
day += FOUR_CENTURIES;
- n--;
+ --n;
}
year += 400 * n;
@@ -1293,6 +1284,7 @@ GetGregorianEraYearDay(
day += ONE_CENTURY_GREGORIAN;
}
year += 100 * n;
+
} else {
/*
* Julian calendar.
@@ -1301,6 +1293,7 @@ GetGregorianEraYearDay(
fields->gregorian = 0;
year = 1;
day = jday - JDAY_1_JAN_1_CE_JULIAN;
+
}
/*
@@ -1311,7 +1304,7 @@ GetGregorianEraYearDay(
day %= FOUR_YEARS;
if (day < 0) {
day += FOUR_YEARS;
- n--;
+ --n;
}
year += 4 * n;
@@ -1336,10 +1329,10 @@ GetGregorianEraYearDay(
*/
if (year <= 0) {
- fields->isBce = 1;
+ fields->era = BCE;
fields->year = 1 - year;
} else {
- fields->isBce = 0;
+ fields->era = CE;
fields->year = year;
}
fields->dayOfYear = day + 1;
@@ -1363,31 +1356,15 @@ GetGregorianEraYearDay(
static void
GetMonthDay(
- TclDateFields *fields) /* Date to convert */
+ TclDateFields* fields) /* Date to convert */
{
int day = fields->dayOfYear;
int month;
- const int *dipm = daysInPriorMonths[IsGregorianLeapYear(fields)];
+ const int* h = hath[IsGregorianLeapYear(fields)];
- /*
- * Estimate month by calculating `dayOfYear / (365/12)`
- */
- month = (day*12) / dipm[12];
- /* then do forwards backwards correction */
- while (1) {
- if (day > dipm[month]) {
- if (month >= 11 || day <= dipm[month+1]) {
- break;
- }
- month++;
- } else {
- if (month == 0) {
- break;
- }
- month--;
- }
+ for (month = 0; month < 12 && day > h[month]; ++month) {
+ day -= h[month];
}
- day -= dipm[month];
fields->month = month+1;
fields->dayOfMonth = day;
}
@@ -1411,19 +1388,19 @@ GetMonthDay(
static void
GetJulianDayFromEraYearWeekDay(
- TclDateFields *fields, /* Date to convert */
+ TclDateFields* fields, /* Date to convert */
int changeover) /* Julian Day Number of the Gregorian
* transition */
{
- Tcl_WideInt firstMonday; /* Julian day number of week 1, day 1 in the
+ int firstMonday; /* Julian day number of week 1, day 1 in the
* given year */
- TclDateFields firstWeek;
/*
* Find January 4 in the ISO8601 year, which will always be in week 1.
*/
- firstWeek.isBce = fields->isBce;
+ TclDateFields firstWeek;
+ firstWeek.era = fields->era;
firstWeek.year = fields->iso8601Year;
firstWeek.month = 1;
firstWeek.dayOfMonth = 4;
@@ -1462,13 +1439,15 @@ GetJulianDayFromEraYearWeekDay(
static void
GetJulianDayFromEraYearMonthDay(
- TclDateFields *fields, /* Date to convert */
+ TclDateFields* fields, /* Date to convert */
int changeover) /* Gregorian transition date as a Julian Day */
{
- Tcl_WideInt year, ym1, ym1o4, ym1o100, ym1o400;
- int month, mm1, q, r;
+ int year; int ym1;
+ int month; int mm1;
+ int q; int r;
+ int ym1o4; int ym1o100; int ym1o400;
- if (fields->isBce) {
+ if (fields->era == BCE) {
year = 1 - fields->year;
} else {
year = fields->year;
@@ -1496,10 +1475,10 @@ GetJulianDayFromEraYearMonthDay(
fields->gregorian = 1;
if (year < 1) {
- fields->isBce = 1;
+ fields->era = BCE;
fields->year = 1-year;
} else {
- fields->isBce = 0;
+ fields->era = CE;
fields->year = year;
}
@@ -1507,29 +1486,17 @@ GetJulianDayFromEraYearMonthDay(
* Try an initial conversion in the Gregorian calendar.
*/
-#if 0 /* BUG https://core.tcl-lang.org/tcl/tktview?name=da340d4f32 */
ym1o4 = ym1 / 4;
-#else
- /*
- * Have to make sure quotient is truncated towards 0 when negative.
- * See above bug for details. The casts are necessary.
- */
- if (ym1 >= 0) {
- ym1o4 = ym1 / 4;
- } else {
- ym1o4 = - (int) (((unsigned int) -ym1) / 4);
- }
-#endif
if (ym1 % 4 < 0) {
- ym1o4--;
+ --ym1o4;
}
ym1o100 = ym1 / 100;
if (ym1 % 100 < 0) {
- ym1o100--;
+ --ym1o100;
}
ym1o400 = ym1 / 400;
if (ym1 % 400 < 0) {
- ym1o400--;
+ --ym1o400;
}
fields->julianDay = JDAY_1_JAN_1_CE_GREGORIAN - 1
+ fields->dayOfMonth
@@ -1549,8 +1516,8 @@ GetJulianDayFromEraYearMonthDay(
fields->julianDay = JDAY_1_JAN_1_CE_JULIAN - 1
+ fields->dayOfMonth
+ daysInPriorMonths[year%4 == 0][month - 1]
- + (365 * ym1)
- + ym1o4;
+ + (ONE_YEAR * ym1)
+ + ym1o4;
}
}
@@ -1570,12 +1537,14 @@ GetJulianDayFromEraYearMonthDay(
static int
IsGregorianLeapYear(
- TclDateFields *fields) /* Date to test */
+ TclDateFields* fields) /* Date to test */
{
- Tcl_WideInt year = fields->year;
+ int year;
- if (fields->isBce) {
- year = 1 - year;
+ if (fields->era == BCE) {
+ year = 1 - fields->year;
+ } else {
+ year = fields->year;
}
if (year%4 != 0) {
return 0;
@@ -1604,10 +1573,10 @@ IsGregorianLeapYear(
*----------------------------------------------------------------------
*/
-static Tcl_WideInt
+static int
WeekdayOnOrBefore(
int dayOfWeek, /* Day of week; Sunday == 0 or 7 */
- Tcl_WideInt julianDay) /* Reference date */
+ int julianDay) /* Reference date */
{
int k = (dayOfWeek + 6) % 7;
if (k < 0) {
@@ -1639,42 +1608,24 @@ WeekdayOnOrBefore(
int
ClockGetenvObjCmd(
- TCL_UNUSED(void *),
- Tcl_Interp *interp,
+ ClientData clientData,
+ Tcl_Interp* interp,
int objc,
Tcl_Obj *const objv[])
{
-#ifdef _WIN32
- const WCHAR *varName;
- const WCHAR *varValue;
- Tcl_DString ds;
-#else
- const char *varName;
- const char *varValue;
-#endif
+ const char* varName;
+ const char* varValue;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "name");
return TCL_ERROR;
}
-#ifdef _WIN32
- Tcl_DStringInit(&ds);
- varName = Tcl_UtfToWCharDString(TclGetString(objv[1]), -1, &ds);
- varValue = _wgetenv(varName);
- if (varValue == NULL) {
- Tcl_DStringFree(&ds);
- } else {
- Tcl_DStringSetLength(&ds, 0);
- Tcl_WCharToUtfDString(varValue, -1, &ds);
- Tcl_DStringResult(interp, &ds);
- }
-#else
varName = TclGetString(objv[1]);
varValue = getenv(varName);
- if (varValue != NULL) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(varValue, -1));
+ if (varValue == NULL) {
+ varValue = "";
}
-#endif
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(varValue, -1));
return TCL_OK;
}
@@ -1704,9 +1655,10 @@ ThreadSafeLocalTime(
* Get a thread-local buffer to hold the returned time.
*/
- struct tm *tmPtr = (struct tm *)Tcl_GetThreadData(&tmKey, sizeof(struct tm));
+ struct tm *tmPtr = (struct tm *)
+ Tcl_GetThreadData(&tmKey, (int) sizeof(struct tm));
#ifdef HAVE_LOCALTIME_R
- tmPtr = localtime_r(timePtr, tmPtr);
+ localtime_r(timePtr, tmPtr);
#else
struct tm *sysTmPtr;
@@ -1715,9 +1667,10 @@ ThreadSafeLocalTime(
if (sysTmPtr == NULL) {
Tcl_MutexUnlock(&clockMutex);
return NULL;
+ } else {
+ memcpy((void *) tmPtr, (void *) localtime(timePtr), sizeof(struct tm));
+ Tcl_MutexUnlock(&clockMutex);
}
- memcpy(tmPtr, sysTmPtr, sizeof(struct tm));
- Tcl_MutexUnlock(&clockMutex);
#endif
return tmPtr;
}
@@ -1742,20 +1695,19 @@ ThreadSafeLocalTime(
int
ClockClicksObjCmd(
- TCL_UNUSED(void *),
- Tcl_Interp *interp, /* Tcl interpreter */
+ ClientData clientData, /* Client data is unused */
+ Tcl_Interp* interp, /* Tcl interpreter */
int objc, /* Parameter count */
- Tcl_Obj *const *objv) /* Parameter values */
+ Tcl_Obj* const* objv) /* Parameter values */
{
- static const char *const clicksSwitches[] = {
+ static const char *clicksSwitches[] = {
"-milliseconds", "-microseconds", NULL
};
enum ClicksSwitch {
- CLICKS_MILLIS, CLICKS_MICROS, CLICKS_NATIVE
+ CLICKS_MILLIS, CLICKS_MICROS, CLICKS_NATIVE
};
int index = CLICKS_NATIVE;
Tcl_Time now;
- Tcl_WideInt clicks = 0;
switch (objc) {
case 1:
@@ -1767,28 +1719,32 @@ ClockClicksObjCmd(
}
break;
default:
- Tcl_WrongNumArgs(interp, 1, objv, "?-switch?");
+ Tcl_WrongNumArgs(interp, 1, objv, "?option?");
return TCL_ERROR;
}
switch (index) {
case CLICKS_MILLIS:
Tcl_GetTime(&now);
- clicks = (Tcl_WideInt)now.sec * 1000 + now.usec / 1000;
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)
+ now.sec * 1000 + now.usec / 1000));
break;
- case CLICKS_NATIVE:
-#ifdef TCL_WIDE_CLICKS
- clicks = TclpGetWideClicks();
+ case CLICKS_NATIVE: {
+#ifndef TCL_WIDE_CLICKS
+ unsigned long clicks = TclpGetClicks();
#else
- clicks = (Tcl_WideInt)TclpGetClicks();
+ Tcl_WideInt clicks = TclpGetWideClicks();
#endif
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) clicks));
break;
+ }
case CLICKS_MICROS:
- clicks = TclpGetMicroseconds();
+ Tcl_GetTime(&now);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
+ ((Tcl_WideInt) now.sec * 1000000) + now.usec));
break;
}
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(clicks));
return TCL_OK;
}
@@ -1812,22 +1768,20 @@ ClockClicksObjCmd(
int
ClockMillisecondsObjCmd(
- TCL_UNUSED(void *),
- Tcl_Interp *interp, /* Tcl interpreter */
+ ClientData clientData, /* Client data is unused */
+ Tcl_Interp* interp, /* Tcl interpreter */
int objc, /* Parameter count */
- Tcl_Obj *const *objv) /* Parameter values */
+ Tcl_Obj* const* objv) /* Parameter values */
{
Tcl_Time now;
- Tcl_Obj *timeObj;
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
Tcl_GetTime(&now);
- TclNewUIntObj(timeObj, (Tcl_WideUInt)
- now.sec * 1000 + now.usec / 1000);
- Tcl_SetObjResult(interp, timeObj);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj( (Tcl_WideInt)
+ now.sec * 1000 + now.usec / 1000));
return TCL_OK;
}
@@ -1851,16 +1805,20 @@ ClockMillisecondsObjCmd(
int
ClockMicrosecondsObjCmd(
- TCL_UNUSED(void *),
- Tcl_Interp *interp, /* Tcl interpreter */
+ ClientData clientData, /* Client data is unused */
+ Tcl_Interp* interp, /* Tcl interpreter */
int objc, /* Parameter count */
- Tcl_Obj *const *objv) /* Parameter values */
+ Tcl_Obj* const* objv) /* Parameter values */
{
+ Tcl_Time now;
+
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(TclpGetMicroseconds()));
+ Tcl_GetTime(&now);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
+ ((Tcl_WideInt) now.sec * 1000000) + now.usec));
return TCL_OK;
}
@@ -1872,66 +1830,69 @@ ClockMicrosecondsObjCmd(
* Parses the arguments for [clock format].
*
* Results:
- * Returns a standard Tcl result, whose value is a four-element list
- * comprising the time format, the locale, and the timezone.
+ * Returns a standard Tcl result, whose value is a four-element
+ * list comprising the time format, the locale, and the timezone.
*
* This function exists because the loop that parses the [clock format]
- * options is a known performance "hot spot", and is implemented in an effort
- * to speed that particular code up.
+ * options is a known performance "hot spot", and is implemented in an
+ * effort to speed that particular code up.
*
*-----------------------------------------------------------------------------
*/
static int
ClockParseformatargsObjCmd(
- void *clientData, /* Client data containing literal pool */
- Tcl_Interp *interp, /* Tcl interpreter */
+ ClientData clientData, /* Client data containing literal pool */
+ Tcl_Interp* interp, /* Tcl interpreter */
int objc, /* Parameter count */
- Tcl_Obj *const objv[]) /* Parameter vector */
-{
- ClockClientData *dataPtr = (ClockClientData *)clientData;
- Tcl_Obj **litPtr = dataPtr->literals;
- Tcl_Obj *results[3]; /* Format, locale and timezone */
+ Tcl_Obj *const objv[] /* Parameter vector */
+) {
+
+ ClockClientData* dataPtr = (ClockClientData*) clientData;
+ Tcl_Obj** litPtr = dataPtr->literals;
+
+ /* Format, locale and timezone */
+
+ Tcl_Obj* results[3];
#define formatObj results[0]
#define localeObj results[1]
#define timezoneObj results[2]
int gmtFlag = 0;
- static const char *const options[] = { /* Command line options expected */
- "-format", "-gmt", "-locale",
- "-timezone", NULL };
+
+ /* Command line options expected */
+
+ static const char* options[] = {
+ "-format", "-gmt", "-locale",
+ "-timezone", NULL };
enum optionInd {
CLOCK_FORMAT_FORMAT, CLOCK_FORMAT_GMT, CLOCK_FORMAT_LOCALE,
- CLOCK_FORMAT_TIMEZONE
+ CLOCK_FORMAT_TIMEZONE
};
- int optionIndex; /* Index of an option. */
- int saw = 0; /* Flag == 1 if option was seen already. */
- Tcl_WideInt clockVal; /* Clock value - just used to parse. */
+ int optionIndex; /* Index of an option */
+ int saw = 0; /* Flag == 1 if option was seen already */
+ Tcl_WideInt clockVal; /* Clock value - just used to parse */
int i;
- /*
- * Args consist of a time followed by keyword-value pairs.
- */
+ /* Args consist of a time followed by keyword-value pairs */
if (objc < 2 || (objc % 2) != 0) {
Tcl_WrongNumArgs(interp, 0, objv,
- "clock format clockval ?-format string? "
- "?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?");
- Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", (char *)NULL);
+ "clock format clockval ?-format string? "
+ "?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?");
+ Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", NULL);
return TCL_ERROR;
}
- /*
- * Extract values for the keywords.
- */
+ /* Extract values for the keywords */
formatObj = litPtr[LIT__DEFAULT_FORMAT];
localeObj = litPtr[LIT_C];
timezoneObj = litPtr[LIT__NIL];
for (i = 2; i < objc; i+=2) {
- if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
- &optionIndex) != TCL_OK) {
- Tcl_SetErrorCode(interp, "CLOCK", "badOption",
- TclGetString(objv[i]), (char *)NULL);
+ if (Tcl_GetIndexFromObj(interp, objv[i], options, "switch", 0,
+ &optionIndex) != TCL_OK) {
+ Tcl_SetErrorCode(interp, "CLOCK", "badSwitch",
+ Tcl_GetString(objv[i]), NULL);
return TCL_ERROR;
}
switch (optionIndex) {
@@ -1939,7 +1900,7 @@ ClockParseformatargsObjCmd(
formatObj = objv[i+1];
break;
case CLOCK_FORMAT_GMT:
- if (Tcl_GetBooleanFromObj(interp, objv[i+1], &gmtFlag) != TCL_OK){
+ if (Tcl_GetBooleanFromObj(interp, objv[i+1], &gmtFlag) != TCL_OK) {
return TCL_ERROR;
}
break;
@@ -1950,29 +1911,25 @@ ClockParseformatargsObjCmd(
timezoneObj = objv[i+1];
break;
}
- saw |= 1 << optionIndex;
+ saw |= (1 << optionIndex);
}
- /*
- * Check options.
- */
+ /* Check options */
- if (TclGetWideIntFromObj(interp, objv[1], &clockVal) != TCL_OK) {
+ if (Tcl_GetWideIntFromObj(interp, objv[1], &clockVal) != TCL_OK) {
return TCL_ERROR;
}
if ((saw & (1 << CLOCK_FORMAT_GMT))
- && (saw & (1 << CLOCK_FORMAT_TIMEZONE))) {
+ && (saw & (1 << CLOCK_FORMAT_TIMEZONE))) {
Tcl_SetObjResult(interp, litPtr[LIT_CANNOT_USE_GMT_AND_TIMEZONE]);
- Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", (char *)NULL);
+ Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", NULL);
return TCL_ERROR;
}
if (gmtFlag) {
timezoneObj = litPtr[LIT_GMT];
}
- /*
- * Return options as a list.
- */
+ /* Return options as a list */
Tcl_SetObjResult(interp, Tcl_NewListObj(3, results));
return TCL_OK;
@@ -1980,6 +1937,7 @@ ClockParseformatargsObjCmd(
#undef timezoneObj
#undef localeObj
#undef formatObj
+
}
/*----------------------------------------------------------------------
@@ -2002,22 +1960,19 @@ ClockParseformatargsObjCmd(
int
ClockSecondsObjCmd(
- TCL_UNUSED(void *),
- Tcl_Interp *interp, /* Tcl interpreter */
+ ClientData clientData, /* Client data is unused */
+ Tcl_Interp* interp, /* Tcl interpreter */
int objc, /* Parameter count */
- Tcl_Obj *const *objv) /* Parameter values */
+ Tcl_Obj* const* objv) /* Parameter values */
{
Tcl_Time now;
- Tcl_Obj *timeObj;
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
Tcl_GetTime(&now);
- TclNewUIntObj(timeObj, (Tcl_WideUInt)now.sec);
-
- Tcl_SetObjResult(interp, timeObj);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) now.sec));
return TCL_OK;
}
@@ -2038,52 +1993,26 @@ ClockSecondsObjCmd(
*----------------------------------------------------------------------
*/
-#ifdef _WIN32
-#define getenv(x) _wgetenv(L##x)
-#else
-#define WCHAR char
-#define wcslen strlen
-#define wcscmp strcmp
-#define wcscpy strcpy
-#endif
-
static void
TzsetIfNecessary(void)
{
- static WCHAR* tzWas = (WCHAR *)INT2PTR(-1); /* Previous value of TZ, protected by
- * clockMutex. */
- static long tzLastRefresh = 0; /* Used for latency before next refresh */
- static size_t tzEnvEpoch = 0; /* Last env epoch, for faster signaling,
- that TZ changed via TCL */
- const WCHAR *tzIsNow; /* Current value of TZ */
-
- /*
- * Prevent performance regression on some platforms by resolving of system time zone:
- * small latency for check whether environment was changed (once per second)
- * no latency if environment was changed with tcl-env (compare both epoch values)
- */
- Tcl_Time now;
- Tcl_GetTime(&now);
- if (now.sec == tzLastRefresh && tzEnvEpoch == TclEnvEpoch) {
- return;
- }
-
- tzEnvEpoch = TclEnvEpoch;
- tzLastRefresh = now.sec;
+ static char* tzWas = INT2PTR(-1); /* Previous value of TZ, protected by
+ * clockMutex. */
+ const char* tzIsNow; /* Current value of TZ */
Tcl_MutexLock(&clockMutex);
tzIsNow = getenv("TZ");
- if (tzIsNow != NULL && (tzWas == NULL || tzWas == (WCHAR *)INT2PTR(-1)
- || wcscmp(tzIsNow, tzWas) != 0)) {
+ if (tzIsNow != NULL && (tzWas == NULL || tzWas == INT2PTR(-1)
+ || strcmp(tzIsNow, tzWas) != 0)) {
tzset();
- if (tzWas != NULL && tzWas != (WCHAR *)INT2PTR(-1)) {
+ if (tzWas != NULL && tzWas != INT2PTR(-1)) {
ckfree(tzWas);
}
- tzWas = (WCHAR *)ckalloc(sizeof(WCHAR) * (wcslen(tzIsNow) + 1));
- wcscpy(tzWas, tzIsNow);
+ tzWas = ckalloc(strlen(tzIsNow) + 1);
+ strcpy(tzWas, tzIsNow);
} else if (tzIsNow == NULL && tzWas != NULL) {
tzset();
- if (tzWas != (WCHAR *)INT2PTR(-1)) ckfree(tzWas);
+ if (tzWas != INT2PTR(-1)) ckfree(tzWas);
tzWas = NULL;
}
Tcl_MutexUnlock(&clockMutex);
@@ -2105,17 +2034,18 @@ TzsetIfNecessary(void)
static void
ClockDeleteCmdProc(
- void *clientData) /* Opaque pointer to the client data */
+ ClientData clientData) /* Opaque pointer to the client data */
{
- ClockClientData *data = (ClockClientData *)clientData;
+ ClockClientData *data = (ClockClientData*) clientData;
int i;
- if (data->refCount-- <= 1) {
+ --(data->refCount);
+ if (data->refCount == 0) {
for (i = 0; i < LIT__END; ++i) {
Tcl_DecrRefCount(data->literals[i]);
}
- ckfree(data->literals);
- ckfree(data);
+ ckfree((char*) (data->literals));
+ ckfree((char*) data);
}
}