Skip to content

Commit 8a496f1

Browse files
committed
Refactor core ensemble creation/management so that the tables describing what's there and what's safe are visible in the core of interpreter creation
2 parents 0466217 + 7cc2a3f commit 8a496f1

22 files changed

+639
-787
lines changed

generic/tclBasic.c

Lines changed: 175 additions & 165 deletions
Large diffs are not rendered by default.

generic/tclBinary.c

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -120,20 +120,20 @@ static const char B64Digits[65] = {
120120
* How to construct the ensembles.
121121
*/
122122

123-
static const EnsembleImplMap binaryMap[] = {
123+
const EnsembleImplMap tclBinaryImplMap[] = {
124124
{ "format", BinaryFormatCmd, TclCompileBasicMin1ArgCmd, NULL, NULL, 0 },
125-
{ "scan", BinaryScanCmd, TclCompileBasicMin2ArgCmd, NULL, NULL, 0 },
125+
{ "scan", BinaryScanCmd, TclCompileBasicMin2ArgCmd, NULL, NULL, 0 }, // TODO: compile?
126126
{ "encode", NULL, NULL, NULL, NULL, 0 },
127127
{ "decode", NULL, NULL, NULL, NULL, 0 },
128128
{ NULL, NULL, NULL, NULL, NULL, 0 }
129129
};
130-
static const EnsembleImplMap encodeMap[] = {
130+
const EnsembleImplMap tclBinaryEncodeImplMap[] = {
131131
{ "hex", BinaryEncodeHex, TclCompileBasic1ArgCmd, NULL, NULL, 0 },
132132
{ "uuencode", BinaryEncodeUu, NULL, NULL, NULL, 0 },
133133
{ "base64", BinaryEncode64, NULL, NULL, NULL, 0 },
134134
{ NULL, NULL, NULL, NULL, NULL, 0 }
135135
};
136-
static const EnsembleImplMap decodeMap[] = {
136+
const EnsembleImplMap tclBinaryDecodeImplMap[] = {
137137
{ "hex", BinaryDecodeHex, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
138138
{ "uuencode", BinaryDecodeUu, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
139139
{ "base64", BinaryDecode64, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0 },
@@ -785,35 +785,6 @@ TclAppendBytesToByteArray(
785785
TclInvalidateStringRep(objPtr);
786786
}
787787

788-
/*
789-
*----------------------------------------------------------------------
790-
*
791-
* TclInitBinaryCmd --
792-
*
793-
* This function is called to create the "binary" Tcl command. See the
794-
* user documentation for details on what it does.
795-
*
796-
* Results:
797-
* A command token for the new command.
798-
*
799-
* Side effects:
800-
* Creates a new binary command as a mapped ensemble.
801-
*
802-
*----------------------------------------------------------------------
803-
*/
804-
805-
Tcl_Command
806-
TclInitBinaryCmd(
807-
Tcl_Interp *interp)
808-
{
809-
Tcl_Command binaryEnsemble;
810-
811-
binaryEnsemble = TclMakeEnsemble(interp, "binary", binaryMap);
812-
TclMakeEnsemble(interp, "binary encode", encodeMap);
813-
TclMakeEnsemble(interp, "binary decode", decodeMap);
814-
return binaryEnsemble;
815-
}
816-
817788
/*
818789
*----------------------------------------------------------------------
819790
*

generic/tclClock.c

Lines changed: 66 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
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 *);
114117
static size_t TzsetIfNecessary(void);
115118
static void ClockDeleteCmdProc(void *);
116119
static void ClockFinalize(void *);
120+
117121
/*
118122
* Structure containing description of "native" clock commands to create.
119123
*/
120-
121124
struct 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+
*/
133141
static 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
171193
TclClockInit(
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

Comments
 (0)