From d1b1eb61ee0797c47516c143c37e76b3dc676a1d Mon Sep 17 00:00:00 2001 From: sebres Date: Tue, 29 May 2018 17:20:36 +0000 Subject: try to re-implement validation rules for `clock scan` (option `-valid 1|0`), see http://core.tcl.tk/tcl/tktview?name=3475995 --- generic/tclClock.c | 51 +++++++++++++++++++++++++++++++++++++++++++++------ generic/tclDate.h | 4 ++++ tests/clock.test | 2 +- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/generic/tclClock.c b/generic/tclClock.c index 2e74735..0074de1 100644 --- a/generic/tclClock.c +++ b/generic/tclClock.c @@ -261,6 +261,8 @@ TclClockInit( data->utc2local.tzName = NULL; data->local2utc.timezoneObj = NULL; + data->defFlags = 0; + /* * Install the commands. */ @@ -974,12 +976,14 @@ ClockConfigureObjCmd( "-system-tz", "-setup-tz", "-default-locale", "-current-locale", "-clear", "-year-century", "-century-switch", + "-validate", NULL }; enum optionInd { CLOCK_SYSTEM_TZ, CLOCK_SETUP_TZ, CLOCK_DEFAULT_LOCALE, CLOCK_CURRENT_LOCALE, CLOCK_CLEAR_CACHE, - CLOCK_YEAR_CENTURY, CLOCK_CENTURY_SWITCH + CLOCK_YEAR_CENTURY, CLOCK_CENTURY_SWITCH, + CLOCK_VALIDATE }; int optionIndex; /* Index of an option. */ int i; @@ -1078,6 +1082,23 @@ ClockConfigureObjCmd( Tcl_NewIntObj(dataPtr->yearOfCenturySwitch)); } break; + case CLOCK_VALIDATE: + if (i < objc) { + int val; + if (Tcl_GetBooleanFromObj(interp, objv[i], &val) != TCL_OK) { + return TCL_ERROR; + } + if (val) { + dataPtr->defFlags |= CLF_VALIDATE; + } else { + dataPtr->defFlags &= ~CLF_VALIDATE; + } + } + if (i+1 >= objc) { + Tcl_SetObjResult(interp, + Tcl_NewIntObj(dataPtr->defFlags & CLF_VALIDATE ? 1 : 0)); + } + break; case CLOCK_CLEAR_CACHE: ClockConfigureClear(dataPtr); break; @@ -3208,19 +3229,22 @@ ClockParseFmtScnArgs( ClockClientData *dataPtr = opts->clientData; int gmtFlag = 0; static const char *const options[] = { - "-base", "-format", "-gmt", "-locale", "-timezone", NULL + "-base", "-format", "-gmt", "-locale", "-timezone", "-validate", NULL }; enum optionInd { CLC_ARGS_BASE, CLC_ARGS_FORMAT, CLC_ARGS_GMT, CLC_ARGS_LOCALE, - CLC_ARGS_TIMEZONE, + CLC_ARGS_TIMEZONE, CLC_ARGS_VALIDATE }; int optionIndex; /* Index of an option. */ int saw = 0; /* Flag == 1 if option was seen already. */ int i; Tcl_WideInt baseVal; /* Base time, expressed in seconds from the Epoch */ - /* clock value (as current base) */ - if ( !(flags & (CLC_SCN_ARGS)) ) { + if ( flags & (CLC_SCN_ARGS) ) { + /* default flags (from configure) */ + opts->flags |= dataPtr->defFlags & (CLF_VALIDATE); + } else { + /* clock value (as current base) */ opts->baseObj = objv[1]; saw |= (1 << CLC_ARGS_BASE); } @@ -3275,6 +3299,21 @@ ClockParseFmtScnArgs( case CLC_ARGS_BASE: opts->baseObj = objv[i+1]; break; + case CLC_ARGS_VALIDATE: + if ( !(flags & CLC_SCN_ARGS) ) { + goto badOptionMsg; + } else { + int val; + if (Tcl_GetBooleanFromObj(interp, objv[i+1], &val) != TCL_OK) { + return TCL_ERROR; + } + if (val) { + opts->flags |= CLF_VALIDATE; + } else { + opts->flags &= ~CLF_VALIDATE; + } + } + break; } saw |= (1 << optionIndex); } @@ -3510,7 +3549,7 @@ ClockScanObjCmd( "?-base seconds? " "?-format string? " "?-gmt boolean? " - "?-locale LOCALE? ?-timezone ZONE?"; + "?-locale LOCALE? ?-timezone ZONE? ?-validate boolean?"; int ret; ClockFmtScnCmdArgs opts; /* Format, locale, timezone and base */ DateInfo yy; /* Common structure used for parsing */ diff --git a/generic/tclDate.h b/generic/tclDate.h index c52dd0a..a88639d 100644 --- a/generic/tclDate.h +++ b/generic/tclDate.h @@ -253,6 +253,7 @@ ClockInitDateInfo(DateInfo *info) { * Structure containing the command arguments supplied to [clock format] and [clock scan] */ +#define CLF_VALIDATE (1 << 2) #define CLF_EXTENDED (1 << 4) #define CLF_STRICT (1 << 8) #define CLF_LOCALE_USED (1 << 15) @@ -338,6 +339,9 @@ typedef struct ClockClientData { /* values */ int tzOffset; } local2utc; + + int defFlags; /* Default flags (from configure), ATM + * only CLF_VALIDATE supported */ } ClockClientData; #define ClockDefaultYearCentury 2000 diff --git a/tests/clock.test b/tests/clock.test index 2d39c1e..5cced17 100644 --- a/tests/clock.test +++ b/tests/clock.test @@ -35827,7 +35827,7 @@ test clock-33.11a {clock test, millis align with micros} { } {1} # clock scan -set syntax "clock scan string ?-base seconds? ?-format string? ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?" +set syntax "clock scan string ?-base seconds? ?-format string? ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE? ?-validate boolean?" test clock-34.1 {clock scan tests} { list [catch {clock scan} msg] $msg } [subst {1 {wrong # args: should be "$syntax"}}] -- cgit v0.12