diff options
| -rw-r--r-- | generic/tclClock.c | 268 | ||||
| -rw-r--r-- | generic/tclClockFmt.c | 178 | ||||
| -rw-r--r-- | generic/tclDate.h | 116 | ||||
| -rw-r--r-- | generic/tclStrIdxTree.c | 2 |
4 files changed, 306 insertions, 258 deletions
diff --git a/generic/tclClock.c b/generic/tclClock.c index 5c428d2..722aba7 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -76,7 +76,7 @@ static int ConvertUTCToLocalUsingTable(Tcl_Interp *, Tcl_WideInt *rangesVal); static int ConvertUTCToLocalUsingC(Tcl_Interp *, TclDateFields *, int); -static int ConvertLocalToUTC(void *clientData, Tcl_Interp *, +static int ConvertLocalToUTC(ClockClientData *, Tcl_Interp *, TclDateFields *, Tcl_Obj *timezoneObj, int); static int ConvertLocalToUTCUsingTable(Tcl_Interp *, TclDateFields *, int, Tcl_Obj *const[], @@ -91,7 +91,7 @@ static void GetMonthDay(TclDateFields *); static Tcl_WideInt WeekdayOnOrBefore(int, Tcl_WideInt); static Tcl_ObjCmdProc ClockClicksObjCmd; static Tcl_ObjCmdProc ClockConvertlocaltoutcObjCmd; -static int ClockGetDateFields(void *clientData, +static int ClockGetDateFields(ClockClientData *, Tcl_Interp *interp, TclDateFields *fields, Tcl_Obj *timezoneObj, int changeover); static Tcl_ObjCmdProc ClockGetdatefieldsObjCmd; @@ -197,7 +197,8 @@ TclClockInit( data->refCount = 0; data->literals = (Tcl_Obj **) ckalloc(LIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < LIT__END; ++i) { - TclInitObjRef(data->literals[i], Tcl_NewStringObj(Literals[i], -1)); + TclInitObjRef(data->literals[i], Tcl_NewStringObj( + Literals[i], TCL_AUTO_LENGTH)); } data->mcLiterals = NULL; data->mcLitIdxs = NULL; @@ -374,19 +375,20 @@ ClockDeleteCmdProc( * * Used to store previously used/cached time zone (makes it reusable). * - * This enables faster switch between time zones (e. g. to convert from one to another). + * This enables faster switch between time zones (e. g. to convert from + * one to another). * * Results: * None. * *---------------------------------------------------------------------- */ - static inline void SavePrevTimezoneObj( ClockClientData *dataPtr) /* Client data containing literal pool */ { Tcl_Obj *timezoneObj = dataPtr->lastSetupTimeZone; + if (timezoneObj && timezoneObj != dataPtr->prevSetupTimeZone) { TclSetObjRef(dataPtr->prevSetupTimeZoneUnnorm, dataPtr->lastSetupTimeZoneUnnorm); TclSetObjRef(dataPtr->prevSetupTimeZone, timezoneObj); @@ -686,19 +688,20 @@ Tcl_Obj * ClockMCDict( ClockFmtScnCmdArgs *opts) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; /* if dict not yet retrieved */ if (opts->mcDictObj == NULL) { /* if locale was not yet used */ if (!(opts->flags & CLF_LOCALE_USED)) { - opts->localeObj = NormLocaleObj((ClockClientData *) opts->clientData, opts->interp, + opts->localeObj = NormLocaleObj(dataPtr, opts->interp, opts->localeObj, &opts->mcDictObj); if (opts->localeObj == NULL) { Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "locale not specified and no default locale set", -1)); + "locale not specified and no default locale set", + TCL_AUTO_LENGTH)); Tcl_SetErrorCode(opts->interp, "CLOCK", "badOption", (char *)NULL); return NULL; } @@ -711,8 +714,8 @@ ClockMCDict( dataPtr->mcLiterals = (Tcl_Obj **) ckalloc(MCLIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < MCLIT__END; ++i) { - TclInitObjRef(dataPtr->mcLiterals[i], - Tcl_NewStringObj(MsgCtLiterals[i], -1)); + TclInitObjRef(dataPtr->mcLiterals[i], Tcl_NewStringObj( + MsgCtLiterals[i], TCL_AUTO_LENGTH)); } } } @@ -795,7 +798,6 @@ ClockMCGet( ClockFmtScnCmdArgs *opts, int mcKey) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; Tcl_Obj *valObj = NULL; if (opts->mcDictObj == NULL) { @@ -806,8 +808,7 @@ ClockMCGet( } Tcl_DictObjGet(opts->interp, opts->mcDictObj, - dataPtr->mcLiterals[mcKey], &valObj); - + opts->dataPtr->mcLiterals[mcKey], &valObj); return valObj; /* or NULL in obscure case if Tcl_DictObjGet failed */ } @@ -831,7 +832,7 @@ ClockMCGetIdx( ClockFmtScnCmdArgs *opts, int mcKey) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; Tcl_Obj *valObj = NULL; if (opts->mcDictObj == NULL) { @@ -874,7 +875,7 @@ ClockMCSetIdx( int mcKey, Tcl_Obj *valObj) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; if (opts->mcDictObj == NULL) { ClockMCDict(opts); @@ -890,7 +891,7 @@ ClockMCSetIdx( dataPtr->mcLitIdxs = (Tcl_Obj **) ckalloc(MCLIT__END * sizeof(Tcl_Obj*)); for (i = 0; i < MCLIT__END; ++i) { TclInitObjRef(dataPtr->mcLitIdxs[i], - Tcl_NewStringObj(MsgCtLitIdxs[i], -1)); + Tcl_NewStringObj(MsgCtLitIdxs[i], TCL_AUTO_LENGTH)); } } @@ -909,7 +910,7 @@ TimezoneLoaded( /* mark GMT zone loaded */ if (dataPtr->gmtSetupTimeZone == NULL) { TclSetObjRef(dataPtr->gmtSetupTimeZone, - dataPtr->literals[LIT_GMT]); + dataPtr->literals[LIT_GMT]); } TclSetObjRef(dataPtr->gmtSetupTimeZoneUnnorm, tzUnnormObj); return; @@ -1175,11 +1176,10 @@ ClockConfigureObjCmd( static inline Tcl_Obj * ClockGetTZData( - void *clientData, /* Opaque pointer to literal pool, etc. */ + ClockClientData *dataPtr, /* Opaque pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ Tcl_Obj *timezoneObj) /* Name of the timezone */ { - ClockClientData *dataPtr = (ClockClientData *)clientData; Tcl_Obj *ret, **out = NULL; /* if cached (if already setup this one) */ @@ -1245,11 +1245,9 @@ ClockGetTZData( static Tcl_Obj * ClockGetSystemTimeZone( - void *clientData, /* Opaque pointer to literal pool, etc. */ + ClockClientData *dataPtr, /* Pointer to literal pool, etc. */ Tcl_Interp *interp) /* Tcl interpreter */ { - ClockClientData *dataPtr = (ClockClientData *)clientData; - /* if known (cached and same epoch) - return now */ if (dataPtr->systemTimeZone != NULL && dataPtr->lastTZEpoch == TzsetIfNecessary()) { @@ -1284,11 +1282,10 @@ ClockGetSystemTimeZone( Tcl_Obj * ClockSetupTimeZone( - void *clientData, /* Opaque pointer to literal pool, etc. */ + ClockClientData *dataPtr, /* Pointer to literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ Tcl_Obj *timezoneObj) { - ClockClientData *dataPtr = (ClockClientData *)clientData; int loaded; Tcl_Obj *callargs[2]; @@ -1401,12 +1398,12 @@ ClockFormatNumericTimeZone( static int ClockConvertlocaltoutcObjCmd( - void *clientData, /* Client data */ + void *clientData, /* Literal table */ Tcl_Interp *interp, /* Tcl interpreter */ int objc, /* Parameter count */ Tcl_Obj *const *objv) /* Parameter vector */ { - ClockClientData *data = (ClockClientData *)clientData; + ClockClientData *dataPtr = (ClockClientData *)clientData; Tcl_Obj *secondsObj; Tcl_Obj *dict; int changeover; @@ -1424,18 +1421,18 @@ ClockConvertlocaltoutcObjCmd( return TCL_ERROR; } dict = objv[1]; - if (Tcl_DictObjGet(interp, dict, data->literals[LIT_LOCALSECONDS], + if (Tcl_DictObjGet(interp, dict, dataPtr->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", TCL_AUTO_LENGTH)); return TCL_ERROR; } if ((TclGetWideIntFromObj(interp, secondsObj, &fields.localSeconds) != TCL_OK) || (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK) - || ConvertLocalToUTC(clientData, interp, &fields, objv[2], changeover)) { + || ConvertLocalToUTC(dataPtr, interp, &fields, objv[2], changeover)) { return TCL_ERROR; } @@ -1449,7 +1446,7 @@ ClockConvertlocaltoutcObjCmd( created = 1; Tcl_IncrRefCount(dict); } - status = Tcl_DictObjPut(interp, dict, data->literals[LIT_SECONDS], + status = Tcl_DictObjPut(interp, dict, dataPtr->literals[LIT_SECONDS], Tcl_NewWideIntObj(fields.seconds)); if (status == TCL_OK) { Tcl_SetObjResult(interp, dict); @@ -1498,8 +1495,8 @@ ClockGetdatefieldsObjCmd( { TclDateFields fields; Tcl_Obj *dict; - ClockClientData *data = (ClockClientData *)clientData; - Tcl_Obj *const *lit = data->literals; + ClockClientData *dataPtr = (ClockClientData *)clientData; + Tcl_Obj *const *lit = dataPtr->literals; int changeover; fields.tzName = NULL; @@ -1529,7 +1526,7 @@ ClockGetdatefieldsObjCmd( /* Extract fields */ - if (ClockGetDateFields(clientData, interp, &fields, objv[2], + if (ClockGetDateFields(dataPtr, interp, &fields, objv[2], changeover) != TCL_OK) { return TCL_ERROR; } @@ -1588,7 +1585,7 @@ ClockGetdatefieldsObjCmd( int ClockGetDateFields( - void *clientData, /* Client data of the interpreter */ + ClockClientData *dataPtr, /* Literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Pointer to result fields, where * fields->seconds contains date to extract */ @@ -1599,7 +1596,7 @@ ClockGetDateFields( * Convert UTC time to local. */ - if (ConvertUTCToLocal(clientData, interp, fields, timezoneObj, + if (ConvertUTCToLocal(dataPtr, interp, fields, timezoneObj, changeover) != TCL_OK) { return TCL_ERROR; } @@ -1609,7 +1606,7 @@ ClockGetDateFields( */ ClockExtractJDAndSODFromSeconds(fields->julianDay, fields->secondOfDay, - fields->localSeconds); + fields->localSeconds); /* * Convert to Julian or Gregorian calendar. @@ -1657,7 +1654,7 @@ FetchEraField( } if (value == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "expected key(s) not found in dictionary", -1)); + "expected key(s) not found in dictionary", TCL_AUTO_LENGTH)); return TCL_ERROR; } return Tcl_GetIndexFromObj(interp, value, eras, "era", TCL_EXACT, storePtr); @@ -1677,7 +1674,7 @@ FetchIntField( } if (value == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "expected key(s) not found in dictionary", -1)); + "expected key(s) not found in dictionary", TCL_AUTO_LENGTH)); return TCL_ERROR; } return TclGetIntFromObj(interp, value, storePtr); @@ -1854,13 +1851,12 @@ ClockGetjuliandayfromerayearweekdayObjCmd( static int ConvertLocalToUTC( - void *clientData, /* Client data of the interpreter */ + ClockClientData *dataPtr, /* Literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Fields of the time */ Tcl_Obj *timezoneObj, /* Time zone */ int changeover) /* Julian Day of the Gregorian transition */ { - ClockClientData *dataPtr = (ClockClientData *)clientData; Tcl_Obj *tzdata; /* Time zone data */ Tcl_Size rowc; /* Number of rows in tzdata */ Tcl_Obj **rowv; /* Pointers to the rows */ @@ -1905,7 +1901,7 @@ ConvertLocalToUTC( * Unpack the tz data. */ - tzdata = ClockGetTZData(clientData, interp, timezoneObj); + tzdata = ClockGetTZData(dataPtr, interp, timezoneObj); if (tzdata == NULL) { return TCL_ERROR; } @@ -2123,7 +2119,7 @@ ConvertLocalToUTCUsingC( if (localErrno != 0 || (fields->seconds == -1 && timeVal.tm_yday == -1)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "time value too large/small to represent", -1)); + "time value too large/small to represent", TCL_AUTO_LENGTH)); return TCL_ERROR; } return TCL_OK; @@ -2147,13 +2143,12 @@ ConvertLocalToUTCUsingC( int ConvertUTCToLocal( - void *clientData, /* Client data of the interpreter */ + ClockClientData *dataPtr, /* Literal pool, etc. */ Tcl_Interp *interp, /* Tcl interpreter */ TclDateFields *fields, /* Fields of the time */ Tcl_Obj *timezoneObj, /* Time zone */ int changeover) /* Julian Day of the Gregorian transition */ { - ClockClientData *dataPtr = (ClockClientData *)clientData; Tcl_Obj *tzdata; /* Time zone data */ Tcl_Size rowc; /* Number of rows in tzdata */ Tcl_Obj **rowv; /* Pointers to the rows */ @@ -2166,7 +2161,7 @@ ConvertUTCToLocal( if (dataPtr->gmtTZName == NULL) { Tcl_Obj *tzName; - tzdata = ClockGetTZData(clientData, interp, timezoneObj); + tzdata = ClockGetTZData(dataPtr, interp, timezoneObj); if (TclListObjGetElements(interp, tzdata, &rowc, &rowv) != TCL_OK || Tcl_ListObjIndex(interp, rowv[0], 3, &tzName) != TCL_OK) { return TCL_ERROR; @@ -2201,7 +2196,7 @@ ConvertUTCToLocal( * Unpack the tz data. */ - tzdata = ClockGetTZData(clientData, interp, timezoneObj); + tzdata = ClockGetTZData(dataPtr, interp, timezoneObj); if (tzdata == NULL) { return TCL_ERROR; } @@ -2346,7 +2341,7 @@ 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)); + "number too large to represent as a Posix time", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "CLOCK", "argTooLarge", (char *)NULL); return TCL_ERROR; } @@ -2355,7 +2350,7 @@ ConvertUTCToLocalUsingC( if (timeVal == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "localtime failed (clock value may be too " - "large/small to represent)", -1)); + "large/small to represent)", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "CLOCK", "localtimeFailed", (char *)NULL); return TCL_ERROR; } @@ -3049,7 +3044,8 @@ ClockGetenvObjCmd( varName = TclGetString(objv[1]); varValue = getenv(varName); if (varValue != NULL) { - Tcl_SetObjResult(interp, Tcl_NewStringObj(varValue, -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + varValue, TCL_AUTO_LENGTH)); } #endif return TCL_OK; @@ -3243,12 +3239,12 @@ ClockMicrosecondsObjCmd( static inline void ClockInitFmtScnArgs( - void *clientData, + ClockClientData *dataPtr, Tcl_Interp *interp, ClockFmtScnCmdArgs *opts) { memset(opts, 0, sizeof(*opts)); - opts->clientData = clientData; + opts->dataPtr = dataPtr; opts->interp = interp; } @@ -3270,22 +3266,24 @@ ClockInitFmtScnArgs( *----------------------------------------------------------------------------- */ -#define CLC_FMT_ARGS (0) -#define CLC_SCN_ARGS (1 << 0) -#define CLC_ADD_ARGS (1 << 1) +typedef enum ClockOperation { + CLC_OP_FMT = 0, /* Doing [clock format] */ + CLC_OP_SCN, /* Doing [clock scan] */ + CLC_OP_ADD /* Doing [clock add] */ +} ClockOperation; static int ClockParseFmtScnArgs( ClockFmtScnCmdArgs *opts, /* Result vector: format, locale, timezone... */ - TclDateFields *date, /* Extracted date-time corresponding base + TclDateFields *date, /* Extracted date-time corresponding base * (by scan or add) resp. clockval (by format) */ int objc, /* Parameter count */ Tcl_Obj *const objv[], /* Parameter vector */ - int flags, /* Flags, differentiates between format, scan, add */ + ClockOperation operation, /* What operation are we doing: format, scan, add */ const char *syntax) /* Syntax of the current command */ { Tcl_Interp *interp = opts->interp; - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; int gmtFlag = 0; static const char *const options[] = { "-base", "-format", "-gmt", "-locale", "-timezone", "-validate", NULL @@ -3299,13 +3297,13 @@ ClockParseFmtScnArgs( int i, baseIdx; Tcl_WideInt baseVal; /* Base time, expressed in seconds from the Epoch */ - if (flags & CLC_SCN_ARGS) { + if (operation == CLC_OP_SCN) { /* default flags (from configure) */ - opts->flags |= dataPtr->defFlags & (CLF_VALIDATE); + opts->flags |= dataPtr->defFlags & CLF_VALIDATE; } else { /* clock value (as current base) */ opts->baseObj = objv[(baseIdx = 1)]; - saw |= (1 << CLC_ARGS_BASE); + saw |= 1 << CLC_ARGS_BASE; } /* @@ -3314,7 +3312,7 @@ ClockParseFmtScnArgs( for (i = 2; i < objc; i+=2) { /* bypass integers (offsets) by "clock add" */ - if (flags & CLC_ADD_ARGS) { + if (operation == CLC_OP_ADD) { Tcl_WideInt num; if (TclGetWideIntFromObj(NULL, objv[i], &num) == TCL_OK) { @@ -3328,8 +3326,7 @@ ClockParseFmtScnArgs( } /* if already specified */ if (saw & (1 << optionIndex)) { - if (!(flags & CLC_SCN_ARGS) - && optionIndex == CLC_ARGS_BASE) { + if (operation != CLC_OP_SCN && optionIndex == CLC_ARGS_BASE) { goto badOptionMsg; } Tcl_SetObjResult(interp, Tcl_ObjPrintf( @@ -3339,7 +3336,7 @@ ClockParseFmtScnArgs( } switch (optionIndex) { case CLC_ARGS_FORMAT: - if (flags & CLC_ADD_ARGS) { + if (operation == CLC_OP_ADD) { goto badOptionMsg; } opts->formatObj = objv[i + 1]; @@ -3359,7 +3356,7 @@ ClockParseFmtScnArgs( opts->baseObj = objv[(baseIdx = i + 1)]; break; case CLC_ARGS_VALIDATE: - if (!(flags & CLC_SCN_ARGS)) { + if (operation != CLC_OP_SCN) { goto badOptionMsg; } else { int val; @@ -3375,7 +3372,7 @@ ClockParseFmtScnArgs( } break; } - saw |= (1 << optionIndex); + saw |= 1 << optionIndex; } /* @@ -3384,7 +3381,8 @@ ClockParseFmtScnArgs( if ((saw & (1 << CLC_ARGS_GMT)) && (saw & (1 << CLC_ARGS_TIMEZONE))) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot use -gmt and -timezone in same call", -1)); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "cannot use -gmt and -timezone in same call", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "CLOCK", "gmtWithTimezone", (char *)NULL); return TCL_ERROR; } @@ -3394,7 +3392,7 @@ ClockParseFmtScnArgs( || TclGetString(opts->timezoneObj) == NULL || opts->timezoneObj->length == 0) { /* If time zone not specified use system time zone */ - opts->timezoneObj = ClockGetSystemTimeZone(opts->clientData, interp); + opts->timezoneObj = ClockGetSystemTimeZone(dataPtr, interp); if (opts->timezoneObj == NULL) { return TCL_ERROR; } @@ -3402,7 +3400,7 @@ ClockParseFmtScnArgs( /* Setup timezone (normalize object if needed and load TZ on demand) */ - opts->timezoneObj = ClockSetupTimeZone(opts->clientData, interp, opts->timezoneObj); + opts->timezoneObj = ClockSetupTimeZone(dataPtr, interp, opts->timezoneObj); if (opts->timezoneObj == NULL) { return TCL_ERROR; } @@ -3413,7 +3411,7 @@ ClockParseFmtScnArgs( Tcl_Obj *baseObj = opts->baseObj; /* bypass integer recognition if looks like option "-now" */ - if ((baseObj->bytes && baseObj->length == 4 && *(baseObj->bytes + 1) == 'n') + if ((baseObj->bytes && baseObj->length == 4 && baseObj->bytes[1] == 'n') || TclGetWideIntFromObj(NULL, baseObj, &baseVal) != TCL_OK) { /* we accept "-now" as current date-time */ static const char *const nowOpts[] = { @@ -3471,7 +3469,7 @@ ClockParseFmtScnArgs( } else { /* extact fields from base */ date->seconds = baseVal; - if (ClockGetDateFields(opts->clientData, interp, date, opts->timezoneObj, + if (ClockGetDateFields(dataPtr, interp, date, opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) { /* TODO - GREGORIAN_CHANGE_DATE should be locale-dependent */ return TCL_ERROR; @@ -3522,7 +3520,6 @@ ClockFormatObjCmd( Tcl_Obj *const objv[]) /* Parameter values */ { ClockClientData *dataPtr = (ClockClientData *)clientData; - static const char *syntax = "clock format clockval|-now " "?-format string? " "?-gmt boolean? " @@ -3544,9 +3541,9 @@ ClockFormatObjCmd( * Extract values for the keywords. */ - ClockInitFmtScnArgs(clientData, interp, &opts); + ClockInitFmtScnArgs(dataPtr, interp, &opts); ret = ClockParseFmtScnArgs(&opts, &dateFmt.date, objc, objv, - CLC_FMT_ARGS, "-format, -gmt, -locale, or -timezone"); + CLC_OP_FMT, "-format, -gmt, -locale, or -timezone"); if (ret != TCL_OK) { goto done; } @@ -3591,6 +3588,7 @@ ClockScanObjCmd( int objc, /* Parameter count */ Tcl_Obj *const objv[]) /* Parameter values */ { + ClockClientData *dataPtr = (ClockClientData *)clientData; static const char *syntax = "clock scan string " "?-base seconds? " "?-format string? " @@ -3614,9 +3612,9 @@ ClockScanObjCmd( * Extract values for the keywords. */ - ClockInitFmtScnArgs(clientData, interp, &opts); + ClockInitFmtScnArgs(dataPtr, interp, &opts); ret = ClockParseFmtScnArgs(&opts, &yy.date, objc, objv, - CLC_SCN_ARGS, "-base, -format, -gmt, -locale, -timezone or -validate"); + CLC_OP_SCN, "-base, -format, -gmt, -locale, -timezone or -validate"); if (ret != TCL_OK) { goto done; } @@ -3632,7 +3630,7 @@ ClockScanObjCmd( * it's not localized. */ if (opts.localeObj != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( - "legacy [clock scan] does not support -locale", -1)); + "legacy [clock scan] does not support -locale", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(interp, "CLOCK", "flagWithLegacyFormat", (char *)NULL); ret = TCL_ERROR; goto done; @@ -3722,13 +3720,11 @@ ClockScanCommit( /* some overflow checks */ if (info->flags & CLF_JULIANDAY) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; - double curJDN = (double)yydate.julianDay + ((double)yySecondOfDay - SECONDS_PER_DAY/2) / SECONDS_PER_DAY; - if (curJDN > dataPtr->maxJDN) { + if (curJDN > opts->dataPtr->maxJDN) { Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "requested date too large to represent", -1)); + "requested date too large to represent", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL); return TCL_ERROR; } @@ -3736,15 +3732,15 @@ ClockScanCommit( /* Local seconds to UTC (stored in yydate.seconds) */ - if (info->flags & (CLF_ASSEMBLE_SECONDS)) { + if (info->flags & CLF_ASSEMBLE_SECONDS) { yydate.localSeconds = -210866803200LL + (SECONDS_PER_DAY * yydate.julianDay) + (yySecondOfDay % SECONDS_PER_DAY); } - if (info->flags & (CLF_ASSEMBLE_SECONDS|CLF_LOCALSEC)) { - if (ConvertLocalToUTC(opts->clientData, opts->interp, &yydate, + if (info->flags & (CLF_ASSEMBLE_SECONDS | CLF_LOCALSEC)) { + if (ConvertLocalToUTC(opts->dataPtr, opts->interp, &yydate, opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) { return TCL_ERROR; } @@ -3780,7 +3776,7 @@ ClockValidDate( const char *errMsg = "", *errCode = ""; TclDateFields temp; int tempCpyFlg = 0; - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; #if 0 printf("yyMonth %d, yyDay %d, yyDayOfYear %d, yyHour %d, yyMinutes %d, yySeconds %d, " @@ -3796,7 +3792,7 @@ ClockValidDate( opts->flags &= ~CLF_VALIDATE_S1; /* stage 1 is done */ /* first year (used later in hath / daysInPriorMonths) */ - if ((info->flags & (CLF_YEAR|CLF_ISO8601YEAR))) { + if ((info->flags & (CLF_YEAR | CLF_ISO8601YEAR))) { if ((info->flags & CLF_ISO8601YEAR)) { if (yydate.iso8601Year < dataPtr->validMinYear || yydate.iso8601Year > dataPtr->validMaxYear) { @@ -3815,8 +3811,8 @@ ClockValidDate( } else if ((info->flags & CLF_ISO8601YEAR)) { yyYear = yydate.iso8601Year; /* used to recognize leap */ } - if ((info->flags & (CLF_ISO8601YEAR|CLF_YEAR)) - == (CLF_ISO8601YEAR|CLF_YEAR)) { + if ((info->flags & (CLF_ISO8601YEAR | CLF_YEAR)) + == (CLF_ISO8601YEAR | CLF_YEAR)) { if (yyYear != yydate.iso8601Year) { errMsg = "ambiguous year"; errCode = "year"; @@ -3966,8 +3962,7 @@ ClockFreeScan( ClockFmtScnCmdArgs *opts) /* Command options */ { Tcl_Interp *interp = opts->interp; - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; - + ClockClientData *dataPtr = opts->dataPtr; int ret = TCL_ERROR; /* @@ -3981,12 +3976,9 @@ ClockFreeScan( yyInput = TclGetString(strObj); if (TclClockFreeScan(interp, info) != TCL_OK) { - Tcl_Obj *msg; - - TclNewObj(msg); - Tcl_AppendPrintfToObj(msg, "unable to convert date-time string \"%s\": %s", - TclGetString(strObj), Tcl_GetString(Tcl_GetObjResult(interp))); - Tcl_SetObjResult(interp, msg); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "unable to convert date-time string \"%s\": %s", + TclGetString(strObj), Tcl_GetString(Tcl_GetObjResult(interp)))); goto done; } @@ -4054,14 +4046,13 @@ ClockFreeScan( * Assemble date, time, zone into seconds-from-epoch */ - if ((info->flags & (CLF_TIME|CLF_HAVEDATE)) == CLF_HAVEDATE) { + if ((info->flags & (CLF_TIME | CLF_HAVEDATE)) == CLF_HAVEDATE) { yySecondOfDay = 0; info->flags |= CLF_ASSEMBLE_SECONDS; } else if (info->flags & CLF_TIME) { - yySecondOfDay = ToSeconds(yyHour, yyMinutes, - yySeconds, yyMeridian); + yySecondOfDay = ToSeconds(yyHour, yyMinutes, yySeconds, yyMeridian); info->flags |= CLF_ASSEMBLE_SECONDS; - } else if ((info->flags & (CLF_DAYOFWEEK|CLF_HAVEDATE)) == CLF_DAYOFWEEK + } else if ((info->flags & (CLF_DAYOFWEEK | CLF_HAVEDATE)) == CLF_DAYOFWEEK || (info->flags & CLF_ORDINALMONTH) || ((info->flags & CLF_RELCONV) && (yyRelMonth != 0 || yyRelDay != 0))) { @@ -4147,7 +4138,7 @@ ClockCalcRelTime( } /* on demand (lazy) assemble julianDay using new year, month, etc. */ - info->flags |= CLF_ASSEMBLE_JULIANDAY|CLF_ASSEMBLE_SECONDS; + info->flags |= CLF_ASSEMBLE_JULIANDAY | CLF_ASSEMBLE_SECONDS; yyRelMonth = 0; } @@ -4395,9 +4386,9 @@ ClockAddObjCmd( * Extract values for the keywords. */ - ClockInitFmtScnArgs(clientData, interp, &opts); + ClockInitFmtScnArgs(dataPtr, interp, &opts); ret = ClockParseFmtScnArgs(&opts, &yy.date, objc, objv, - CLC_ADD_ARGS, "-gmt, -locale, or -timezone"); + CLC_OP_ADD, "-gmt, -locale, or -timezone"); if (ret != TCL_OK) { goto done; } @@ -4405,7 +4396,9 @@ ClockAddObjCmd( /* time together as seconds of the day */ yySecondOfDay = yySeconds = yydate.localSeconds % SECONDS_PER_DAY; /* seconds are in localSeconds (relative base date), so reset time here */ - yyHour = 0; yyMinutes = 0; yyMeridian = MER24; + yyHour = 0; + yyMinutes = 0; + yyMeridian = MER24; ret = TCL_ERROR; @@ -4642,58 +4635,69 @@ ClockSafeCatchCmd( #define wcscmp strcmp #define wcscpy strcpy #endif +#define TZ_INIT_MARKER ((WCHAR *) INT2PTR(-1)) static size_t 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 tzWasEpoch = 0; /* Epoch, signals that TZ changed */ - static size_t tzEnvEpoch = 0; /* Last env epoch, for faster signaling, - that TZ changed via TCL */ - const WCHAR *tzIsNow; /* Current value of TZ */ + typedef struct ClockTzStatic { + WCHAR *was; /* Previous value of TZ. */ + long lastRefresh; /* Used for latency before next refresh. */ + size_t epoch; /* Epoch, signals that TZ changed. */ + size_t envEpoch; /* Last env epoch, for faster signaling, + * that TZ changed via TCL */ + } ClockTzStatic; + static ClockTzStatic tz = { /* Global timezone info; protected by + * clockMutex.*/ + TZ_INIT_MARKER, 0, 0, 0 + }; + const WCHAR *tzNow; /* Current value of TZ. */ + Tcl_Time now; /* Current time. */ + size_t epoch; /* The tz.epoch that the TZ was read at. */ /* * 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 tzWasEpoch; + if (now.sec == tz.lastRefresh && tz.envEpoch == TclEnvEpoch) { + return tz.epoch; } - tzEnvEpoch = TclEnvEpoch; - tzLastRefresh = now.sec; + tz.envEpoch = TclEnvEpoch; + tz.lastRefresh = now.sec; /* check in lock */ Tcl_MutexLock(&clockMutex); - tzIsNow = getenv("TCL_TZ"); - if (tzIsNow == NULL) { - tzIsNow = getenv("TZ"); + tzNow = getenv("TCL_TZ"); + if (tzNow == NULL) { + tzNow = getenv("TZ"); } - if (tzIsNow != NULL && (tzWas == NULL || tzWas == (WCHAR *)INT2PTR(-1) - || wcscmp(tzIsNow, tzWas) != 0)) { + if (tzNow != NULL && (tz.was == NULL || tz.was == TZ_INIT_MARKER + || wcscmp(tzNow, tz.was) != 0)) { tzset(); - if (tzWas != NULL && tzWas != (WCHAR *)INT2PTR(-1)) { - ckfree(tzWas); + if (tz.was != NULL && tz.was != TZ_INIT_MARKER) { + ckfree(tz.was); } - tzWas = (WCHAR *)ckalloc(sizeof(WCHAR) * (wcslen(tzIsNow) + 1)); - wcscpy(tzWas, tzIsNow); - tzWasEpoch++; - } else if (tzIsNow == NULL && tzWas != NULL) { + tz.was = (WCHAR *) + ckalloc(sizeof(WCHAR) * (wcslen(tzNow) + 1)); + wcscpy(tz.was, tzNow); + epoch = ++tz.epoch; + } else if (tzNow == NULL && tz.was != NULL) { tzset(); - if (tzWas != (WCHAR *)INT2PTR(-1)) { - ckfree(tzWas); + if (tz.was != TZ_INIT_MARKER) { + ckfree(tz.was); } - tzWas = NULL; - tzWasEpoch++; + tz.was = NULL; + epoch = ++tz.epoch; + } else { + epoch = tz.epoch; } Tcl_MutexUnlock(&clockMutex); - return tzWasEpoch; + return epoch; } /* diff --git a/generic/tclClockFmt.c b/generic/tclClockFmt.c index 06684a6..cbb935d 100644 --- a/generic/tclClockFmt.c +++ b/generic/tclClockFmt.c @@ -33,6 +33,11 @@ static void ClockFrmScnFinalize(void *); */ static Tcl_HashKeyType ClockFmtScnStorageHashKeyType; + +#define IntFieldAt(info, offset) \ + ((int *) (((char *) (info)) + (offset))) +#define WideFieldAt(info, offset) \ + ((Tcl_WideInt *) (((char *) (info)) + (offset))) /* * Clock scan and format facilities. @@ -41,7 +46,7 @@ static Tcl_HashKeyType ClockFmtScnStorageHashKeyType; /* *---------------------------------------------------------------------- * - * _str2int -- , _str2wideInt -- + * Clock_str2int, Clock_str2wideInt -- * * Fast inline-convertion of string to signed int or wide int by given * start/end. @@ -57,7 +62,7 @@ static Tcl_HashKeyType ClockFmtScnStorageHashKeyType; */ static inline void -_str2int_no( +Clock_str2int_no( int *out, const char *p, const char *e, @@ -65,8 +70,9 @@ _str2int_no( { /* assert(e <= p + 10); */ int val = 0; + /* overflow impossible for 10 digits ("9..9"), so no needs to check at all */ - while (p < e) { /* never overflows */ + while (p < e) { /* never overflows */ val = val * 10 + (*p++ - '0'); } if (sign < 0) { @@ -76,7 +82,7 @@ _str2int_no( } static inline void -_str2wideInt_no( +Clock_str2wideInt_no( Tcl_WideInt *out, const char *p, const char *e, @@ -84,8 +90,9 @@ _str2wideInt_no( { /* assert(e <= p + 18); */ Tcl_WideInt val = 0; + /* overflow impossible for 18 digits ("9..9"), so no needs to check at all */ - while (p < e) { /* never overflows */ + while (p < e) { /* never overflows */ val = val * 10 + (*p++ - '0'); } if (sign < 0) { @@ -100,7 +107,7 @@ _str2wideInt_no( #endif static inline int -_str2int( +Clock_str2int( int *out, const char *p, const char *e, @@ -109,6 +116,7 @@ _str2int( int val = 0; /* overflow impossible for 10 digits ("9..9"), so no needs to check before */ const char *eNO = p + 10; + if (eNO > e) { eNO = e; } @@ -118,6 +126,7 @@ _str2int( if (sign >= 0) { while (p < e) { /* check for overflow */ int prev = val; + val = val * 10 + (*p++ - '0'); if (val / 10 < prev) { return TCL_ERROR; @@ -127,6 +136,7 @@ _str2int( val = -val; while (p < e) { /* check for overflow */ int prev = val; + val = val * 10 - (*p++ - '0'); if (val / 10 > prev) { return TCL_ERROR; @@ -138,7 +148,7 @@ _str2int( } static inline int -_str2wideInt( +Clock_str2wideInt( Tcl_WideInt *out, const char *p, const char *e, @@ -147,6 +157,7 @@ _str2wideInt( Tcl_WideInt val = 0; /* overflow impossible for 18 digits ("9..9"), so no needs to check before */ const char *eNO = p + 18; + if (eNO > e) { eNO = e; } @@ -156,6 +167,7 @@ _str2wideInt( if (sign >= 0) { while (p < e) { /* check for overflow */ Tcl_WideInt prev = val; + val = val * 10 + (*p++ - '0'); if (val / 10 < prev) { return TCL_ERROR; @@ -165,6 +177,7 @@ _str2wideInt( val = -val; while (p < e) { /* check for overflow */ Tcl_WideInt prev = val; + val = val * 10 - (*p++ - '0'); if (val / 10 > prev) { return TCL_ERROR; @@ -182,7 +195,7 @@ TclAtoWIe( const char *e, int sign) { - return _str2wideInt(out, p, e, sign); + return Clock_str2wideInt(out, p, e, sign); } #if defined(__GNUC__) || defined(__GNUG__) @@ -192,7 +205,7 @@ TclAtoWIe( /* *---------------------------------------------------------------------- * - * _itoaw -- , _witoaw -- + * Clock_itoaw, Clock_witoaw -- * * Fast inline-convertion of signed int or wide int to string, using * given padding with specified padchar and width (or without padding). @@ -206,14 +219,16 @@ TclAtoWIe( */ static inline char * -_itoaw( +Clock_itoaw( char *buf, int val, char padchar, unsigned short width) { char *p; - static int wrange[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + static const int wrange[] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 + }; /* positive integer */ @@ -226,7 +241,8 @@ _itoaw( p = buf + width; *p-- = '\0'; do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' + c; } while (val > 0); @@ -254,13 +270,15 @@ _itoaw( /* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */ if (-1 % 10 == -1) { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' - c; } while (val < 0); } else { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' + c; } while (val < 0); @@ -287,18 +305,20 @@ TclItoAw( char padchar, unsigned short width) { - return _itoaw(buf, val, padchar, width); + return Clock_itoaw(buf, val, padchar, width); } static inline char * -_witoaw( +Clock_witoaw( char *buf, Tcl_WideInt val, char padchar, unsigned short width) { char *p; - static int wrange[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; + static const int wrange[] = { + 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 + }; /* positive integer */ @@ -306,6 +326,7 @@ _witoaw( /* check resp. recalculate width */ if (val >= 10000000000LL) { Tcl_WideInt val2 = val / 10000000000LL; + while (width <= 9 && val2 >= wrange[width]) { width++; } @@ -340,6 +361,7 @@ _witoaw( width--; if (val <= -10000000000LL) { Tcl_WideInt val2 = val / 10000000000LL; + while (width <= 9 && val2 <= -wrange[width]) { width++; } @@ -356,13 +378,15 @@ _witoaw( /* differentiate platforms with -1 % 10 == 1 and -1 % 10 == -1 */ if (-1 % 10 == -1) { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' - c; } while (val < 0); } else { do { - char c = (val % 10); + char c = val % 10; + val /= 10; *p-- = '0' + c; } while (val < 0); @@ -903,7 +927,7 @@ Tcl_Obj * ClockLocalizeFormat( ClockFmtScnCmdArgs *opts) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; Tcl_Obj *valObj = NULL, *keyObj; keyObj = ClockFrmObjGetLocFmtKey(opts->interp, opts->formatObj); @@ -1051,8 +1075,8 @@ DetermineGreedySearchLen( { int minLen = tok->map->minSize; int maxLen; - const char *p = yyInput + minLen, - *end = info->dateEnd; + const char *p = yyInput + minLen; + const char *end = info->dateEnd; /* if still tokens available, try to correct minimum length */ if ((tok + 1)->map) { @@ -1558,7 +1582,7 @@ ClockScnToken_DayOfWeek_Proc( } if (val > 7) { Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "day of week is greater than 7", -1)); + "day of week is greater than 7", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(opts->interp, "CLOCK", "badDayOfWeek", (char *)NULL); return TCL_ERROR; } @@ -1625,7 +1649,7 @@ ClockScnToken_LocaleERA_Proc( DateInfo *info, ClockScanToken *tok) { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; int ret, val; int minLen, maxLen; @@ -1683,7 +1707,7 @@ ClockScnToken_LocaleListMatcher_Proc( } if (tok->map->offs > 0) { - *(int *)(((char *)info) + tok->map->offs) = --val; + *IntFieldAt(info, tok->map->offs) = --val; } return TCL_OK; @@ -1712,7 +1736,7 @@ ClockScnToken_JDN_Proc( while (p < end && isdigit(UCHAR(*p))) { p++; } - if (_str2wideInt(&intJD, s, p, (*yyInput != '-' ? 1 : -1)) != TCL_OK) { + if (Clock_str2wideInt(&intJD, s, p, (*yyInput != '-' ? 1 : -1)) != TCL_OK) { return TCL_RETURN; } yyInput = p; @@ -1730,7 +1754,7 @@ ClockScnToken_JDN_Proc( fractJDDiv *= 10; p++; } - if (_str2int(&fractJD, s, p, 1) != TCL_OK) { + if (Clock_str2int(&fractJD, s, p, 1) != TCL_OK) { return TCL_RETURN; } yyInput = p; @@ -1742,7 +1766,7 @@ ClockScnToken_JDN_Proc( */ fractJD = (int)tok->map->offs /* 0 for calendar or 43200 for astro JD */ - + (int)((Tcl_WideInt)SECONDS_PER_DAY * fractJD / fractJDDiv); + + (int)((Tcl_WideInt)SECONDS_PER_DAY * fractJD / fractJDDiv); if (fractJD > SECONDS_PER_DAY) { fractJD %= SECONDS_PER_DAY; intJD += 1; @@ -1840,7 +1864,7 @@ ClockScnToken_TimeZone_Proc( /* try to apply new time zone */ Tcl_IncrRefCount(tzObjStor); - opts->timezoneObj = ClockSetupTimeZone(opts->clientData, opts->interp, + opts->timezoneObj = ClockSetupTimeZone(opts->dataPtr, opts->interp, tzObjStor); Tcl_DecrRefCount(tzObjStor); @@ -1890,8 +1914,8 @@ ClockScnToken_StarDate_Proc( if (p >= end || p - s < 4) { return TCL_RETURN; } - if (_str2int(&year, s, p - 3, 1) != TCL_OK - || _str2int(&fractYear, p - 3, p, 1) != TCL_OK) { + if (Clock_str2int(&year, s, p - 3, 1) != TCL_OK + || Clock_str2int(&fractYear, p - 3, p, 1) != TCL_OK) { return TCL_RETURN; } if (*p++ != '.') { @@ -1903,7 +1927,7 @@ ClockScnToken_StarDate_Proc( fractDayDiv *= 10; p++; } - if (_str2int(&fractDay, s, p, 1) != TCL_OK) { + if (Clock_str2int(&fractDay, s, p, 1) != TCL_OK) { return TCL_RETURN; } yyInput = p; @@ -1934,6 +1958,10 @@ ClockScnToken_StarDate_Proc( return TCL_OK; } +/* + * Descriptors for the various fields in [clock scan]. + */ + static const char *ScnSTokenMapIndex = "dmbyYHMSpJjCgGVazUsntQ"; static const ClockScanTokenMap ScnSTokenMap[] = { /* %d %e */ @@ -2142,7 +2170,7 @@ ClockGetOrParseScanFormat( fss->scnSpaceCount = 0; scnTok = tok = (ClockScanToken *) ckalloc(sizeof(*tok) * fss->scnTokC); - memset(tok, 0, sizeof(*(tok))); + memset(tok, 0, sizeof(*tok)); tokCnt = 1; while (p < e) { switch (*p) { @@ -2249,10 +2277,11 @@ ClockGetOrParseScanFormat( tokCnt++; continue; } -word_tok: + word_tok: { ClockScanToken *wordTok = tok; - if (tok > scnTok && (tok-1)->map == &ScnWordTokenMap) { + + if (tok > scnTok && (tok - 1)->map == &ScnWordTokenMap) { wordTok = tok - 1; } /* new word token */ @@ -2275,7 +2304,7 @@ word_tok: /* calculate end distance value for each tokens */ if (tok > scnTok) { unsigned endDist = 0; - ClockScanToken *prevTok = tok-1; + ClockScanToken *prevTok = tok - 1; while (prevTok >= scnTok) { prevTok->endDistance = endDist; @@ -2316,7 +2345,7 @@ ClockScan( Tcl_Obj *strObj, /* String containing the time to scan */ ClockFmtScnCmdArgs *opts) /* Command options */ { - ClockClientData *dataPtr = (ClockClientData *)opts->clientData; + ClockClientData *dataPtr = opts->dataPtr; ClockFmtScnStorage *fss; ClockScanToken *tok; const ClockScanTokenMap *map; @@ -2421,24 +2450,20 @@ ClockScan( x = p + size; if (map->type == CTOKT_INT) { if (size <= 10) { - _str2int_no((int *)(((char *)info) + map->offs), + Clock_str2int_no(IntFieldAt(info, map->offs), p, x, sign); - } else { - if (_str2int((int *)(((char *)info) + map->offs), - p, x, sign) != TCL_OK) { - goto overflow; - } + } else if (Clock_str2int( + IntFieldAt(info, map->offs), p, x, sign) != TCL_OK) { + goto overflow; } p = x; } else { if (size <= 18) { - _str2wideInt_no((Tcl_WideInt *)(((char *)info) + map->offs), - p, x, sign); - } else { - if (_str2wideInt((Tcl_WideInt *)(((char *)info) + map->offs), - p, x, sign) != TCL_OK) { - goto overflow; - } + Clock_str2wideInt_no( + WideFieldAt(info, map->offs), p, x, sign); + } else if (Clock_str2wideInt( + WideFieldAt(info, map->offs), p, x, sign) != TCL_OK) { + goto overflow; } p = x; } @@ -2651,14 +2676,14 @@ ClockScan( overflow: Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "integer value too large to represent", -1)); + "integer value too large to represent", TCL_AUTO_LENGTH)); Tcl_SetErrorCode(opts->interp, "CLOCK", "dateTooLarge", (char *)NULL); goto done; not_match: #if 1 Tcl_SetObjResult(opts->interp, Tcl_NewStringObj( - "input string does not match supplied format", -1)); + "input string does not match supplied format", TCL_AUTO_LENGTH)); #else /* to debug where exactly scan breaks */ Tcl_SetObjResult(opts->interp, Tcl_ObjPrintf( @@ -2772,9 +2797,9 @@ ClockFmtToken_StarDate_Proc( } memcpy(dateFmt->output, "Stardate ", 9); dateFmt->output += 9; - dateFmt->output = _itoaw(dateFmt->output, + dateFmt->output = Clock_itoaw(dateFmt->output, dateFmt->date.year - RODDENBERRY, '0', 2); - dateFmt->output = _itoaw(dateFmt->output, + dateFmt->output = Clock_itoaw(dateFmt->output, fractYear, '0', 3); *dateFmt->output++ = '.'; /* be sure positive after decimal point (note: clock-value can be negative) */ @@ -2782,7 +2807,7 @@ ClockFmtToken_StarDate_Proc( if (v < 0) { v = 10 + v; } - dateFmt->output = _itoaw(dateFmt->output, v, '0', 1); + dateFmt->output = Clock_itoaw(dateFmt->output, v, '0', 1); return TCL_OK; } static int @@ -2837,7 +2862,7 @@ ClockFmtToken_JDN_Proc( if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { return TCL_ERROR; } - dateFmt->output = _witoaw(dateFmt->output, intJD, '0', 1); + dateFmt->output = Clock_witoaw(dateFmt->output, intJD, '0', 1); /* simplest cases .0 and .5 */ if (!fractJD || fractJD == (SECONDS_PER_DAY / 2)) { /* point + 0 or 5 */ @@ -2863,11 +2888,11 @@ ClockFmtToken_JDN_Proc( return TCL_ERROR; } *dateFmt->output++ = '.'; - p = _itoaw(dateFmt->output, fractJD, '0', JDN_MAX_PRECISION); + p = Clock_itoaw(dateFmt->output, fractJD, '0', JDN_MAX_PRECISION); /* remove trailing zero's */ dateFmt->output++; - while (p > dateFmt->output && *(p-1) == '0') { + while (p > dateFmt->output && p[-1] == '0') { p--; } *p = '\0'; @@ -2894,12 +2919,12 @@ ClockFmtToken_TimeZone_Proc( return TCL_ERROR; } *dateFmt->output++ = sign; - dateFmt->output = _itoaw(dateFmt->output, z / 3600, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, z / 3600, '0', 2); z %= 3600; - dateFmt->output = _itoaw(dateFmt->output, z / 60, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, z / 60, '0', 2); z %= 60; if (z != 0) { - dateFmt->output = _itoaw(dateFmt->output, z, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, z, '0', 2); } } else { Tcl_Obj * objPtr; @@ -2907,7 +2932,7 @@ ClockFmtToken_TimeZone_Proc( Tcl_Size len; /* convert seconds to local seconds to obtain tzName object */ - if (ConvertUTCToLocal(opts->clientData, opts->interp, + if (ConvertUTCToLocal(opts->dataPtr, opts->interp, &dateFmt->date, opts->timezoneObj, GREGORIAN_CHANGE_DATE) != TCL_OK) { return TCL_ERROR; @@ -2986,12 +3011,10 @@ ClockFmtToken_LocaleERAYear_Proc( } if (*tok->tokWord.start == 'C') { /* %EC */ *val = dateFmt->date.year / 100; - dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2); } else { /* %Ey */ *val = dateFmt->date.year % 100; - dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2); } } else { Tcl_Obj *objPtr; @@ -3027,8 +3050,7 @@ ClockFmtToken_LocaleERAYear_Proc( if (FrmResultAllocate(dateFmt, 11) != TCL_OK) { return TCL_ERROR; } - dateFmt->output = _itoaw(dateFmt->output, - *val, '0', 2); + dateFmt->output = Clock_itoaw(dateFmt->output, *val, '0', 2); return TCL_OK; } } @@ -3042,6 +3064,10 @@ ClockFmtToken_LocaleERAYear_Proc( return TCL_OK; } +/* + * Descriptors for the various fields in [clock format]. + */ + static const char *FmtSTokenMapIndex = "demNbByYCHMSIklpaAuwUVzgGjJsntQ"; static const ClockFormatTokenMap FmtSTokenMap[] = { @@ -3219,7 +3245,7 @@ ClockGetOrParseFmtFormat( fss->fmtTokC = EstimateTokenCount(p, e); fmtTok = tok = (ClockFormatToken *) ckalloc(sizeof(*tok) * fss->fmtTokC); - memset(tok, 0, sizeof(*(tok))); + memset(tok, 0, sizeof(*tok)); tokCnt = 1; while (p < e) { switch (*p) { @@ -3293,8 +3319,8 @@ ClockGetOrParseFmtFormat( word_tok: { ClockFormatToken *wordTok = tok; - if (tok > fmtTok && (tok-1)->map == &FmtWordTokenMap) { - wordTok = tok-1; + if (tok > fmtTok && (tok - 1)->map == &FmtWordTokenMap) { + wordTok = tok - 1; } if (wordTok == tok) { wordTok->tokWord.start = p; @@ -3368,7 +3394,7 @@ ClockFormat( map = tok->map; switch (map->type) { case CTOKT_INT: { - int val = (int)*(int *)(((char *)dateFmt) + map->offs); + int val = *IntFieldAt(dateFmt, map->offs); if (map->fmtproc == NULL) { if (map->flags & CLFMT_DECR) { @@ -3397,13 +3423,15 @@ ClockFormat( goto error; } if (map->width) { - dateFmt->output = _itoaw(dateFmt->output, val, *map->tostr, map->width); + dateFmt->output = Clock_itoaw( + dateFmt->output, val, *map->tostr, map->width); } else { dateFmt->output += sprintf(dateFmt->output, map->tostr, val); } } else { const char *s; Tcl_Obj * mcObj = ClockMCGet(opts, PTR2INT(map->data) /* mcKey */); + if (mcObj == NULL) { goto error; } @@ -3421,13 +3449,13 @@ ClockFormat( break; } case CTOKT_WIDE: { - Tcl_WideInt val = *(Tcl_WideInt *)(((char *)dateFmt) + map->offs); + Tcl_WideInt val = *WideFieldAt(dateFmt, map->offs); if (FrmResultAllocate(dateFmt, 21) != TCL_OK) { goto error; } if (map->width) { - dateFmt->output = _witoaw(dateFmt->output, val, *map->tostr, map->width); + dateFmt->output = Clock_witoaw(dateFmt->output, val, *map->tostr, map->width); } else { dateFmt->output += sprintf(dateFmt->output, map->tostr, val); } diff --git a/generic/tclDate.h b/generic/tclDate.h index 8b71827..60e07ab 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -31,42 +31,51 @@ #define RODDENBERRY 1946 /* Another epoch (Hi, Jeff!) */ +enum DateInfoFlags { + CLF_OPTIONAL = 1 << 0, /* token is non mandatory */ + CLF_POSIXSEC = 1 << 1, + CLF_LOCALSEC = 1 << 2, + CLF_JULIANDAY = 1 << 3, + CLF_TIME = 1 << 4, + CLF_ZONE = 1 << 5, + CLF_CENTURY = 1 << 6, + CLF_DAYOFMONTH = 1 << 7, + CLF_DAYOFYEAR = 1 << 8, + CLF_MONTH = 1 << 9, + CLF_YEAR = 1 << 10, + CLF_DAYOFWEEK = 1 << 11, + CLF_ISO8601YEAR = 1 << 12, + CLF_ISO8601WEAK = 1 << 13, + CLF_ISO8601CENTURY = 1 << 14, + + CLF_SIGNED = 1 << 15, + + /* Compounds */ + + CLF_HAVEDATE = (CLF_DAYOFMONTH | CLF_MONTH | CLF_YEAR), + CLF_DATE = (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR + | CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR + | CLF_DAYOFWEEK | CLF_ISO8601WEAK), + + /* + * Extra flags used outside of scan/format-tokens too (int, not a short). + */ + + CLF_RELCONV = 1 << 17, + CLF_ORDINALMONTH = 1 << 18, + + /* On demand (lazy) assemble flags */ + + CLF_ASSEMBLE_DATE = 1 << 28,/* assemble year, month, etc. using julianDay */ + CLF_ASSEMBLE_JULIANDAY = 1 << 29, + /* assemble julianDay using year, month, etc. */ + CLF_ASSEMBLE_SECONDS = 1 << 30 + /* assemble localSeconds (and seconds at end) */ +}; -#define CLF_OPTIONAL (1 << 0) /* token is non mandatory */ -#define CLF_POSIXSEC (1 << 1) -#define CLF_LOCALSEC (1 << 2) -#define CLF_JULIANDAY (1 << 3) -#define CLF_TIME (1 << 4) -#define CLF_ZONE (1 << 5) -#define CLF_CENTURY (1 << 6) -#define CLF_DAYOFMONTH (1 << 7) -#define CLF_DAYOFYEAR (1 << 8) -#define CLF_MONTH (1 << 9) -#define CLF_YEAR (1 << 10) -#define CLF_DAYOFWEEK (1 << 11) -#define CLF_ISO8601YEAR (1 << 12) -#define CLF_ISO8601WEAK (1 << 13) -#define CLF_ISO8601CENTURY (1 << 14) - -#define CLF_SIGNED (1 << 15) - -/* extra flags used outside of scan/format-tokens too (int, not a short int) */ -#define CLF_RELCONV (1 << 17) -#define CLF_ORDINALMONTH (1 << 18) - -/* On demand (lazy) assemble flags */ -#define CLF_ASSEMBLE_DATE (1 << 28) /* assemble year, month, etc. using julianDay */ -#define CLF_ASSEMBLE_JULIANDAY (1 << 29) /* assemble julianDay using year, month, etc. */ -#define CLF_ASSEMBLE_SECONDS (1 << 30) /* assemble localSeconds (and seconds at end) */ - -#define CLF_HAVEDATE (CLF_DAYOFMONTH|CLF_MONTH|CLF_YEAR) -#define CLF_DATE (CLF_JULIANDAY | CLF_DAYOFMONTH | CLF_DAYOFYEAR | \ - CLF_MONTH | CLF_YEAR | CLF_ISO8601YEAR | \ - CLF_DAYOFWEEK | CLF_ISO8601WEAK) - -#define TCL_MIN_SECONDS -0x00F0000000000000LL -#define TCL_MAX_SECONDS 0x00F0000000000000LL -#define TCL_INV_SECONDS (TCL_MIN_SECONDS-1) +#define TCL_MIN_SECONDS -0x00F0000000000000LL +#define TCL_MAX_SECONDS 0x00F0000000000000LL +#define TCL_INV_SECONDS (TCL_MIN_SECONDS - 1) /* * Enumeration of the string literals used in [clock] @@ -148,10 +157,11 @@ typedef enum ClockMsgCtLiteral { * Structure containing the fields used in [clock format] and [clock scan] */ -#define CLF_CTZ (1 << 4) +enum TclDateFieldsFlags { + CLF_CTZ = (1 << 4) +}; typedef struct TclDateFields { - /* Cacheable fields: */ Tcl_WideInt seconds; /* Time expressed in seconds from the Posix @@ -270,15 +280,19 @@ ClockInitDateInfo( * Structure containing the command arguments supplied to [clock format] and [clock scan] */ -#define CLF_VALIDATE_S1 (1 << 0) -#define CLF_VALIDATE_S2 (1 << 1) -#define CLF_VALIDATE (CLF_VALIDATE_S1|CLF_VALIDATE_S2) -#define CLF_EXTENDED (1 << 4) -#define CLF_STRICT (1 << 8) -#define CLF_LOCALE_USED (1 << 15) +enum ClockFmtScnCmdArgsFlags { + CLF_VALIDATE_S1 = (1 << 0), + CLF_VALIDATE_S2 = (1 << 1), + CLF_VALIDATE = (CLF_VALIDATE_S1|CLF_VALIDATE_S2), + CLF_EXTENDED = (1 << 4), + CLF_STRICT = (1 << 8), + CLF_LOCALE_USED = (1 << 15) +}; + +typedef struct ClockClientData ClockClientData; typedef struct ClockFmtScnCmdArgs { - void *clientData; /* Opaque pointer to literal pool, etc. */ + ClockClientData *dataPtr; /* Pointer to literal pool, etc. */ Tcl_Interp *interp; /* Tcl interpreter */ Tcl_Obj *formatObj; /* Format */ Tcl_Obj *localeObj; /* Name of the locale where the time will be expressed. */ @@ -422,10 +436,12 @@ typedef struct DateFormat { Tcl_Obj *localeEra; } DateFormat; -#define CLFMT_INCR (1 << 3) -#define CLFMT_DECR (1 << 4) -#define CLFMT_CALC (1 << 5) -#define CLFMT_LOCALE_INDX (1 << 8) +enum ClockFormatTokenMapFlags { + CLFMT_INCR = (1 << 3), + CLFMT_DECR = (1 << 4), + CLFMT_CALC = (1 << 5), + CLFMT_LOCALE_INDX = (1 << 8) +}; typedef struct ClockFormatToken ClockFormatToken; @@ -513,7 +529,7 @@ MODULE_SCOPE void GetJulianDayFromEraYearMonthDay( TclDateFields *fields, int changeover); MODULE_SCOPE void GetJulianDayFromEraYearDay( TclDateFields *fields, int changeover); -MODULE_SCOPE int ConvertUTCToLocal(void *clientData, Tcl_Interp *, +MODULE_SCOPE int ConvertUTCToLocal(ClockClientData *dataPtr, Tcl_Interp *, TclDateFields *, Tcl_Obj *timezoneObj, int); MODULE_SCOPE Tcl_Obj * LookupLastTransition(Tcl_Interp *, Tcl_WideInt, Tcl_Size, Tcl_Obj *const *, Tcl_WideInt *rangesVal); @@ -521,7 +537,7 @@ MODULE_SCOPE int TclClockFreeScan(Tcl_Interp *interp, DateInfo *info); /* tclClock.c module declarations */ -MODULE_SCOPE Tcl_Obj * ClockSetupTimeZone(void *clientData, +MODULE_SCOPE Tcl_Obj * ClockSetupTimeZone(ClockClientData *dataPtr, Tcl_Interp *interp, Tcl_Obj *timezoneObj); MODULE_SCOPE Tcl_Obj * ClockMCDict(ClockFmtScnCmdArgs *opts); MODULE_SCOPE Tcl_Obj * ClockMCGet(ClockFmtScnCmdArgs *opts, int mcKey); diff --git a/generic/tclStrIdxTree.c b/generic/tclStrIdxTree.c index a1c83a9..533f73d 100644 --- a/generic/tclStrIdxTree.c +++ b/generic/tclStrIdxTree.c @@ -462,7 +462,7 @@ TclStrIdxTreePrint( Tcl_Obj *obj[2]; const char *s; - TclInitObjRef(obj[0], Tcl_NewStringObj("::puts", -1)); + TclInitObjRef(obj[0], Tcl_NewStringObj("::puts", TCL_AUTO_LENGTH)); while (tree != NULL) { s = TclGetString(tree->key) + offs; TclInitObjRef(obj[1], Tcl_ObjPrintf("%*s%.*s\t:%d", |
