diff options
Diffstat (limited to 'generic/tclClock.c')
| -rw-r--r-- | generic/tclClock.c | 878 |
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); } } |
