2222#pragma clang diagnostic ignored "-Wc++-keyword"
2323#endif
2424
25+ /* The namespace containing the [clock] internals. */
26+ #define TCL_CLOCK_NS "::tcl::clock"
27+
2528/*
2629 * Table of the days in each month, leap and common years
2730 */
@@ -114,10 +117,10 @@ static struct tm * ThreadSafeLocalTime(const time_t *);
114117static size_t TzsetIfNecessary (void );
115118static void ClockDeleteCmdProc (void * );
116119static void ClockFinalize (void * );
120+
117121/*
118122 * Structure containing description of "native" clock commands to create.
119123 */
120-
121124struct ClockCommand {
122125 const char * name ; /* The tail of the command name. The full name
123126 * is "::tcl::clock::<name>". When NULL marks
@@ -126,27 +129,46 @@ struct ClockCommand {
126129 * will always have the ClockClientData sent
127130 * to it, but may well ignore this data. */
128131 CompileProc * compileProc ; /* The compiler for the command. */
129- void * clientData ; /* Any clientData to give the command (if NULL
130- * a reference to ClockClientData will be sent) */
132+ int useClientData ; /* Whether to use the shared ClockClientData
133+ * with this command. */
131134};
132135
136+ /*
137+ * Table of command created by this file, excluding the compiled parts of the
138+ * [clock] ensemble, as those are defined below (and never need access to the
139+ * ClockClientData).
140+ */
133141static const struct ClockCommand clockCommands [] = {
134- {"add" , ClockAddObjCmd , TclCompileBasicMin1ArgCmd , NULL },
135- {"clicks" , ClockClicksObjCmd , TclCompileClockClicksCmd , NULL },
136- {"format" , ClockFormatObjCmd , TclCompileBasicMin1ArgCmd , NULL },
137- {"getenv" , ClockGetenvObjCmd , TclCompileBasicMin1ArgCmd , NULL },
138- {"microseconds" , ClockMicrosecondsObjCmd ,TclCompileClockReadingCmd , INT2PTR (CLOCK_READ_MICROS )},
139- {"milliseconds" , ClockMillisecondsObjCmd ,TclCompileClockReadingCmd , INT2PTR (CLOCK_READ_MILLIS )},
140- {"scan" , ClockScanObjCmd , TclCompileBasicMin1ArgCmd , NULL },
141- {"seconds" , ClockSecondsObjCmd , TclCompileClockReadingCmd , INT2PTR (CLOCK_READ_SECS )},
142- {"ConvertLocalToUTC" , ClockConvertlocaltoutcObjCmd , NULL , NULL },
143- {"GetDateFields" , ClockGetdatefieldsObjCmd , NULL , NULL },
142+ {"add" , ClockAddObjCmd , TclCompileBasicMin1ArgCmd , 1 },
143+ {"format" , ClockFormatObjCmd , TclCompileBasicMin1ArgCmd , 1 },
144+ {"getenv" , ClockGetenvObjCmd , NULL , 1 },
145+ {"scan" , ClockScanObjCmd , TclCompileBasicMin1ArgCmd , 1 },
146+ {"ConvertLocalToUTC" , ClockConvertlocaltoutcObjCmd , NULL , 1 },
147+ {"GetDateFields" , ClockGetdatefieldsObjCmd , NULL , 1 },
144148 {"GetJulianDayFromEraYearMonthDay" ,
145- ClockGetjuliandayfromerayearmonthdayObjCmd , NULL , NULL },
149+ ClockGetjuliandayfromerayearmonthdayObjCmd , NULL , 1 },
146150 {"GetJulianDayFromEraYearWeekDay" ,
147- ClockGetjuliandayfromerayearweekdayObjCmd , NULL , NULL },
148- {"catch" , TclSafeCatchCmd , TclCompileBasicMin1ArgCmd , NULL },
149- {NULL , NULL , NULL , NULL }
151+ ClockGetjuliandayfromerayearweekdayObjCmd , NULL , 1 },
152+ {"catch" , TclSafeCatchCmd , NULL , 0 },
153+ {NULL , NULL , NULL , 0 }
154+ };
155+
156+ /*
157+ * Definition of the [clock] ensemble.
158+ *
159+ * [clock add], [clock format] and [clock scan] have special clientData, so
160+ * we just tell the ensemble that they'll be there instead of maxing them at
161+ * this point.
162+ */
163+ const EnsembleImplMap tclClockImplMap [] = {
164+ {"add" , NULL , NULL , NULL , NULL , 1 },
165+ {"clicks" , ClockClicksObjCmd , TclCompileClockClicksCmd , NULL , NULL , 0 },
166+ {"format" , NULL , NULL , NULL , NULL , 1 },
167+ {"microseconds" , ClockMicrosecondsObjCmd ,TclCompileClockReadingCmd , NULL , INT2PTR (CLOCK_READ_MICROS ), 0 },
168+ {"milliseconds" , ClockMillisecondsObjCmd ,TclCompileClockReadingCmd , NULL , INT2PTR (CLOCK_READ_MILLIS ), 0 },
169+ {"scan" , NULL , NULL , NULL , NULL , 1 },
170+ {"seconds" , ClockSecondsObjCmd , TclCompileClockReadingCmd , NULL , INT2PTR (CLOCK_READ_SECS ), 0 },
171+ {NULL , NULL , NULL , NULL , NULL , 0 }
150172};
151173
152174/*
@@ -171,15 +193,8 @@ void
171193TclClockInit (
172194 Tcl_Interp * interp ) /* Tcl interpreter */
173195{
174- const struct ClockCommand * clockCmdPtr ;
175- char cmdName [50 ]; /* Buffer large enough to hold the string
176- *::tcl::clock::GetJulianDayFromEraYearMonthDay
177- * plus a terminating NUL. */
178- Command * cmdPtr ;
179- ClockClientData * data ;
180- int i ;
181-
182196 static int initialized = 0 ; /* global clock engine initialized (in process) */
197+
183198 /*
184199 * Register handler to finalize clock on exit.
185200 */
@@ -201,9 +216,10 @@ TclClockInit(
201216 * Create the client data, which is a refcounted literal pool.
202217 */
203218
204- data = (ClockClientData * )Tcl_Alloc (sizeof (ClockClientData ));
219+ ClockClientData * data = (ClockClientData * )Tcl_Alloc (sizeof (ClockClientData ));
205220 data -> refCount = 0 ;
206221 data -> literals = (Tcl_Obj * * )Tcl_Alloc (LIT__END * sizeof (Tcl_Obj * ));
222+ int i ;
207223 for (i = 0 ; i < LIT__END ; ++ i ) {
208224 TclInitObjRef (data -> literals [i ], Tcl_NewStringObj (
209225 Literals [i ], TCL_AUTO_LENGTH ));
@@ -253,27 +269,22 @@ TclClockInit(
253269 * Install the commands.
254270 */
255271
256- #define TCL_CLOCK_PREFIX_LEN 14 /* == strlen("::tcl::clock::") */
257- memcpy ( cmdName , "::tcl::clock::" , TCL_CLOCK_PREFIX_LEN ) ;
272+ Tcl_Namespace * nsPtr = Tcl_FindNamespace ( interp , TCL_CLOCK_NS , NULL , 0 );
273+ const struct ClockCommand * clockCmdPtr ;
258274 for (clockCmdPtr = clockCommands ; clockCmdPtr -> name != NULL ; clockCmdPtr ++ ) {
259- void * clientData ;
260-
261- strcpy (cmdName + TCL_CLOCK_PREFIX_LEN , clockCmdPtr -> name );
262- if (!(clientData = clockCmdPtr -> clientData )) {
275+ void * clientData = NULL ;
276+ if (clockCmdPtr -> useClientData ) {
263277 clientData = data ;
264278 data -> refCount ++ ;
265279 }
266- cmdPtr = (Command * )Tcl_CreateObjCommand (interp , cmdName ,
267- clockCmdPtr -> objCmdProc , clientData ,
268- clockCmdPtr -> clientData ? NULL : ClockDeleteCmdProc );
269- cmdPtr -> compileProc = clockCmdPtr -> compileProc ?
270- clockCmdPtr -> compileProc : TclCompileBasicMin0ArgCmd ;
271- }
272- cmdPtr = (Command * ) Tcl_CreateObjCommand (interp ,
273- "::tcl::unsupported::clock::configure" ,
280+ Command * cmdPtr = (Command * )TclCreateObjCommandInNs (interp ,
281+ clockCmdPtr -> name , nsPtr , clockCmdPtr -> objCmdProc , clientData ,
282+ clientData ? ClockDeleteCmdProc : NULL );
283+ cmdPtr -> compileProc = clockCmdPtr -> compileProc ;
284+ }
285+ Tcl_CreateObjCommand (interp , "::tcl::unsupported::clock::configure" ,
274286 ClockConfigureObjCmd , data , ClockDeleteCmdProc );
275287 data -> refCount ++ ;
276- cmdPtr -> compileProc = TclCompileBasicMin0ArgCmd ;
277288}
278289
279290/*
@@ -959,16 +970,16 @@ ClockConfigureObjCmd(
959970{
960971 ClockClientData * dataPtr = (ClockClientData * )clientData ;
961972 static const char * const options [] = {
962- "-default-locale" , "-clear" , "-current-locale" ,
963- "-year-century" , "-century-switch" ,
964- "-min-year" , "-max-year" , "-max-jdn" , "-validate " ,
965- "-init-complete " , "-setup-tz" , "-system-tz" , NULL
973+ "-default-locale" , "-clear" , "-current-locale" ,
974+ "-year-century" , "-century-switch" ,
975+ "-min-year" , "-max-year" , "-max-jdn" ,
976+ "-validate " , "-setup-tz" , "-system-tz" , NULL
966977 };
967978 enum optionInd {
968979 CLOCK_DEFAULT_LOCALE , CLOCK_CLEAR_CACHE , CLOCK_CURRENT_LOCALE ,
969980 CLOCK_YEAR_CENTURY , CLOCK_CENTURY_SWITCH ,
970981 CLOCK_MIN_YEAR , CLOCK_MAX_YEAR , CLOCK_MAX_JDN , CLOCK_VALIDATE ,
971- CLOCK_INIT_COMPLETE , CLOCK_SETUP_TZ , CLOCK_SYSTEM_TZ
982+ CLOCK_SETUP_TZ , CLOCK_SYSTEM_TZ
972983 };
973984 int optionIndex ; /* Index of an option. */
974985 Tcl_Size i ;
@@ -1140,26 +1151,6 @@ ClockConfigureObjCmd(
11401151 case CLOCK_CLEAR_CACHE :
11411152 ClockConfigureClear (dataPtr );
11421153 break ;
1143- case CLOCK_INIT_COMPLETE : {
1144- /*
1145- * Init completed.
1146- * Compile clock ensemble (performance purposes).
1147- */
1148- Tcl_Command token = Tcl_FindCommand (interp , "::clock" ,
1149- NULL , TCL_GLOBAL_ONLY );
1150- if (!token ) {
1151- return TCL_ERROR ;
1152- }
1153- int ensFlags = 0 ;
1154- if (Tcl_GetEnsembleFlags (interp , token , & ensFlags ) != TCL_OK ) {
1155- return TCL_ERROR ;
1156- }
1157- ensFlags |= ENSEMBLE_COMPILE ;
1158- if (Tcl_SetEnsembleFlags (interp , token , ensFlags ) != TCL_OK ) {
1159- return TCL_ERROR ;
1160- }
1161- break ;
1162- }
11631154 default :
11641155 TCL_UNREACHABLE ();
11651156 }
@@ -1418,7 +1409,6 @@ ClockConvertlocaltoutcObjCmd(
14181409 int changeover ;
14191410 TclDateFields fields ;
14201411 int created = 0 ;
1421- int status ;
14221412
14231413 fields .tzName = NULL ;
14241414 /*
@@ -1455,15 +1445,15 @@ ClockConvertlocaltoutcObjCmd(
14551445 created = 1 ;
14561446 Tcl_IncrRefCount (dict );
14571447 }
1458- status = Tcl_DictObjPut (interp , dict , dataPtr -> literals [LIT_SECONDS ],
1448+ int result = Tcl_DictObjPut (interp , dict , dataPtr -> literals [LIT_SECONDS ],
14591449 Tcl_NewWideIntObj (fields .seconds ));
1460- if (status == TCL_OK ) {
1450+ if (result == TCL_OK ) {
14611451 Tcl_SetObjResult (interp , dict );
14621452 }
14631453 if (created ) {
14641454 Tcl_DecrRefCount (dict );
14651455 }
1466- return status ;
1456+ return result ;
14671457}
14681458
14691459/*
@@ -1702,7 +1692,6 @@ ClockGetjuliandayfromerayearmonthdayObjCmd(
17021692 Tcl_Obj * const * lit = data -> literals ;
17031693 int changeover ;
17041694 int copied = 0 ;
1705- int status ;
17061695 int isBce = 0 ;
17071696
17081697 fields .tzName = NULL ;
@@ -1743,15 +1732,15 @@ ClockGetjuliandayfromerayearmonthdayObjCmd(
17431732 Tcl_IncrRefCount (dict );
17441733 copied = 1 ;
17451734 }
1746- status = Tcl_DictObjPut (interp , dict , lit [LIT_JULIANDAY ],
1735+ int result = Tcl_DictObjPut (interp , dict , lit [LIT_JULIANDAY ],
17471736 Tcl_NewWideIntObj (fields .julianDay ));
1748- if (status == TCL_OK ) {
1737+ if (result == TCL_OK ) {
17491738 Tcl_SetObjResult (interp , dict );
17501739 }
17511740 if (copied ) {
17521741 Tcl_DecrRefCount (dict );
17531742 }
1754- return status ;
1743+ return result ;
17551744}
17561745
17571746/*
@@ -1788,7 +1777,6 @@ ClockGetjuliandayfromerayearweekdayObjCmd(
17881777 Tcl_Obj * const * lit = data -> literals ;
17891778 int changeover ;
17901779 int copied = 0 ;
1791- int status ;
17921780 int isBce = 0 ;
17931781
17941782 fields .tzName = NULL ;
@@ -1829,15 +1817,15 @@ ClockGetjuliandayfromerayearweekdayObjCmd(
18291817 Tcl_IncrRefCount (dict );
18301818 copied = 1 ;
18311819 }
1832- status = Tcl_DictObjPut (interp , dict , lit [LIT_JULIANDAY ],
1820+ int result = Tcl_DictObjPut (interp , dict , lit [LIT_JULIANDAY ],
18331821 Tcl_NewWideIntObj (fields .julianDay ));
1834- if (status == TCL_OK ) {
1822+ if (result == TCL_OK ) {
18351823 Tcl_SetObjResult (interp , dict );
18361824 }
18371825 if (copied ) {
18381826 Tcl_DecrRefCount (dict );
18391827 }
1840- return status ;
1828+ return result ;
18411829}
18421830
18431831/*
0 commit comments