Tcl Source Code

Check-in [ed50d4c0b3]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:A more simple solution to the challenge posed in the tip-689-proof-for-nathan branch, where the goal is to initialize [clock] on demand without [namespace unknown]. No additional namespaces are reused and no procedures are renamed.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | tip-689-proof-for-nathan-solved
Files: files | file ages | folders
SHA3-256: ed50d4c0b3c7782ede41ea739fba2dbe047b6dbdc493f1bea04bc46a018ab169
User & Date: pooryorick 2024-03-22 23:09:27
Context
2024-03-22
23:40
A more simple solution to the challenge posed in the tip-689-proof-for-nathan branch, where the goal... check-in: 5c8e11b5b7 user: pooryorick tags: tip-689-proof-for-nathan-solved2
23:09
A more simple solution to the challenge posed in the tip-689-proof-for-nathan branch, where the goal... Leaf check-in: ed50d4c0b3 user: pooryorick tags: tip-689-proof-for-nathan-solved
22:35
Generalize the [namespace ensemble configure ... -unknown] approach a little more for the purpose of... check-in: 332ef3ab83 user: pooryorick tags: tip-689-proof-for-nathan-solved
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclClock.c.

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
    const char *name;		/* The tail of the command name. The full name
				 * is "::tcl::clock::<name>". When NULL marks
				 * the end of the table. */
    Tcl_ObjCmdProc *objCmdProc; /* Function that implements the command. This
				 * will always have the ClockClientData sent
				 * to it, but may well ignore this data. */
    CompileProc *compileProc;	/* The compiler for the command. */
    int initialize;		/* 0 if no initialization is needed */
    void *clientData;	/* Any clientData to give the command (if NULL
    				 * a reference to ClockClientData will be sent) */
};

static const struct ClockCommand clockCommands[] = {
    {"add",		ClockAddObjCmd,		TclCompileBasicMin1ArgCmd, 1, NULL},
    {"clicks",		ClockClicksObjCmd,	TclCompileClockClicksCmd,  0, NULL},
    {"format",		ClockFormatObjCmd,	TclCompileBasicMin1ArgCmd, 1, NULL},
    {"getenv",		ClockGetenvObjCmd,	TclCompileBasicMin1ArgCmd, 0, NULL},
    {"microseconds",	ClockMicrosecondsObjCmd,TclCompileClockReadingCmd, 0, INT2PTR(1)},
    {"milliseconds",	ClockMillisecondsObjCmd,TclCompileClockReadingCmd, 0, INT2PTR(2)},
    {"scan",		ClockScanObjCmd,	TclCompileBasicMin1ArgCmd, 1, NULL},
    {"seconds",		ClockSecondsObjCmd,	TclCompileClockReadingCmd, 0, INT2PTR(3)},
    {"ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd,		NULL,  0, NULL},
    {"GetDateFields",	  ClockGetdatefieldsObjCmd,		NULL,  0, NULL},
    {"GetJulianDayFromEraYearMonthDay",
		ClockGetjuliandayfromerayearmonthdayObjCmd,	NULL,  0, NULL},
    {"GetJulianDayFromEraYearWeekDay",
		ClockGetjuliandayfromerayearweekdayObjCmd,	NULL,  0, NULL},
    {"catch",		ClockSafeCatchCmd,	TclCompileBasicMin1ArgCmd, 0, NULL},
    {NULL, NULL, NULL, 0, NULL}
};

/*
 *----------------------------------------------------------------------
 *
 * TclClockInit --
 *







<





|
|
|
|
|
|
|
|
|
|

|

|
|
|







129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    const char *name;		/* The tail of the command name. The full name
				 * is "::tcl::clock::<name>". When NULL marks
				 * the end of the table. */
    Tcl_ObjCmdProc *objCmdProc; /* Function that implements the command. This
				 * will always have the ClockClientData sent
				 * to it, but may well ignore this data. */
    CompileProc *compileProc;	/* The compiler for the command. */

    void *clientData;	/* Any clientData to give the command (if NULL
    				 * a reference to ClockClientData will be sent) */
};

