diff options
author | dgp <dgp@users.sourceforge.net> | 2007-11-21 16:26:57 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2007-11-21 16:26:57 (GMT) |
commit | f6088cd9143e40f8d8979840ce7540c1d855cff3 (patch) | |
tree | 58c5ed5badb0827faa480a2f33b2fbb441a75968 | |
parent | e0a8745f18080b7835c31fe5aa49d4e3ebd79780 (diff) | |
download | tcl-f6088cd9143e40f8d8979840ce7540c1d855cff3.zip tcl-f6088cd9143e40f8d8979840ce7540c1d855cff3.tar.gz tcl-f6088cd9143e40f8d8979840ce7540c1d855cff3.tar.bz2 |
merge updates from HEAD
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | generic/tclCmdIL.c | 45 | ||||
-rw-r--r-- | generic/tclIOGT.c | 590 | ||||
-rw-r--r-- | generic/tclInt.h | 18 | ||||
-rw-r--r-- | generic/tclNamesp.c | 76 | ||||
-rw-r--r-- | generic/tclPkg.c | 14 |
6 files changed, 392 insertions, 360 deletions
@@ -1,3 +1,12 @@ +2007-11-21 Donal K. Fellows <donal.k.fellows@manchester.ac.uk> + + * generic/tclNamesp.c (TclMakeEnsemble): Factor out the code to set up + a core ensemble from a table of information about subcommands, ready + for reuse within the core. + + * generic/various: Start to return more useful Error codes, currently + mainly on assorted lookup failures. + 2007-11-20 Donal K. Fellows <dkf@users.sf.net> * generic/tclDictObj.c: Changed the underlying implementation of the diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index 7d8a33b..b750d53 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -16,7 +16,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclCmdIL.c,v 1.115.2.10 2007/11/21 06:30:48 dgp Exp $ + * RCS: @(#) $Id: tclCmdIL.c,v 1.115.2.11 2007/11/21 16:26:59 dgp Exp $ */ #include "tclInt.h" @@ -149,11 +149,7 @@ static Tcl_Obj * SelectObjFromSublist(Tcl_Obj *firstPtr, * "info" command. */ -static const struct { - const char *name; /* The name of the subcommand. */ - Tcl_ObjCmdProc *proc; /* The implementation of the subcommand. */ - CompileProc *compileProc; /* The compiler for the subcommand. */ -} defaultInfoMap[] = { +static const EnsembleImplMap defaultInfoMap[] = { {"args", InfoArgsCmd, NULL}, {"body", InfoBodyCmd, NULL}, {"cmdcount", InfoCmdCountCmd, NULL}, @@ -388,42 +384,7 @@ Tcl_Command TclInitInfoCmd( Tcl_Interp *interp) /* Current interpreter. */ { - Tcl_Command ensemble; /* The overall ensemble. */ - Tcl_Namespace *tclNsPtr; /* Reference to the "::tcl" namespace. */ - - tclNsPtr = Tcl_FindNamespace(interp, "::tcl", NULL, - TCL_CREATE_NS_IF_UNKNOWN); - if (tclNsPtr == NULL) { - Tcl_Panic("unable to find or create ::tcl namespace!"); - } - tclNsPtr = Tcl_FindNamespace(interp, "::tcl::info", NULL, - TCL_CREATE_NS_IF_UNKNOWN); - if (tclNsPtr == NULL) { - Tcl_Panic("unable to find or create ::tcl::info namespace!"); - } - ensemble = Tcl_CreateEnsemble(interp, "::info", tclNsPtr, - TCL_ENSEMBLE_PREFIX | ENSEMBLE_COMPILE); - if (ensemble != NULL) { - Tcl_Obj *mapDict; - int i; - - TclNewObj(mapDict); - for (i=0 ; defaultInfoMap[i].name != NULL ; i++) { - Tcl_Obj *fromObj, *toObj; - Command *cmdPtr; - - fromObj = Tcl_NewStringObj(defaultInfoMap[i].name, -1); - TclNewLiteralStringObj(toObj, "::tcl::info::"); - Tcl_AppendToObj(toObj, defaultInfoMap[i].name, -1); - Tcl_DictObjPut(NULL, mapDict, fromObj, toObj); - cmdPtr = (Command *) Tcl_CreateObjCommand(interp, - TclGetString(toObj), defaultInfoMap[i].proc, NULL, NULL); - cmdPtr->compileProc = defaultInfoMap[i].compileProc; - } - Tcl_SetEnsembleMappingDict(interp, ensemble, mapDict); - } - - return ensemble; + return TclMakeEnsemble(interp, "info", defaultInfoMap); } /* diff --git a/generic/tclIOGT.c b/generic/tclIOGT.c index 99a058c..9a430b2 100644 --- a/generic/tclIOGT.c +++ b/generic/tclIOGT.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * CVS: $Id: tclIOGT.c,v 1.17.2.1 2007/11/12 19:18:17 dgp Exp $ + * CVS: $Id: tclIOGT.c,v 1.17.2.2 2007/11/21 16:26:59 dgp Exp $ */ #include "tclInt.h" @@ -24,18 +24,18 @@ static int TransformBlockModeProc(ClientData instanceData, int mode); static int TransformCloseProc(ClientData instanceData, - Tcl_Interp* interp); + Tcl_Interp *interp); static int TransformInputProc(ClientData instanceData, char *buf, int toRead, int *errorCodePtr); static int TransformOutputProc(ClientData instanceData, - CONST char *buf, int toWrite, int *errorCodePtr); + const char *buf, int toWrite, int *errorCodePtr); static int TransformSeekProc(ClientData instanceData, long offset, int mode, int *errorCodePtr); static int TransformSetOptionProc(ClientData instanceData, - Tcl_Interp *interp, CONST char *optionName, - CONST char *value); + Tcl_Interp *interp, const char *optionName, + const char *value); static int TransformGetOptionProc(ClientData instanceData, - Tcl_Interp *interp, CONST char *optionName, + Tcl_Interp *interp, const char *optionName, Tcl_DString *dsPtr); static void TransformWatchProc(ClientData instanceData, int mask); static int TransformGetFileHandleProc(ClientData instanceData, @@ -64,22 +64,22 @@ static int ExecuteCallback(TransformChannelData *ctrl, int preserve); /* - * Action codes to give to 'ExecuteCallback' (argument 'transmit') confering - * to the procedure what to do with the result of the script it calls. + * Action codes to give to 'ExecuteCallback' (argument 'transmit'), telling + * the procedure what to do with the result of the script it calls. */ -#define TRANSMIT_DONT (0) /* No transfer to do */ -#define TRANSMIT_DOWN (1) /* Transfer to the underlying channel */ -#define TRANSMIT_SELF (2) /* Transfer into our channel. */ -#define TRANSMIT_IBUF (3) /* Transfer to internal input buffer */ -#define TRANSMIT_NUM (4) /* Transfer number to 'maxRead' */ +#define TRANSMIT_DONT 0 /* No transfer to do. */ +#define TRANSMIT_DOWN 1 /* Transfer to the underlying channel. */ +#define TRANSMIT_SELF 2 /* Transfer into our channel. */ +#define TRANSMIT_IBUF 3 /* Transfer to internal input buffer. */ +#define TRANSMIT_NUM 4 /* Transfer number to 'maxRead'. */ /* - * Codes for 'preserve' of 'ExecuteCallback' + * Codes for 'preserve' of 'ExecuteCallback'. */ -#define P_PRESERVE (1) -#define P_NO_PRESERVE (0) +#define P_PRESERVE 1 +#define P_NO_PRESERVE 0 /* * Strings for the action codes delivered to the script implementing a @@ -105,69 +105,69 @@ static int ExecuteCallback(TransformChannelData *ctrl, typedef struct ResultBuffer ResultBuffer; -static void ResultClear(ResultBuffer *r); -static void ResultInit(ResultBuffer *r); -static int ResultLength(ResultBuffer *r); -static int ResultCopy(ResultBuffer *r, unsigned char *buf, - int toRead); -static void ResultAdd(ResultBuffer *r, unsigned char *buf, - int toWrite); +static inline void ResultClear(ResultBuffer *r); +static inline void ResultInit(ResultBuffer *r); +static inline int ResultEmpty(ResultBuffer *r); +static inline int ResultCopy(ResultBuffer *r, unsigned char *buf, + size_t toRead); +static inline void ResultAdd(ResultBuffer *r, unsigned char *buf, + size_t toWrite); /* - * This structure describes the channel type structure for Tcl based + * This structure describes the channel type structure for Tcl-based * transformations. */ static Tcl_ChannelType transformChannelType = { - "transform", /* Type name. */ - TCL_CHANNEL_VERSION_5, /* v5 channel */ - TransformCloseProc, /* Close proc. */ - TransformInputProc, /* Input proc. */ - TransformOutputProc, /* Output proc. */ - TransformSeekProc, /* Seek proc. */ - TransformSetOptionProc, /* Set option proc. */ - TransformGetOptionProc, /* Get option proc. */ - TransformWatchProc, /* Initialize notifier. */ - TransformGetFileHandleProc, /* Get OS handles out of channel. */ - NULL, /* close2proc */ - TransformBlockModeProc, /* Set blocking/nonblocking mode.*/ - NULL, /* Flush proc. */ - TransformNotifyProc, /* Handling of events bubbling up */ - TransformWideSeekProc, /* Wide seek proc */ - NULL, /* thread action */ - NULL, /* truncate */ + "transform", /* Type name. */ + TCL_CHANNEL_VERSION_5, /* v5 channel */ + TransformCloseProc, /* Close proc. */ + TransformInputProc, /* Input proc. */ + TransformOutputProc, /* Output proc. */ + TransformSeekProc, /* Seek proc. */ + TransformSetOptionProc, /* Set option proc. */ + TransformGetOptionProc, /* Get option proc. */ + TransformWatchProc, /* Initialize notifier. */ + TransformGetFileHandleProc, /* Get OS handles out of channel. */ + NULL, /* close2proc */ + TransformBlockModeProc, /* Set blocking/nonblocking mode.*/ + NULL, /* Flush proc. */ + TransformNotifyProc, /* Handling of events bubbling up. */ + TransformWideSeekProc, /* Wide seek proc. */ + NULL, /* Thread action. */ + NULL, /* Truncate. */ }; /* * Possible values for 'flags' field in control structure, see below. */ -#define CHANNEL_ASYNC (1<<0) /* non-blocking mode */ +#define CHANNEL_ASYNC (1<<0) /* Non-blocking mode. */ /* - * Definition of the structure containing the information about the - * internal input buffer. + * Definition of the structure containing the information about the internal + * input buffer. */ struct ResultBuffer { unsigned char *buf; /* Reference to the buffer area. */ - int allocated; /* Allocated size of the buffer area. */ - int used; /* Number of bytes in the buffer, <= - * allocated. */ + size_t allocated; /* Allocated size of the buffer area. */ + size_t used; /* Number of bytes in the buffer, no more than + * number allocated. */ }; /* - * Additional bytes to allocate during buffer expansion + * Additional bytes to allocate during buffer expansion. */ -#define INCREMENT (512) +#define INCREMENT 512 /* * Number of milliseconds to wait before firing an event to flush out * information waiting in buffers (fileevent support). */ -#define FLUSH_DELAY (5) +#define FLUSH_DELAY 5 /* * Convenience macro to make some casts easier to use. @@ -202,16 +202,16 @@ struct TransformChannelData { */ int maxRead; /* Maximum allowed number of bytes to read, as - * given to us by the tcl script implementing + * given to us by the Tcl script implementing * the transformation. */ Tcl_Interp *interp; /* Reference to the interpreter which created * the transformation. Used to execute the * code below. */ Tcl_Obj *command; /* Tcl code to execute for a buffer */ ResultBuffer result; /* Internal buffer used to store the result of - * a transformation of incoming data. - * Additionally serves as buffer of all data - * not yet consumed by the reader. */ + * a transformation of incoming data. Also + * serves as buffer of all data not yet + * consumed by the reader. */ }; /* @@ -240,15 +240,15 @@ TclChannelTransform( Tcl_Obj *cmdObjPtr) /* Script to use for transform. */ { Channel *chanPtr; /* The actual channel. */ - ChannelState *statePtr; /* state info for channel */ - int mode; /* rw mode of the channel */ + ChannelState *statePtr; /* State info for channel. */ + int mode; /* Read/write mode of the channel. */ TransformChannelData *dataPtr; - int res; Tcl_DString ds; - if (chan == (Tcl_Channel) NULL) { + if (chan == NULL) { return TCL_ERROR; } + chanPtr = (Channel *) chan; statePtr = chanPtr->state; chanPtr = statePtr->topChanPtr; @@ -263,36 +263,31 @@ TclChannelTransform( dataPtr = (TransformChannelData *) ckalloc(sizeof(TransformChannelData)); - Tcl_DStringInit (&ds); + Tcl_DStringInit(&ds); Tcl_GetChannelOption(interp, chan, "-blocking", &ds); - dataPtr->readIsFlushed = 0; - dataPtr->flags = 0; - + dataPtr->flags = 0; if (ds.string[0] == '0') { dataPtr->flags |= CHANNEL_ASYNC; } - Tcl_DStringFree(&ds); dataPtr->self = chan; dataPtr->watchMask = 0; dataPtr->mode = mode; - dataPtr->timer = (Tcl_TimerToken) NULL; - dataPtr->maxRead = 4096; /* Initial value not relevant */ + dataPtr->timer = NULL; + dataPtr->maxRead = 4096; /* Initial value not relevant. */ dataPtr->interp = interp; dataPtr->command = cmdObjPtr; - Tcl_IncrRefCount(dataPtr->command); ResultInit(&dataPtr->result); - dataPtr->self = Tcl_StackChannel(interp, &transformChannelType, - (ClientData) dataPtr, mode, chan); - if (dataPtr->self == (Tcl_Channel) NULL) { + dataPtr->self = Tcl_StackChannel(interp, &transformChannelType, dataPtr, + mode, chan); + if (dataPtr->self == NULL) { Tcl_AppendResult(interp, "\nfailed to stack channel \"", Tcl_GetChannelName(chan), "\"", NULL); - Tcl_DecrRefCount(dataPtr->command); ResultClear(&dataPtr->result); ckfree((char *) dataPtr); @@ -303,27 +298,18 @@ TclChannelTransform( * At last initialize the transformation at the script level. */ - if (dataPtr->mode & TCL_WRITABLE) { - res = ExecuteCallback(dataPtr, NULL, A_CREATE_WRITE, NULL, 0, - TRANSMIT_DONT, P_NO_PRESERVE); - - if (res != TCL_OK) { - Tcl_UnstackChannel(interp, chan); - return TCL_ERROR; - } + if ((dataPtr->mode & TCL_WRITABLE) && ExecuteCallback(dataPtr, NULL, + A_CREATE_WRITE, NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE) != TCL_OK){ + Tcl_UnstackChannel(interp, chan); + return TCL_ERROR; } - if (dataPtr->mode & TCL_READABLE) { - res = ExecuteCallback(dataPtr, NULL, A_CREATE_READ, NULL, 0, - TRANSMIT_DONT, P_NO_PRESERVE); - - if (res != TCL_OK) { - ExecuteCallback(dataPtr, NULL, A_DELETE_WRITE, NULL, 0, - TRANSMIT_DONT, P_NO_PRESERVE); - - Tcl_UnstackChannel(interp, chan); - return TCL_ERROR; - } + if ((dataPtr->mode & TCL_READABLE) && ExecuteCallback(dataPtr, NULL, + A_CREATE_READ, NULL, 0, TRANSMIT_DONT, P_NO_PRESERVE) != TCL_OK) { + ExecuteCallback(dataPtr, NULL, A_DELETE_WRITE, NULL, 0, TRANSMIT_DONT, + P_NO_PRESERVE); + Tcl_UnstackChannel(interp, chan); + return TCL_ERROR; } return TCL_OK; @@ -349,18 +335,25 @@ TclChannelTransform( static int ExecuteCallback( TransformChannelData *dataPtr, - /* Transformation with the callback */ + /* Transformation with the callback. */ Tcl_Interp *interp, /* Current interpreter, possibly NULL. */ - unsigned char *op, /* Operation invoking the callback */ + unsigned char *op, /* Operation invoking the callback. */ unsigned char *buf, /* Buffer to give to the script. */ - int bufLen, /* And its length */ + int bufLen, /* And its length. */ int transmit, /* Flag, determines whether the result of the * callback is sent to the underlying channel * or not. */ - int preserve) /* Flag. If true the procedure will preserver + int preserve) /* Flag. If true the procedure will preserve * the result state of all accessed * interpreters. */ { + Tcl_Obj *resObj; /* See below, switch (transmit). */ + int resLen; + unsigned char *resBuf; + Tcl_InterpState state = NULL; + int res = TCL_OK; + Tcl_Obj *command = Tcl_DuplicateObj(dataPtr->command); + /* * Step 1, create the complete command to execute. Do this by appending * operation and buffer to operate upon to a copy of the callback @@ -369,20 +362,13 @@ ExecuteCallback( * arguments. Feather's curried commands would come in handy here. */ - Tcl_Obj *resObj; /* See below, switch (transmit) */ - int resLen; - unsigned char *resBuf; - Tcl_InterpState state = NULL; - int res = TCL_OK; - Tcl_Obj *command = Tcl_DuplicateObj(dataPtr->command); - - if (preserve) { + if (preserve == P_PRESERVE) { state = Tcl_SaveInterpState(dataPtr->interp, res); } Tcl_IncrRefCount(command); res = Tcl_ListObjAppendElement(dataPtr->interp, command, - Tcl_NewStringObj((char*) op, -1)); + Tcl_NewStringObj((char *) op, -1)); if (res != TCL_OK) { goto cleanup; } @@ -395,7 +381,7 @@ ExecuteCallback( res = Tcl_ListObjAppendElement(dataPtr->interp, command, Tcl_NewByteArrayObj(buf, bufLen)); if (res != TCL_OK) { - goto cleanup; + goto cleanup; } /* @@ -410,9 +396,9 @@ ExecuteCallback( Tcl_DecrRefCount(command); command = NULL; - if ((res != TCL_OK) && (interp != NULL) && - (dataPtr->interp != interp) && !preserve) { - Tcl_SetObjResult(interp, Tcl_GetObjResult(dataPtr->interp)); + if ((res != TCL_OK) && (interp != NULL) && (dataPtr->interp != interp) + && (preserve == P_NO_PRESERVE)) { + Tcl_SetObjResult(interp, Tcl_GetObjResult(dataPtr->interp)); return res; } @@ -428,20 +414,20 @@ ExecuteCallback( case TRANSMIT_DOWN: resObj = Tcl_GetObjResult(dataPtr->interp); - resBuf = (unsigned char *) Tcl_GetByteArrayFromObj(resObj, &resLen); + resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen); Tcl_WriteRaw(Tcl_GetStackedChannel(dataPtr->self), (char *) resBuf, resLen); break; case TRANSMIT_SELF: resObj = Tcl_GetObjResult(dataPtr->interp); - resBuf = (unsigned char *) Tcl_GetByteArrayFromObj(resObj, &resLen); + resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen); Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen); break; case TRANSMIT_IBUF: resObj = Tcl_GetObjResult(dataPtr->interp); - resBuf = (unsigned char *) Tcl_GetByteArrayFromObj(resObj, &resLen); + resBuf = Tcl_GetByteArrayFromObj(resObj, &resLen); ResultAdd(&dataPtr->result, resBuf, resLen); break; @@ -456,22 +442,18 @@ ExecuteCallback( } Tcl_ResetResult(dataPtr->interp); - - if (preserve) { + if (preserve == P_PRESERVE) { (void) Tcl_RestoreInterpState(dataPtr->interp, state); } - return res; cleanup: - if (preserve) { + if (preserve == P_PRESERVE) { (void) Tcl_RestoreInterpState(dataPtr->interp, state); } - if (command != NULL) { - Tcl_DecrRefCount(command); + Tcl_DecrRefCount(command); } - return res; } @@ -494,15 +476,15 @@ ExecuteCallback( static int TransformBlockModeProc( - ClientData instanceData, /* State of transformation */ - int mode) /* New blocking mode */ + ClientData instanceData, /* State of transformation. */ + int mode) /* New blocking mode. */ { - TransformChannelData *dataPtr = (TransformChannelData *) instanceData; + TransformChannelData *dataPtr = instanceData; if (mode == TCL_MODE_NONBLOCKING) { - dataPtr->flags |= CHANNEL_ASYNC; + dataPtr->flags |= CHANNEL_ASYNC; } else { - dataPtr->flags &= ~(CHANNEL_ASYNC); + dataPtr->flags &= ~CHANNEL_ASYNC; } return 0; } @@ -529,14 +511,12 @@ TransformCloseProc( ClientData instanceData, Tcl_Interp *interp) { - TransformChannelData *dataPtr = (TransformChannelData *) instanceData; + TransformChannelData *dataPtr = instanceData; /* * Important: In this procedure 'dataPtr->self' already points to the * underlying channel. - */ - - /* + * * There is no need to cancel an existing channel handler, this is already * done. Either by 'Tcl_UnstackChannel' or by the general cleanup in * 'Tcl_Close'. @@ -545,9 +525,9 @@ TransformCloseProc( * removed channel. */ - if (dataPtr->timer != (Tcl_TimerToken) NULL) { - Tcl_DeleteTimerHandler(dataPtr->timer); - dataPtr->timer = (Tcl_TimerToken) NULL; + if (dataPtr->timer != NULL) { + Tcl_DeleteTimerHandler(dataPtr->timer); + dataPtr->timer = NULL; } /* @@ -558,34 +538,32 @@ TransformCloseProc( */ if (dataPtr->mode & TCL_WRITABLE) { - ExecuteCallback(dataPtr, interp, A_FLUSH_WRITE, NULL, 0, - TRANSMIT_DOWN, 1); + ExecuteCallback(dataPtr, interp, A_FLUSH_WRITE, NULL, 0, + TRANSMIT_DOWN, P_PRESERVE); } if ((dataPtr->mode & TCL_READABLE) && !dataPtr->readIsFlushed) { dataPtr->readIsFlushed = 1; - ExecuteCallback(dataPtr, interp, A_FLUSH_READ, NULL, 0, - TRANSMIT_IBUF, 1); + ExecuteCallback(dataPtr, interp, A_FLUSH_READ, NULL, 0, TRANSMIT_IBUF, + P_PRESERVE); } if (dataPtr->mode & TCL_WRITABLE) { - ExecuteCallback(dataPtr, interp, A_DELETE_WRITE, NULL, 0, - TRANSMIT_DONT, 1); + ExecuteCallback(dataPtr, interp, A_DELETE_WRITE, NULL, 0, + TRANSMIT_DONT, P_PRESERVE); } - if (dataPtr->mode & TCL_READABLE) { - ExecuteCallback(dataPtr, interp, A_DELETE_READ, NULL, 0, - TRANSMIT_DONT, 1); + ExecuteCallback(dataPtr, interp, A_DELETE_READ, NULL, 0, + TRANSMIT_DONT, P_PRESERVE); } /* - * General cleanup + * General cleanup. */ ResultClear(&dataPtr->result); Tcl_DecrRefCount(dataPtr->command); ckfree((char *) dataPtr); - return TCL_OK; } @@ -612,11 +590,13 @@ TransformInputProc( int toRead, int *errorCodePtr) { - TransformChannelData* dataPtr = (TransformChannelData *) instanceData; - int gotBytes, read, res, copied; + TransformChannelData *dataPtr = instanceData; + int gotBytes, read, copied; Tcl_Channel downChan; - /* should assert (dataPtr->mode & TCL_READABLE) */ + /* + * Should assert(dataPtr->mode & TCL_READABLE); + */ if (toRead == 0) { /* @@ -629,13 +609,12 @@ TransformInputProc( downChan = Tcl_GetStackedChannel(dataPtr->self); while (toRead > 0) { - /* + /* * Loop until the request is satisfied (or no data is available from * below, possibly EOF). */ - copied = ResultCopy(&dataPtr->result, UCHARP(buf), toRead); - + copied = ResultCopy(&dataPtr->result, UCHARP(buf), toRead); toRead -= copied; buf += copied; gotBytes += copied; @@ -645,6 +624,7 @@ TransformInputProc( * The request was completely satisfied from our buffers. We can * break out of the loop and return to the caller. */ + return gotBytes; } @@ -661,20 +641,22 @@ TransformInputProc( */ ExecuteCallback(dataPtr, NULL, A_QUERY_MAXREAD, NULL, 0, - TRANSMIT_NUM /* -> maxRead */, 1); + TRANSMIT_NUM /* -> maxRead */, P_PRESERVE); if (dataPtr->maxRead >= 0) { if (dataPtr->maxRead < toRead) { - toRead = dataPtr->maxRead; + toRead = dataPtr->maxRead; } - } /* else: 'maxRead < 0' == Accept the current value of toRead */ - + } /* else: 'maxRead < 0' == Accept the current value of toRead. */ if (toRead <= 0) { return gotBytes; } - read = Tcl_ReadRaw(downChan, buf, toRead); + /* + * Get bytes from the underlying channel. + */ + read = Tcl_ReadRaw(downChan, buf, toRead); if (read < 0) { /* * Report errors to caller. EAGAIN is a special situation. If we @@ -683,14 +665,12 @@ TransformInputProc( */ if ((Tcl_GetErrno() == EAGAIN) && (gotBytes > 0)) { - return gotBytes; + return gotBytes; } *errorCodePtr = Tcl_GetErrno(); return -1; - } - - if (read == 0) { + } else if (read == 0) { /* * Check wether we hit on EOF in the underlying channel or not. If * not differentiate between blocking and non-blocking modes. In @@ -701,44 +681,44 @@ TransformInputProc( * convert and flush all waiting partial data. */ - if (! Tcl_Eof(downChan)) { - if ((gotBytes == 0) && (dataPtr->flags & CHANNEL_ASYNC)) { + if (!Tcl_Eof(downChan)) { + if ((gotBytes == 0) && (dataPtr->flags & CHANNEL_ASYNC)) { *errorCodePtr = EWOULDBLOCK; return -1; - } else { - return gotBytes; - } - } else { - if (dataPtr->readIsFlushed) { - /* - * Already flushed, nothing to do anymore. - */ - return gotBytes; } + return gotBytes; + } - dataPtr->readIsFlushed = 1; + if (dataPtr->readIsFlushed) { + /* + * Already flushed, nothing to do anymore. + */ - ExecuteCallback(dataPtr, NULL, A_FLUSH_READ, NULL, 0, - TRANSMIT_IBUF, P_PRESERVE); + return gotBytes; + } - if (ResultLength(&dataPtr->result) == 0) { - /* we had nothing to flush */ - return gotBytes; - } + dataPtr->readIsFlushed = 1; + ExecuteCallback(dataPtr, NULL, A_FLUSH_READ, NULL, 0, + TRANSMIT_IBUF, P_PRESERVE); - continue; /* at: while (toRead > 0) */ + if (ResultEmpty(&dataPtr->result)) { + /* + * We had nothing to flush. + */ + + return gotBytes; } + + continue; /* at: while (toRead > 0) */ } /* read == 0 */ /* * Transform the read chunk and add the result to our read buffer - * (dataPtr->result) + * (dataPtr->result). */ - res = ExecuteCallback(dataPtr, NULL, A_READ, UCHARP(buf), read, - TRANSMIT_IBUF, P_PRESERVE); - - if (res != TCL_OK) { + if (ExecuteCallback(dataPtr, NULL, A_READ, UCHARP(buf), read, + TRANSMIT_IBUF, P_PRESERVE) != TCL_OK) { *errorCodePtr = EINVAL; return -1; } @@ -766,27 +746,27 @@ TransformInputProc( static int TransformOutputProc( ClientData instanceData, - CONST char *buf, + const char *buf, int toWrite, int *errorCodePtr) { - TransformChannelData* dataPtr = (TransformChannelData*) instanceData; - int res; + TransformChannelData *dataPtr = instanceData; - /* should assert (dataPtr->mode & TCL_WRITABLE) */ + /* + * Should assert(dataPtr->mode & TCL_WRITABLE); + */ if (toWrite == 0) { /* * Catch a no-op. */ + return 0; } - res = ExecuteCallback(dataPtr, NULL, A_WRITE, UCHARP(buf), toWrite, - TRANSMIT_DOWN, P_NO_PRESERVE); - - if (res != TCL_OK) { - *errorCodePtr = EINVAL; + if (ExecuteCallback(dataPtr, NULL, A_WRITE, UCHARP(buf), toWrite, + TRANSMIT_DOWN, P_NO_PRESERVE) != TCL_OK) { + *errorCodePtr = EINVAL; return -1; } @@ -815,24 +795,24 @@ TransformOutputProc( static int TransformSeekProc( - ClientData instanceData, /* The channel to manipulate */ + ClientData instanceData, /* The channel to manipulate. */ long offset, /* Size of movement. */ - int mode, /* How to move */ + int mode, /* How to move. */ int *errorCodePtr) /* Location of error flag. */ { - TransformChannelData *dataPtr = (TransformChannelData *) instanceData; + TransformChannelData *dataPtr = instanceData; Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self); Tcl_ChannelType *parentType = Tcl_GetChannelType(parent); Tcl_DriverSeekProc *parentSeekProc = Tcl_ChannelSeekProc(parentType); if ((offset == 0) && (mode == SEEK_CUR)) { - /* + /* * This is no seek but a request to tell the caller the current * location. Simply pass the request down. */ - return (*parentSeekProc) (Tcl_GetChannelInstanceData(parent), - offset, mode, errorCodePtr); + return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset, + mode, errorCodePtr); } /* @@ -842,19 +822,19 @@ TransformSeekProc( */ if (dataPtr->mode & TCL_WRITABLE) { - ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, - TRANSMIT_DOWN, P_NO_PRESERVE); + ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN, + P_NO_PRESERVE); } if (dataPtr->mode & TCL_READABLE) { - ExecuteCallback(dataPtr, NULL, A_CLEAR_READ, NULL, 0, - TRANSMIT_DONT, P_NO_PRESERVE); + ExecuteCallback(dataPtr, NULL, A_CLEAR_READ, NULL, 0, TRANSMIT_DONT, + P_NO_PRESERVE); ResultClear(&dataPtr->result); dataPtr->readIsFlushed = 0; } - return (*parentSeekProc) (Tcl_GetChannelInstanceData(parent), - offset, mode, errorCodePtr); + return parentSeekProc(Tcl_GetChannelInstanceData(parent), offset, mode, + errorCodePtr); } /* @@ -879,31 +859,30 @@ TransformSeekProc( static Tcl_WideInt TransformWideSeekProc( - ClientData instanceData, /* The channel to manipulate */ + ClientData instanceData, /* The channel to manipulate. */ Tcl_WideInt offset, /* Size of movement. */ - int mode, /* How to move */ + int mode, /* How to move. */ int *errorCodePtr) /* Location of error flag. */ { - TransformChannelData * dataPtr = (TransformChannelData *) instanceData; + TransformChannelData *dataPtr = instanceData; Tcl_Channel parent = Tcl_GetStackedChannel(dataPtr->self); - Tcl_ChannelType* parentType = Tcl_GetChannelType(parent); - Tcl_DriverSeekProc* parentSeekProc = Tcl_ChannelSeekProc(parentType); - Tcl_DriverWideSeekProc* parentWideSeekProc = + Tcl_ChannelType *parentType = Tcl_GetChannelType(parent); + Tcl_DriverSeekProc *parentSeekProc = Tcl_ChannelSeekProc(parentType); + Tcl_DriverWideSeekProc *parentWideSeekProc = Tcl_ChannelWideSeekProc(parentType); ClientData parentData = Tcl_GetChannelInstanceData(parent); if ((offset == Tcl_LongAsWide(0)) && (mode == SEEK_CUR)) { - /* + /* * This is no seek but a request to tell the caller the current * location. Simply pass the request down. */ if (parentWideSeekProc != NULL) { - return (*parentWideSeekProc) (parentData, offset, mode, - errorCodePtr); + return parentWideSeekProc(parentData, offset, mode, errorCodePtr); } - return Tcl_LongAsWide((*parentSeekProc) (parentData, 0, mode, + return Tcl_LongAsWide(parentSeekProc(parentData, 0, mode, errorCodePtr)); } @@ -914,13 +893,13 @@ TransformWideSeekProc( */ if (dataPtr->mode & TCL_WRITABLE) { - ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, - TRANSMIT_DOWN, P_NO_PRESERVE); + ExecuteCallback(dataPtr, NULL, A_FLUSH_WRITE, NULL, 0, TRANSMIT_DOWN, + P_NO_PRESERVE); } if (dataPtr->mode & TCL_READABLE) { - ExecuteCallback(dataPtr, NULL, A_CLEAR_READ, NULL, 0, - TRANSMIT_DONT, P_NO_PRESERVE); + ExecuteCallback(dataPtr, NULL, A_CLEAR_READ, NULL, 0, TRANSMIT_DONT, + P_NO_PRESERVE); ResultClear(&dataPtr->result); dataPtr->readIsFlushed = 0; } @@ -930,7 +909,7 @@ TransformWideSeekProc( */ if (parentWideSeekProc != NULL) { - return (*parentWideSeekProc) (parentData, offset, mode, errorCodePtr); + return parentWideSeekProc(parentData, offset, mode, errorCodePtr); } /* @@ -946,8 +925,8 @@ TransformWideSeekProc( return Tcl_LongAsWide(-1); } - return Tcl_LongAsWide((*parentSeekProc) (parentData, - Tcl_WideAsLong(offset), mode, errorCodePtr)); + return Tcl_LongAsWide(parentSeekProc(parentData, Tcl_WideAsLong(offset), + mode, errorCodePtr)); } /* @@ -972,19 +951,20 @@ static int TransformSetOptionProc( ClientData instanceData, Tcl_Interp *interp, - CONST char *optionName, - CONST char *value) + const char *optionName, + const char *value) { - TransformChannelData* dataPtr = (TransformChannelData*) instanceData; + TransformChannelData *dataPtr = instanceData; Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self); Tcl_DriverSetOptionProc *setOptionProc; setOptionProc = Tcl_ChannelSetOptionProc(Tcl_GetChannelType(downChan)); - if (setOptionProc != NULL) { - return (*setOptionProc)(Tcl_GetChannelInstanceData(downChan), - interp, optionName, value); + if (setOptionProc == NULL) { + return TCL_ERROR; } - return TCL_ERROR; + + return setOptionProc(Tcl_GetChannelInstanceData(downChan), interp, + optionName, value); } /* @@ -1009,17 +989,17 @@ static int TransformGetOptionProc( ClientData instanceData, Tcl_Interp *interp, - CONST char *optionName, + const char *optionName, Tcl_DString *dsPtr) { - TransformChannelData* dataPtr = (TransformChannelData*) instanceData; + TransformChannelData *dataPtr = instanceData; Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self); Tcl_DriverGetOptionProc *getOptionProc; getOptionProc = Tcl_ChannelGetOptionProc(Tcl_GetChannelType(downChan)); if (getOptionProc != NULL) { - return (*getOptionProc)(Tcl_GetChannelInstanceData(downChan), - interp, optionName, dsPtr); + return getOptionProc(Tcl_GetChannelInstanceData(downChan), interp, + optionName, dsPtr); } else if (optionName == NULL) { /* * Request is query for all options, this is ok. @@ -1029,7 +1009,7 @@ TransformGetOptionProc( } /* - * Request for a specific option has to fail, we don't have any. + * Request for a specific option has to fail, since we don't have any. */ return TCL_ERROR; @@ -1055,17 +1035,17 @@ TransformGetOptionProc( /* ARGSUSED */ static void TransformWatchProc( - ClientData instanceData, /* Channel to watch */ - int mask) /* Events of interest */ + ClientData instanceData, /* Channel to watch. */ + int mask) /* Events of interest. */ { + TransformChannelData *dataPtr = instanceData; + Tcl_Channel downChan; + /* * The caller expressed interest in events occuring for this channel. We * are forwarding the call to the underlying channel now. */ - TransformChannelData *dataPtr = (TransformChannelData *) instanceData; - Tcl_Channel downChan; - dataPtr->watchMask = mask; /* @@ -1086,28 +1066,28 @@ TransformWatchProc( * Management of the internal timer. */ - if ((dataPtr->timer != (Tcl_TimerToken) NULL) && - (!(mask & TCL_READABLE) || ResultLength(&dataPtr->result)==0)) { - /* + if ((dataPtr->timer != NULL) && + (!(mask & TCL_READABLE) || ResultEmpty(&dataPtr->result))) { + /* * A pending timer exists, but either is there no (more) interest in - * the events it generates or nothing is availablee for reading, so + * the events it generates or nothing is available for reading, so * remove it. */ - Tcl_DeleteTimerHandler(dataPtr->timer); - dataPtr->timer = (Tcl_TimerToken) NULL; + Tcl_DeleteTimerHandler(dataPtr->timer); + dataPtr->timer = NULL; } - if ((dataPtr->timer == (Tcl_TimerToken) NULL) && - (mask & TCL_READABLE) && (ResultLength(&dataPtr->result) > 0)) { - /* + if ((dataPtr->timer == NULL) && (mask & TCL_READABLE) + && !ResultEmpty(&dataPtr->result)) { + /* * There is no pending timer, but there is interest in readable events * and we actually have data waiting, so generate a timer to flush * that. */ dataPtr->timer = Tcl_CreateTimerHandler(FLUSH_DELAY, - TransformChannelHandlerTimer, (ClientData) dataPtr); + TransformChannelHandlerTimer, dataPtr); } } @@ -1130,17 +1110,17 @@ TransformWatchProc( static int TransformGetFileHandleProc( - ClientData instanceData, /* Channel to query */ - int direction, /* Direction of interest */ - ClientData *handlePtr) /* Place to store the handle into */ + ClientData instanceData, /* Channel to query. */ + int direction, /* Direction of interest. */ + ClientData *handlePtr) /* Place to store the handle into. */ { + TransformChannelData *dataPtr = instanceData; + /* * Return the handle belonging to parent channel. IOW, pass the request * down and the result up. */ - TransformChannelData *dataPtr = (TransformChannelData *) instanceData; - return Tcl_GetChannelHandle(Tcl_GetStackedChannel(dataPtr->self), direction, handlePtr); } @@ -1164,17 +1144,18 @@ TransformGetFileHandleProc( static int TransformNotifyProc( - ClientData clientData, /* The state of the notified transformation */ - int mask) /* The mask of occuring events */ + ClientData clientData, /* The state of the notified + * transformation. */ + int mask) /* The mask of occuring events. */ { - TransformChannelData *dataPtr = (TransformChannelData *) clientData; + TransformChannelData *dataPtr = clientData; /* * An event occured in the underlying channel. This transformation doesn't * process such events thus returns the incoming mask unchanged. */ - if (dataPtr->timer != (Tcl_TimerToken) NULL) { + if (dataPtr->timer != NULL) { /* * Delete an existing timer. It was not fired, yet we are here, so the * channel below generated such an event and we don't have to. The @@ -1184,9 +1165,8 @@ TransformNotifyProc( */ Tcl_DeleteTimerHandler(dataPtr->timer); - dataPtr->timer = (Tcl_TimerToken) NULL; + dataPtr->timer = NULL; } - return mask; } @@ -1209,14 +1189,12 @@ TransformNotifyProc( static void TransformChannelHandlerTimer( - ClientData clientData) /* Transformation to query */ + ClientData clientData) /* Transformation to query. */ { - TransformChannelData *dataPtr = (TransformChannelData *) clientData; - - dataPtr->timer = (Tcl_TimerToken) NULL; + TransformChannelData *dataPtr = clientData; - if (!(dataPtr->watchMask & TCL_READABLE) || - (ResultLength(&dataPtr->result) == 0)) { + dataPtr->timer = NULL; + if (!(dataPtr->watchMask&TCL_READABLE) || ResultEmpty(&dataPtr->result)) { /* * The timer fired, but either is there no (more) interest in the * events it generates or nothing is available for reading, so ignore @@ -1225,7 +1203,6 @@ TransformChannelHandlerTimer( return; } - Tcl_NotifyChannel(dataPtr->self, TCL_READABLE); } @@ -1245,14 +1222,14 @@ TransformChannelHandlerTimer( *---------------------------------------------------------------------- */ -static void +static inline void ResultClear( ResultBuffer *r) /* Reference to the buffer to clear out. */ { r->used = 0; if (r->allocated) { - ckfree((char *) r->buf); + ckfree((char *) r->buf); r->buf = NULL; r->allocated = 0; } @@ -1275,9 +1252,10 @@ ResultClear( *---------------------------------------------------------------------- */ -static void +static inline void ResultInit( - ResultBuffer *r) /* Reference to the structure to initialize */ + ResultBuffer *r) /* Reference to the structure to + * initialize. */ { r->used = 0; r->allocated = 0; @@ -1287,24 +1265,24 @@ ResultInit( /* *---------------------------------------------------------------------- * - * ResultLength -- + * ResultEmpty -- * - * Returns the number of bytes stored in the buffer. + * Returns whether the number of bytes stored in the buffer is zero. * * Side effects: * None. * * Result: - * An integer, see above too. + * A boolean. * *---------------------------------------------------------------------- */ -static int -ResultLength( - ResultBuffer *r) /* The structure to query */ +static inline int +ResultEmpty( + ResultBuffer *r) /* The structure to query. */ { - return r->used; + return r->used == 0; } /* @@ -1325,51 +1303,44 @@ ResultLength( *---------------------------------------------------------------------- */ -static int +static inline int ResultCopy( ResultBuffer *r, /* The buffer to read from. */ unsigned char *buf, /* The buffer to copy into. */ - int toRead) /* Number of requested bytes. */ + size_t toRead) /* Number of requested bytes. */ { if (r->used == 0) { - /* + /* * Nothing to copy in the case of an empty buffer. */ - return 0; - } - - if (r->used == toRead) { - /* + return 0; + } else if (r->used == toRead) { + /* * We have just enough. Copy everything to the caller. */ - memcpy(buf, r->buf, (size_t) toRead); + memcpy(buf, r->buf, toRead); r->used = 0; - return toRead; - } - - if (r->used > toRead) { - /* + } else if (r->used > toRead) { + /* * The internal buffer contains more than requested. Copy the * requested subset to the caller, and shift the remaining bytes down. */ - memcpy(buf, r->buf, (size_t) toRead); - memmove(r->buf, r->buf + toRead, (size_t) r->used - toRead); - + memcpy(buf, r->buf, toRead); + memmove(r->buf, r->buf + toRead, r->used - toRead); r->used -= toRead; - return toRead; - } - - /* - * There is not enough in the buffer to satisfy the caller, so take - * everything. - */ + } else { + /* + * There is not enough in the buffer to satisfy the caller, so take + * everything. + */ - memcpy(buf, r->buf, (size_t) r->used); - toRead = r->used; - r->used = 0; + memcpy(buf, r->buf, r->used); + toRead = r->used; + r->used = 0; + } return toRead; } @@ -1389,24 +1360,23 @@ ResultCopy( *---------------------------------------------------------------------- */ -static void +static inline void ResultAdd( - ResultBuffer *r, /* The buffer to extend */ - unsigned char *buf, /* The buffer to read from */ - int toWrite) /* The number of bytes in 'buf' */ + ResultBuffer *r, /* The buffer to extend. */ + unsigned char *buf, /* The buffer to read from. */ + size_t toWrite) /* The number of bytes in 'buf'. */ { - if ((r->used + toWrite) > r->allocated) { - /* + if (r->used + toWrite > r->allocated) { + /* * Extension of the internal buffer is required. */ - if (r->allocated == 0) { + if (r->allocated == 0) { r->allocated = toWrite + INCREMENT; - r->buf = UCHARP(ckalloc((unsigned) r->allocated)); + r->buf = UCHARP(ckalloc(r->allocated)); } else { r->allocated += toWrite + INCREMENT; - r->buf = UCHARP(ckrealloc((char *) r->buf, - (unsigned) r->allocated)); + r->buf = UCHARP(ckrealloc((char *) r->buf, r->allocated)); } } @@ -1414,7 +1384,7 @@ ResultAdd( * Now we may copy the data. */ - memcpy(r->buf + r->used, buf, (size_t) toWrite); + memcpy(r->buf + r->used, buf, toWrite); r->used += toWrite; } diff --git a/generic/tclInt.h b/generic/tclInt.h index d2a438d..e09e6ef 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -13,7 +13,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclInt.h,v 1.310.2.17 2007/11/21 06:44:32 dgp Exp $ + * RCS: @(#) $Id: tclInt.h,v 1.310.2.18 2007/11/21 16:26:59 dgp Exp $ */ #ifndef _TCLINT @@ -1291,7 +1291,6 @@ typedef struct ExecStack { Tcl_Obj *stackWords[1]; } ExecStack; - /* * The data structure defining the execution environment for ByteCode's. * There is one ExecEnv structure per Tcl interpreter. It holds the evaluation @@ -1394,6 +1393,17 @@ typedef struct ByteCodeStats { #endif /* TCL_COMPILE_STATS */ /* + * Structure used in implementation of those core ensembles which are + * partially compiled. + */ + +typedef struct { + const char *name; /* The name of the subcommand. */ + Tcl_ObjCmdProc *proc; /* The implementation of the subcommand. */ + CompileProc *compileProc; /* The compiler for the subcommand. */ +} EnsembleImplMap; + +/* *---------------------------------------------------------------- * Data structures related to commands. *---------------------------------------------------------------- @@ -1880,7 +1890,7 @@ typedef struct Interp { } Interp; /* - * Macros that use the TSD-ekeko + * Macros that use the TSD-ekeko. */ #define TclAsyncReady(iPtr) \ @@ -2521,6 +2531,8 @@ MODULE_SCOPE Tcl_Obj * TclLsetList(Tcl_Interp *interp, Tcl_Obj *listPtr, MODULE_SCOPE Tcl_Obj * TclLsetFlat(Tcl_Interp *interp, Tcl_Obj *listPtr, int indexCount, Tcl_Obj *const indexArray[], Tcl_Obj *valuePtr); +MODULE_SCOPE Tcl_Command TclMakeEnsemble(Tcl_Interp *interp, const char *name, + const EnsembleImplMap map[]); MODULE_SCOPE int TclMarkList(Tcl_Interp *interp, const char *list, const char *end, int *argcPtr, const int **argszPtr, const char ***argvPtr); diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index dd31c45..37ac553 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -23,7 +23,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclNamesp.c,v 1.134.2.12 2007/11/21 06:30:53 dgp Exp $ + * RCS: @(#) $Id: tclNamesp.c,v 1.134.2.13 2007/11/21 16:27:00 dgp Exp $ */ #include "tclInt.h" @@ -5875,6 +5875,80 @@ Tcl_IsEnsemble( /* *---------------------------------------------------------------------- * + * TclMakeEnsemble -- + * + * Create an ensemble from a table of implementation commands. The + * ensemble will be subject to (limited) compilation if any of the + * implementation commands are compilable. + * + * Results: + * Handle for the ensemble, or NULL if creation of it fails. + * + * Side effects: + * May advance bytecode compilation epoch. + * + *---------------------------------------------------------------------- + */ + +Tcl_Command +TclMakeEnsemble( + Tcl_Interp *interp, + const char *name, + const EnsembleImplMap map[]) +{ + Tcl_Command ensemble; /* The overall ensemble. */ + Tcl_Namespace *tclNsPtr; /* Reference to the "::tcl" namespace. */ + Tcl_DString buf; + + tclNsPtr = Tcl_FindNamespace(interp, "::tcl", NULL, + TCL_CREATE_NS_IF_UNKNOWN); + if (tclNsPtr == NULL) { + Tcl_Panic("unable to find or create ::tcl namespace!"); + } + Tcl_DStringInit(&buf); + Tcl_DStringAppend(&buf, "::tcl::", -1); + Tcl_DStringAppend(&buf, name, -1); + tclNsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buf), NULL, + TCL_CREATE_NS_IF_UNKNOWN); + if (tclNsPtr == NULL) { + Tcl_Panic("unable to find or create %s namespace!", + Tcl_DStringValue(&buf)); + } + ensemble = Tcl_CreateEnsemble(interp, Tcl_DStringValue(&buf)+5, tclNsPtr, + TCL_ENSEMBLE_PREFIX); + Tcl_DStringAppend(&buf, "::", -1); + if (ensemble != NULL) { + Tcl_Obj *mapDict; + int i, compile = 0; + + TclNewObj(mapDict); + for (i=0 ; map[i].name != NULL ; i++) { + Tcl_Obj *fromObj, *toObj; + Command *cmdPtr; + + fromObj = Tcl_NewStringObj(map[i].name, -1); + TclNewStringObj(toObj, Tcl_DStringValue(&buf), + Tcl_DStringLength(&buf)); + Tcl_AppendToObj(toObj, map[i].name, -1); + Tcl_DictObjPut(NULL, mapDict, fromObj, toObj); + cmdPtr = (Command *) Tcl_CreateObjCommand(interp, + TclGetString(toObj), map[i].proc, NULL, NULL); + cmdPtr->compileProc = map[i].compileProc; + compile |= (map[i].compileProc != NULL); + } + Tcl_SetEnsembleMappingDict(interp, ensemble, mapDict); + if (compile) { + Tcl_SetEnsembleFlags(interp, ensemble, + TCL_ENSEMBLE_PREFIX | ENSEMBLE_COMPILE); + } + } + + return ensemble; +} + +/* + *---------------------------------------------------------------------- + * * NsEnsembleImplementationCmd -- * * Implements an ensemble of commands (being those exported by a diff --git a/generic/tclPkg.c b/generic/tclPkg.c index 147b117..809f23f 100644 --- a/generic/tclPkg.c +++ b/generic/tclPkg.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclPkg.c,v 1.27.2.4 2007/11/21 06:30:54 dgp Exp $ + * RCS: @(#) $Id: tclPkg.c,v 1.27.2.5 2007/11/21 16:27:00 dgp Exp $ * * TIP #268. * Heavily rewritten to handle the extend version numbers, and extended @@ -690,15 +690,20 @@ Tcl_PkgPresentEx( if (hPtr) { pkgPtr = Tcl_GetHashValue(hPtr); if (pkgPtr->version != NULL) { - /* * At this point we know that the package is present. Make sure * that the provided version meets the current requirement by * calling Tcl_PkgRequireEx() to check for us. */ - return Tcl_PkgRequireEx(interp, name, version, exact, - clientDataPtr); + const char *foundVersion = Tcl_PkgRequireEx(interp, name, version, + exact, clientDataPtr); + + if (foundVersion == NULL) { + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name, + NULL); + } + return foundVersion; } } @@ -708,6 +713,7 @@ Tcl_PkgPresentEx( } else { Tcl_AppendResult(interp, "package ", name, " is not present", NULL); } + Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name, NULL); return NULL; } |