static const struct ClockCommand clockCommands[] = {
    {"add",		ClockAddObjCmd,		TclCompileBasicMin1ArgCmd, NULL},
    {"clicks",		ClockClicksObjCmd,	TclCompileClockClicksCmd, NULL},
    {"format",		ClockFormatObjCmd,	TclCompileBasicMin1ArgCmd, NULL},
    {"getenv",		ClockGetenvObjCmd,	TclCompileBasicMin1ArgCmd, NULL},
    {"microseconds",	ClockMicrosecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(1)},
    {"milliseconds",	ClockMillisecondsObjCmd,TclCompileClockReadingCmd, INT2PTR(2)},
    {"scan",		ClockScanObjCmd,	TclCompileBasicMin1ArgCmd, NULL},
    {"seconds",		ClockSecondsObjCmd,	TclCompileClockReadingCmd, INT2PTR(3)},
    {"ConvertLocalToUTC", ClockConvertlocaltoutcObjCmd,		NULL, NULL},
    {"GetDateFields",	  ClockGetdatefieldsObjCmd,		NULL, NULL},
    {"GetJulianDayFromEraYearMonthDay",
		ClockGetjuliandayfromerayearmonthdayObjCmd,	NULL, NULL},
    {"GetJulianDayFromEraYearWeekDay",
		ClockGetjuliandayfromerayearweekdayObjCmd,	NULL, NULL},
    {"catch",		ClockSafeCatchCmd,	TclCompileBasicMin1ArgCmd, NULL},
    {NULL, NULL, NULL, NULL}
};

/*
 *----------------------------------------------------------------------
 *
 * TclClockInit --
 *
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
TclClockInit(
    Tcl_Interp *interp)		/* Tcl interpreter */
{
    const struct ClockCommand *clockCmdPtr;
    char cmdNamePublic[50];	/* Buffer large enough to hold the string
				 *::tcl::clock::GetJulianDayFromEraYearMonthDay
				 * plus a terminating NUL. */
    char cmdNameUninitialized[65];
				/* Buffer large enough to hold the string
				 *::tcl::clock::uninitialized::GetJulianDayFromEraYearMonthDay
				 * plus a terminating NUL. */
    char *cmdName;
    Command         *cmdPtr;
    ClockClientData *data;
    int i;

    /*
     * Safe interps get [::clock] as alias to a parent, so do not need their







<
<
<
<







178
179
180
181
182
183
184




185
186
187
188
189
190
191
TclClockInit(
    Tcl_Interp *interp)		/* Tcl interpreter */
{
    const struct ClockCommand *clockCmdPtr;
    char cmdNamePublic[50];	/* Buffer large enough to hold the string
				 *::tcl::clock::GetJulianDayFromEraYearMonthDay
				 * plus a terminating NUL. */




    char *cmdName;
    Command         *cmdPtr;
    ClockClientData *data;
    int i;

    /*
     * Safe interps get [::clock] as alias to a parent, so do not need their
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
    /*
     * Install the commands.
     */

#define TCL_CLOCK_PREFIX_LEN 14 /* == strlen("::tcl::clock::") */
#define TCL_CLOCK_UNINITIALIZED_PREFIX_LEN 29 /* == strlen("::tcl::clock::uninitialized::") */
    memcpy(cmdNamePublic, "::tcl::clock::", TCL_CLOCK_PREFIX_LEN);
    memcpy(cmdNameUninitialized, "::tcl::clock::uninitialized::"
	    , TCL_CLOCK_UNINITIALIZED_PREFIX_LEN);
    for (clockCmdPtr=clockCommands ; clockCmdPtr->name!=NULL ; clockCmdPtr++) {
    	void *clientData;

	if (clockCmdPtr->initialize == 1) {
	    cmdName = cmdNameUninitialized;
	    strcpy(cmdName + TCL_CLOCK_UNINITIALIZED_PREFIX_LEN, clockCmdPtr->name);
	} else {
	    cmdName = cmdNamePublic;
	    strcpy(cmdName + TCL_CLOCK_PREFIX_LEN, clockCmdPtr->name);
	}

	if (!(clientData = clockCmdPtr->clientData)) {
	    clientData = data;
	    data->refCount++;
	}
	cmdPtr = (Command *)Tcl_CreateObjCommand(interp, cmdName,
		clockCmdPtr->objCmdProc, clientData,







<
<



<
<
<
<
|
|
<







250
251
252
253
254
255
256


257
258
259




260
261

262
263
264
265
266
267
268
    /*
     * Install the commands.
     */

#define TCL_CLOCK_PREFIX_LEN 14 /* == strlen("::tcl::clock::") */
#define TCL_CLOCK_UNINITIALIZED_PREFIX_LEN 29 /* == strlen("::tcl::clock::uninitialized::") */
    memcpy(cmdNamePublic, "::tcl::clock::", TCL_CLOCK_PREFIX_LEN);


    for (clockCmdPtr=clockCommands ; clockCmdPtr->name!=NULL ; clockCmdPtr++) {
    	void *clientData;





	cmdName = cmdNamePublic;
	strcpy(cmdName + TCL_CLOCK_PREFIX_LEN, clockCmdPtr->name);


	if (!(clientData = clockCmdPtr->clientData)) {
	    clientData = data;
	    data->refCount++;
	}
	cmdPtr = (Command *)Tcl_CreateObjCommand(interp, cmdName,
		clockCmdPtr->objCmdProc, clientData,

Changes to library/init.tcl.

118
119
120
121
122
123
124

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
	namespace inscope ::tcl::clock [list namespace ensemble create -command \
	    [uplevel 1 [list ::namespace origin [::lindex [info level 0] 0]]] \
	    -map $cmdmap \
	    -unknown [
		list ::apply [list {name action args} {
		    # Auto-load clock.tcl
		    ::source -encoding utf-8 [::file join [info library] clock.tcl]

		    set ensemble [uplevel 1 [::list ::namespace which $name]]
		    set ns [namespace ensemble configure $ensemble -namespace]
		    set unns ${ns}::uninitialized
		    set cmdmap [namespace ensemble configure $ensemble -map]
		    foreach name [info commands ${unns}::*] {
			set tail [namespace tail $name]
			set target ${ns}::$tail
			rename $name $target
			dict set cmdmap [namespace tail $name] $target
		    }
		    namespace ensemble configure $ensemble -map $cmdmap -unknown {}
		    return
		} [namespace current]]
		]
	    ]
	::tcl::unsupported::clock::configure -init-complete







>


<

|
<
<
<
|







118
119
120
121
122
123
124
125
126
127

128
129



130
131
132
133
134
135
136
137
	namespace inscope ::tcl::clock [list namespace ensemble create -command \
	    [uplevel 1 [list ::namespace origin [::lindex [info level 0] 0]]] \
	    -map $cmdmap \
	    -unknown [
		list ::apply [list {name action args} {
		    # Auto-load clock.tcl
		    ::source -encoding utf-8 [::file join [info library] clock.tcl]
		    set uninitialized {add format scan}
		    set ensemble [uplevel 1 [::list ::namespace which $name]]
		    set ns [namespace ensemble configure $ensemble -namespace]

		    set cmdmap [namespace ensemble configure $ensemble -map]
		    foreach name $uninitialized {



			dict set cmdmap $name ${ns}::$name
		    }
		    namespace ensemble configure $ensemble -map $cmdmap -unknown {}
		    return
		} [namespace current]]
		]
	    ]
	::tcl::unsupported::clock::configure -init-complete