diff options
Diffstat (limited to 'generic/tclEnsemble.c')
| -rw-r--r-- | generic/tclEnsemble.c | 332 | 
1 files changed, 159 insertions, 173 deletions
| diff --git a/generic/tclEnsemble.c b/generic/tclEnsemble.c index 5c30a0b..7a295ba 100644 --- a/generic/tclEnsemble.c +++ b/generic/tclEnsemble.c @@ -21,12 +21,12 @@ static inline Tcl_Obj *	NewNsObj(Tcl_Namespace *namespacePtr);  static inline int	EnsembleUnknownCallback(Tcl_Interp *interp,  			    EnsembleConfig *ensemblePtr, int objc,  			    Tcl_Obj *const objv[], Tcl_Obj **prefixObjPtr); -static int		NsEnsembleImplementationCmdNR(ClientData clientData, +static int		NsEnsembleImplementationCmdNR(void *clientData,  			    Tcl_Interp *interp,int objc,Tcl_Obj *const objv[]);  static void		BuildEnsembleConfig(EnsembleConfig *ensemblePtr);  static int		NsEnsembleStringOrder(const void *strPtr1,  			    const void *strPtr2); -static void		DeleteEnsembleConfig(ClientData clientData); +static void		DeleteEnsembleConfig(void *clientData);  static void		MakeCachedEnsembleCommand(Tcl_Obj *objPtr,  			    EnsembleConfig *ensemblePtr, Tcl_HashEntry *hPtr,  			    Tcl_Obj *fix); @@ -70,8 +70,8 @@ enum EnsConfigOpts {  };  /* - * This structure defines a Tcl object type that contains a reference to an - * ensemble subcommand (e.g. the "length" in [string length ab]). It is used + * ensembleCmdType is a Tcl object type that contains a reference to an + * ensemble subcommand, e.g. the "length" in [string length ab]. It is used   * to cache the mapping between the subcommand itself and the real command   * that implements it.   */ @@ -151,7 +151,7 @@ NewNsObj(  int  TclNamespaceEnsembleCmd( -    TCL_UNUSED(ClientData), +    TCL_UNUSED(void *),      Tcl_Interp *interp,      int objc,      Tcl_Obj *const objv[]) @@ -163,7 +163,8 @@ TclNamespaceEnsembleCmd(      Tcl_DictSearch search;      Tcl_Obj *listObj;      const char *simpleName; -    int index, done; +    int index; +    int done;      if (nsPtr == NULL || nsPtr->flags & NS_DEAD) {  	if (!Tcl_InterpDeleted(interp)) { @@ -187,7 +188,8 @@ TclNamespaceEnsembleCmd(      switch ((enum EnsSubcmds) index) {      case ENS_CREATE: {  	const char *name; -	int len, allocatedMapFlag = 0; +	int len; +	int allocatedMapFlag = 0;  	/*  	 * Defaults  	 */ @@ -498,7 +500,8 @@ TclNamespaceEnsembleCmd(  	    Tcl_SetObjResult(interp, resultObj);  	} else { -	    int len, allocatedMapFlag = 0; +	    int len; +	    int allocatedMapFlag = 0;  	    Tcl_Obj *subcmdObj = NULL, *mapObj = NULL, *paramObj = NULL,  		    *unknownObj = NULL; /* Defaults, silence gcc 4 warnings */  	    int permitPrefix, flags = 0;	/* silence gcc 4 warning */ @@ -940,7 +943,8 @@ Tcl_SetEnsembleMappingDict(  	return TCL_ERROR;      }      if (mapDict != NULL) { -	int size, done; +	int size; +	int done;  	Tcl_DictSearch search;  	Tcl_Obj *valuePtr; @@ -1523,7 +1527,8 @@ TclMakeEnsemble(      Tcl_DString buf, hiddenBuf;      const char **nameParts = NULL;      const char *cmdName = NULL; -    int i, nameCount = 0, ensembleFlags = 0, hiddenLen; +    int i, nameCount = 0; +    int ensembleFlags = 0, hiddenLen;      /*       * Construct the path for the ensemble namespace and create it. @@ -1674,7 +1679,7 @@ TclMakeEnsemble(  int  TclEnsembleImplementationCmd( -    ClientData clientData, +    void *clientData,      Tcl_Interp *interp,      int objc,      Tcl_Obj *const objv[]) @@ -1685,7 +1690,7 @@ TclEnsembleImplementationCmd(  static int  NsEnsembleImplementationCmdNR( -    ClientData clientData, +    void *clientData,      Tcl_Interp *interp,      int objc,      Tcl_Obj *const objv[]) @@ -1704,7 +1709,7 @@ NsEnsembleImplementationCmdNR(      int subIdx;      /* -     * Must recheck objc, since numParameters might have changed. Cf. test +     * Must recheck objc since numParameters might have changed. See test       * namespace-53.9.       */ @@ -1712,7 +1717,7 @@ NsEnsembleImplementationCmdNR(      subIdx = 1 + ensemblePtr->numParameters;      if (objc < subIdx + 1) {  	/* -	 * We don't have a subcommand argument. Make error message. +	 * No subcommand argument. Make error message.  	 */  	Tcl_DString buf;	/* Message being built */ @@ -1744,18 +1749,16 @@ NsEnsembleImplementationCmdNR(      }      /* -     * Determine if the table of subcommands is right. If so, we can just look -     * up in there and go straight to dispatch. +     * If the table of subcommands is valid just lookup up the command there +     * and go to dispatch.       */      subObj = objv[subIdx];      if (ensemblePtr->epoch == ensemblePtr->nsPtr->exportLookupEpoch) {  	/* -	 * Table of subcommands is still valid; therefore there might be a -	 * valid cache of discovered information which we can reuse. Do the -	 * check here, and if we're still valid, we can jump straight to the -	 * part where we do the invocation of the subcommand. +	 * Table of subcommands is still valid so if the internal representtion +	 * is an ensembleCmd, just call it.  	 */  	EnsembleCmdRep *ensembleCmd; @@ -1777,8 +1780,8 @@ NsEnsembleImplementationCmdNR(      }      /* -     * Look in the hashtable for the subcommand name; this is the fastest way -     * of all if there is no cache in operation. +     * Look in the hashtable for the named subcommand.  This is the fastest +     * path if there is no cache in operation.       */      hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable, @@ -1786,26 +1789,25 @@ NsEnsembleImplementationCmdNR(      if (hPtr != NULL) {  	/* -	 * Cache for later in the subcommand object. +	 * Cache ensemble in the subcommand object for later.  	 */  	MakeCachedEnsembleCommand(subObj, ensemblePtr, hPtr, NULL);      } else if (!(ensemblePtr->flags & TCL_ENSEMBLE_PREFIX)) {  	/* -	 * Could not map, no prefixing, go to unknown/error handling. +	 * Could not map.  No prefixing.  Go to unknown/error handling.  	 */  	goto unknownOrAmbiguousSubcommand;      } else {  	/* -	 * If we've not already confirmed the command with the hash as part of -	 * building our export table, we need to scan the sorted array for -	 * matches. +	 * If the command isn't yet confirmed with the hash as part of building +	 * the export table, scan the sorted array for matches.  	 */ -	const char *subcmdName; /* Name of the subcommand, or unique prefix of -				 * it (will be an error for a non-unique -				 * prefix). */ +	const char *subcmdName; /* Name of the subcommand or unique prefix of +				 * it (a non-unique prefix produces an error). +				 */  	char *fullName = NULL;	/* Full name of the subcommand. */  	int stringLength, i;  	int tableLength = ensemblePtr->subcommandTable.numEntries; @@ -1820,10 +1822,10 @@ NsEnsembleImplementationCmdNR(  	    if (cmp == 0) {  		if (fullName != NULL) {  		    /* -		     * Since there's never the exact-match case to worry about -		     * (hash search filters this), getting here indicates that -		     * our subcommand is an ambiguous prefix of (at least) two -		     * exported subcommands, which is an error case. +		     * Hash search filters out the exact-match case, so getting +		     * here indicates that the subcommand is an ambiguous +		     * prefix of at least two exported subcommands, which is an +		     * error case.  		     */  		    goto unknownOrAmbiguousSubcommand; @@ -1831,9 +1833,8 @@ NsEnsembleImplementationCmdNR(  		fullName = ensemblePtr->subcommandArrayPtr[i];  	    } else if (cmp < 0) {  		/* -		 * Because we are searching a sorted table, we can now stop -		 * searching because we have gone past anything that could -		 * possibly match. +		 * The table is sorted so stop searching because a match would +		 * have been found already.  		 */  		break; @@ -1841,7 +1842,7 @@ NsEnsembleImplementationCmdNR(  	}  	if (fullName == NULL) {  	    /* -	     * The subcommand is not a prefix of anything, so bail out! +	     * The subcommand is not a prefix of anything. Bail out!  	     */  	    goto unknownOrAmbiguousSubcommand; @@ -1871,21 +1872,19 @@ NsEnsembleImplementationCmdNR(    runResultingSubcommand:      /* -     * Do the real work of execution of the subcommand by building an array of -     * objects (note that this is potentially not the same length as the -     * number of arguments to this ensemble command), populating it and then -     * feeding it back through the main command-lookup engine. In theory, we -     * could look up the command in the namespace ourselves, as we already -     * have the namespace in which it is guaranteed to exist, +     * Execute the subcommand by populating an array of objects, which might +     * not be the same length as the number of arguments to this ensemble +     * command, and then handing it to the main command-lookup engine. In +     * theory, the command could be looked up right here using the namespace in +     * which it is guaranteed to exist,       *       *   ((Q: That's not true if the -map option is used, is it?))       * -     * but we don't do that (the cacheing of the command object used should -     * help with that.) +     * but don't do that because cacheing of the command object should help.       */      { -	Tcl_Obj *copyPtr;	/* The actual list of words to dispatch to. +	Tcl_Obj *copyPtr;	/* The list of words to dispatch on.  				 * Will be freed by the dispatch engine. */  	Tcl_Obj **copyObjv;  	int copyObjc, prefixObjc; @@ -1908,8 +1907,8 @@ NsEnsembleImplementationCmdNR(  	TclDecrRefCount(prefixObj);  	/* -	 * Record what arguments the script sent in so that things like -	 * Tcl_WrongNumArgs can give the correct error message. Parameters +	 * Record the words of the command as given so that routines like +	 * Tcl_WrongNumArgs can produce the correct error message. Parameters  	 * count both as inserted and removed arguments.  	 */ @@ -1931,10 +1930,9 @@ NsEnsembleImplementationCmdNR(    unknownOrAmbiguousSubcommand:      /* -     * Have not been able to match the subcommand asked for with a real -     * subcommand that we export. See whether a handler has been registered -     * for dealing with this situation. Will only call (at most) once for any -     * particular ensemble invocation. +     * The named subcommand did not match any exported command. If there is a +     * handler registered unknown subcommands, call it, but not more than once +     * for this call.       */      if (ensemblePtr->unknownHandler != NULL && reparseCount++ < 1) { @@ -1950,10 +1948,10 @@ NsEnsembleImplementationCmdNR(      }      /* -     * We cannot determine what subcommand to hand off to, so generate a -     * (standard) failure message. Note the one odd case compared with -     * standard ensemble-like command, which is where a namespace has no -     * exported commands at all... +     * Could not find a routine for the named subcommand so generate a standard +     * failure message.  The one odd case compared with a standard +     * ensemble-like command is where a namespace has no exported commands at +     * all...       */      Tcl_ResetResult(interp); @@ -1987,7 +1985,7 @@ NsEnsembleImplementationCmdNR(  int  TclClearRootEnsemble( -    TCL_UNUSED(ClientData *), +    TCL_UNUSED(void **),      Tcl_Interp *interp,      int result)  { @@ -2000,8 +1998,8 @@ TclClearRootEnsemble(   *   * TclInitRewriteEnsemble --   * - *	Applies a rewrite of arguments so that an ensemble subcommand will - *	report error messages correctly for the overall command. + *	Applies a rewrite of arguments so that an ensemble subcommand + *	correctly reports any error messages for the overall command.   *   * Results:   *	Whether this is the first rewrite applied, a value which must be @@ -2079,7 +2077,7 @@ TclResetRewriteEnsemble(   *   * TclSpellFix --   * - *	Record a spelling correction that needs making in the generation of + *	Records a spelling correction that needs making in the generation of   *	the WrongNumArgs usage message.   *   * Results: @@ -2093,7 +2091,7 @@ TclResetRewriteEnsemble(  static int  FreeER( -    ClientData data[], +    void *data[],      TCL_UNUSED(Tcl_Interp *),      int result)  { @@ -2144,8 +2142,8 @@ TclSpellFix(      if (badIdx < iPtr->ensembleRewrite.numInsertedObjs) {  	/* -	 * Misspelled value was inserted. We cannot directly jump to the bad -	 * value, but have to search. +	 * Misspelled value was inserted. Cannot directly jump to the bad +	 * value.  Must search.  	 */  	idx = 1; @@ -2257,22 +2255,22 @@ TclFetchEnsembleRoot(  /*   * ----------------------------------------------------------------------   * - * EnsmebleUnknownCallback -- + * EnsembleUnknownCallback --   * - *	Helper for the ensemble engine that handles the procesing of unknown - *	callbacks. See the user documentation of the ensemble unknown handler - *	for details; this function is only ever called when such a function is - *	defined, and is only ever called once per ensemble dispatch (i.e. if a - *	reparse still fails, this isn't called again). + *	Helper for the ensemble engine.  Calls the routine registered for + *	"ensemble unknown" case.  See the user documentation of the + *	ensemble unknown handler for details.  Only called when such a + *	function is defined, and is only called once per ensemble dispatch. + *	I.e. even if a reparse still fails, this isn't called again.   *   * Results:   *	TCL_OK -	*prefixObjPtr contains the command words to dispatch   *			to. - *	TCL_CONTINUE -	Need to reparse (*prefixObjPtr is invalid). - *	TCL_ERROR -	Something went wrong! Error message in interpreter. + *	TCL_CONTINUE -	Need to reparse, i.e. *prefixObjPtr is invalid + *	TCL_ERROR -	Something went wrong. Error message in interpreter.   *   * Side effects: - *	Calls the Tcl interpreter, so arbitrary. + *	Arbitrary, due to evaluation of script provided by client.   *   * ----------------------------------------------------------------------   */ @@ -2285,28 +2283,28 @@ EnsembleUnknownCallback(      Tcl_Obj *const objv[],      Tcl_Obj **prefixObjPtr)  { -    int paramc, i, result, prefixObjc; +    int paramc, i, prefixObjc; +    int result;      Tcl_Obj **paramv, *unknownCmd, *ensObj;      /* -     * Create the unknown command callback to determine what to do. +     * Create the "unknown" command callback to determine what to do.       */      unknownCmd = Tcl_DuplicateObj(ensemblePtr->unknownHandler);      TclNewObj(ensObj);      Tcl_GetCommandFullName(interp, ensemblePtr->token, ensObj);      Tcl_ListObjAppendElement(NULL, unknownCmd, ensObj); -    for (i=1 ; i<objc ; i++) { +    for (i = 1 ; i < objc ; i++) {  	Tcl_ListObjAppendElement(NULL, unknownCmd, objv[i]);      }      TclListObjGetElementsM(NULL, unknownCmd, ¶mc, ¶mv);      Tcl_IncrRefCount(unknownCmd);      /* -     * Now call the unknown handler. (We don't bother NRE-enabling this; deep -     * recursing through unknown handlers is horribly perverse.) Note that it -     * is always an error for an unknown handler to delete its ensemble; don't -     * do that! +     * Call the "unknown" handler.  No attempt to NRE-enable this as deep +     * recursion through unknown handlers is perverse. It is always an error +     * for an unknown handler to delete its ensemble. Don't do that.       */      Tcl_Preserve(ensemblePtr); @@ -2324,10 +2322,9 @@ EnsembleUnknownCallback(      Tcl_Release(ensemblePtr);      /* -     * If we succeeded, we should either have a list of words that form the -     * command to be executed, or an empty list. In the empty-list case, the -     * ensemble is believed to be updated so we should ask the ensemble engine -     * to reparse the original command. +     * On success the result is a list of words that form the command to be +     * executed.  If the list is empty, the ensemble should have been updated, +     * so ask the ensemble engine to reparse the original command.       */      if (result == TCL_OK) { @@ -2336,11 +2333,7 @@ EnsembleUnknownCallback(  	TclDecrRefCount(unknownCmd);  	Tcl_ResetResult(interp); -	/* -	 * Namespace is still there. Check if the result is a valid list. If -	 * it is, and it is non-empty, that list is what we are using as our -	 * replacement. -	 */ +	/* A non-empty list is the replacement command. */  	if (TclListObjLengthM(interp, *prefixObjPtr, &prefixObjc) != TCL_OK) {  	    TclDecrRefCount(*prefixObjPtr); @@ -2353,7 +2346,7 @@ EnsembleUnknownCallback(  	}  	/* -	 * Namespace alive & empty result => reparse. +	 * Empty result => reparse.  	 */  	TclDecrRefCount(*prefixObjPtr); @@ -2361,7 +2354,7 @@ EnsembleUnknownCallback(      }      /* -     * Oh no! An exceptional result. Convert to an error. +     * Convert exceptional result to an error.       */      if (!Tcl_InterpDeleted(interp)) { @@ -2401,16 +2394,16 @@ EnsembleUnknownCallback(   *   * MakeCachedEnsembleCommand --   * - *	Cache what we've computed so far; it's not nice to repeatedly copy - *	strings about. Note that to do this, we start by deleting any old - *	representation that there was (though if it was an out of date - *	ensemble rep, we can skip some of the deallocation process.) + *	Caches what has been computed so far to minimize string copying. + *	Starts by deleting any existing representation but reusing the existing + *	structure if it is an ensembleCmd.   *   * Results: - *	None + *	None.   *   * Side effects: - *	Alters the internal representation of the first object parameter. + *	Converts the internal representation of the given object to an + *	ensembleCmd.   *   *----------------------------------------------------------------------   */ @@ -2432,8 +2425,7 @@ MakeCachedEnsembleCommand(  	}      } else {  	/* -	 * Kill the old internal rep, and replace it with a brand new one of -	 * our own. +	 * Replace any old internal representation with a new one.  	 */  	ensembleCmd = (EnsembleCmdRep *)ckalloc(sizeof(EnsembleCmdRep)); @@ -2459,17 +2451,16 @@ MakeCachedEnsembleCommand(   *   * DeleteEnsembleConfig --   * - *	Destroys the data structure used to represent an ensemble. This is - *	called when the ensemble's command is deleted (which happens - *	automatically if the ensemble's namespace is deleted.) Maintainers - *	should note that ensembles should be deleted by deleting their - *	commands. + *	Destroys the data structure used to represent an ensemble.  Called when + *	the procedure for the ensemble is deleted, which happens automatically + *	if the namespace for the ensemble is deleted.  Deleting the procedure + *	for an ensemble is the right way to initiate cleanup.   *   * Results:   *	None.   *   * Side effects: - *	Memory is (eventually) deallocated. + *	Memory is eventually deallocated.   *   *----------------------------------------------------------------------   */ @@ -2496,15 +2487,12 @@ ClearTable(  static void  DeleteEnsembleConfig( -    ClientData clientData) +    void *clientData)  {      EnsembleConfig *ensemblePtr = (EnsembleConfig *)clientData;      Namespace *nsPtr = ensemblePtr->nsPtr; -    /* -     * Unlink from the ensemble chain if it has not been marked as having been -     * done already. -     */ +    /* Unlink from the ensemble chain if it not already marked as unlinked. */      if (ensemblePtr->next != ensemblePtr) {  	EnsembleConfig *ensPtr = (EnsembleConfig *) nsPtr->ensembles; @@ -2530,7 +2518,7 @@ DeleteEnsembleConfig(      ensemblePtr->flags |= ENSEMBLE_DEAD;      /* -     * Kill the pointer-containing fields. +     * Release the fields that contain pointers.       */      ClearTable(ensemblePtr); @@ -2548,10 +2536,9 @@ DeleteEnsembleConfig(      }      /* -     * Arrange for the structure to be reclaimed. Note that this is complex -     * because we have to make sure that we can react sensibly when an -     * ensemble is deleted during the process of initialising the ensemble -     * (especially the unknown callback.) +     * Arrange for the structure to be reclaimed. This is complex because it is +     * necessary to react sensibly when an ensemble is deleted during its +     * initialisation, particularly in the case of an unknown callback.       */      Tcl_EventuallyFree(ensemblePtr, TCL_DYNAMIC); @@ -2562,11 +2549,11 @@ DeleteEnsembleConfig(   *   * BuildEnsembleConfig --   * - *	Create the internal data structures that describe how an ensemble - *	looks, being a hash mapping from the full command name to the Tcl list - *	that describes the implementation prefix words, and a sorted array of - *	all the full command names to allow for reasonably efficient - *	unambiguous prefix handling. + *	Creates the internal data structures that describe how an ensemble + *	looks.  The structures are a hash map from the full command name to the + *	Tcl list that describes the implementation prefix words, and a sorted + *	array of all the full command names to allow for reasonably efficient + *	handling of an unambiguous prefix.   *   * Results:   *	None. @@ -2574,7 +2561,7 @@ DeleteEnsembleConfig(   * Side effects:   *	Reallocates and rebuilds the hash table and array stored at the   *	ensemblePtr argument. For large ensembles or large namespaces, this is - *	a potentially expensive operation. + *	may be an expensive operation.   *   *----------------------------------------------------------------------   */ @@ -2583,10 +2570,10 @@ static void  BuildEnsembleConfig(      EnsembleConfig *ensemblePtr)  { -    Tcl_HashSearch search;	/* Used for scanning the set of commands in -				 * the namespace that backs up this -				 * ensemble. */ -    int i, j, isNew; +    Tcl_HashSearch search;	/* Used for scanning the commands in +				 * the namespace for this ensemble. */ +    int i, j; +    int isNew;      Tcl_HashTable *hash = &ensemblePtr->subcommandTable;      Tcl_HashEntry *hPtr;      Tcl_Obj *mapDict = ensemblePtr->subcommandDict; @@ -2602,13 +2589,13 @@ BuildEnsembleConfig(          /*           * There is a list of exactly what subcommands go in the table. -         * Must determine the target for each. +         * Determine the target for each.           */          TclListObjGetElementsM(NULL, subList, &subc, &subv);          if (subList == mapDict) {              /* -             * Strange case where explicit list of subcommands is same value +             * Unusual case where explicit list of subcommands is same value               * as the dict mapping to targets.               */ @@ -2657,10 +2644,10 @@ BuildEnsembleConfig(                  }                  /* -                 * target was not in the dictionary so map onto the namespace. -                 * Note in this case that we do not guarantee that the command -                 * is actually there; that is the programmer's responsibility -                 * (or [::unknown] of course). +                 * Target was not in the dictionary.  Map onto the namespace. +                 * In this case there is no guarantee that the command +                 * is actually there.  It is the responsibility of the +                 * programmer (or [::unknown] of course) to provide the procedure.                   */                  cmdObj = Tcl_NewStringObj(name, -1); @@ -2671,9 +2658,9 @@ BuildEnsembleConfig(          }      } else if (mapDict) {          /* -         * No subcmd list, but we do have a mapping dictionary so we should -         * use the keys of that. Convert the dictionary's contents into the -         * form required for the ensemble's internal hashtable. +         * No subcmd list, but there is a mapping dictionary, so +         * use the keys of that. Convert the contents of the dictionary into the +         * form required for the internal hashtable of the ensemble.           */          Tcl_DictSearch dictSearch; @@ -2692,18 +2679,15 @@ BuildEnsembleConfig(          }      } else {  	/* -	 * Discover what commands are actually exported by the namespace. -	 * What we have is an array of patterns and a hash table whose keys -	 * are the command names exported by the namespace (the contents do -	 * not matter here.) We must find out what commands are actually -	 * exported by filtering each command in the namespace against each of -	 * the patterns in the export list. Note that we use an intermediate -	 * hash table to make memory management easier, and because that makes -	 * exact matching far easier too. +	 * Use the array of patterns and the hash table whose keys are the +	 * commands exported by the namespace.  The corresponding values do not +	 * matter here.  Filter the commands in the namespace against the +	 * patterns in the export list to find out what commands are actually +	 * exported. Use an intermediate hash table to make memory management +	 * easier and to make exact matching much easier.  	 * -	 * Suggestion for future enhancement: compute the unique prefixes and -	 * place them in the hash too, which should make for even faster -	 * matching. +	 * Suggestion for future enhancement: Compute the unique prefixes and +	 * place them in the hash too for even faster matching.  	 */  	hPtr = Tcl_FirstHashEntry(&ensemblePtr->nsPtr->cmdTable, &search); @@ -2748,22 +2732,22 @@ BuildEnsembleConfig(      /*       * Create a sorted array of all subcommands in the ensemble; hash tables       * are all very well for a quick look for an exact match, but they can't -     * determine things like whether a string is a prefix of another (not -     * without lots of preparation anyway) and they're no good for when we're -     * generating the error message either. +     * determine things like whether a string is a prefix of another, at least +     * not without a lot of preparation, and they're not useful for generating +     * the error message either.       * -     * We do this by filling an array with the names (we use the hash keys -     * directly to save a copy, since any time we change the array we change -     * the hash too, and vice versa) and running quicksort over the array. +     * Do this by filling an array with the names:  Use the hash keys +     * directly to save a copy since any time we change the array we change +     * the hash too, and vice versa, and run quicksort over the array.       */      ensemblePtr->subcommandArrayPtr =  	    (char **)ckalloc(sizeof(char *) * hash->numEntries);      /* -     * Fill array from both ends as this makes us less likely to end up with -     * performance problems in qsort(), which is good. Note that doing this -     * makes this code much more opaque, but the naive alternatve: +     * Fill the array from both ends as this reduces the likelihood of +     * performance problems in qsort(). This makes this code much more opaque, +     * but the naive alternatve:       *       * for (hPtr=Tcl_FirstHashEntry(hash,&search),i=0 ;       *	       hPtr!=NULL ; hPtr=Tcl_NextHashEntry(&search),i++) { @@ -2771,11 +2755,11 @@ BuildEnsembleConfig(       * }       *       * can produce long runs of precisely ordered table entries when the -     * commands in the namespace are declared in a sorted fashion (an ordering -     * some people like) and the hashing functions (or the command names -     * themselves) are fairly unfortunate. By filling from both ends, it -     * requires active malice (and probably a debugger) to get qsort() to have -     * awful runtime behaviour. +     * commands in the namespace are declared in a sorted fashion,  which is an +     * ordering some people like, and the hashing functions or the command +     * names themselves are fairly unfortunate. Filling from both ends means +     * that it requires active malice, and probably a debugger, to get qsort() +     * to have awful runtime behaviour.       */      i = 0; @@ -2801,8 +2785,7 @@ BuildEnsembleConfig(   *   * NsEnsembleStringOrder --   * - *	Helper function to compare two pointers to two strings for use with - *	qsort(). + *	Helper to for uset with sort() that compares two string pointers.   *   * Results:   *	-1 if the first string is smaller, 1 if the second string is smaller, @@ -2930,14 +2913,15 @@ TclCompileEnsemble(      Tcl_Obj *replaced, *replacement;      Tcl_Command ensemble = (Tcl_Command) cmdPtr;      Command *oldCmdPtr = cmdPtr, *newCmdPtr; -    int len, result, flags = 0, i, depth = 1, invokeAnyway = 0; +    int result, flags = 0, depth = 1, invokeAnyway = 0;      int ourResult = TCL_ERROR; -    unsigned numBytes; +    int i, len; +    TCL_HASH_TYPE numBytes;      const char *word;      TclNewObj(replaced);      Tcl_IncrRefCount(replaced); -    if (parsePtr->numWords < depth + 1) { +    if (parsePtr->numWords <= depth) {  	goto failed;      }      if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { @@ -3197,7 +3181,7 @@ TclCompileEnsemble(       * Throw out any line information generated by the failed compile attempt.       */ -    while (mapPtr->nuloc - 1 > eclIndex) { +    while (mapPtr->nuloc > eclIndex + 1) {          mapPtr->nuloc--;          ckfree(mapPtr->loc[mapPtr->nuloc].line);          mapPtr->loc[mapPtr->nuloc].line = NULL; @@ -3264,10 +3248,11 @@ TclAttemptCompileProc(      CompileEnv *envPtr)		/* Holds resulting instructions. */  {      DefineLineInformation; -    int result, i; +    int result; +    int i;      Tcl_Token *saveTokenPtr = parsePtr->tokenPtr;      int savedStackDepth = envPtr->currStackDepth; -    unsigned savedCodeNext = envPtr->codeNext - envPtr->codeStart; +    TCL_HASH_TYPE savedCodeNext = envPtr->codeNext - envPtr->codeStart;      int savedAuxDataArrayNext = envPtr->auxDataArrayNext;      int savedExceptArrayNext = envPtr->exceptArrayNext;  #ifdef TCL_COMPILE_DEBUG @@ -3400,7 +3385,8 @@ CompileToInvokedCommand(      Tcl_Token *tokPtr;      Tcl_Obj *objPtr, **words;      const char *bytes; -    int i, numWords, cmdLit, extraLiteralFlags = LITERAL_CMD_NAME; +    int cmdLit, extraLiteralFlags = LITERAL_CMD_NAME; +    int i, numWords, length;      /*       * Push the words of the command. Take care; the command words may be @@ -3411,9 +3397,9 @@ CompileToInvokedCommand(      TclListObjGetElementsM(NULL, replacements, &numWords, &words);      for (i = 0, tokPtr = parsePtr->tokenPtr; i < parsePtr->numWords;  	    i++, tokPtr = TokenAfter(tokPtr)) { -	if (i > 0 && i < numWords+1) { -	    bytes = TclGetString(words[i-1]); -	    PushLiteral(envPtr, bytes, words[i-1]->length); +	if (i > 0 && i <= numWords) { +	    bytes = TclGetStringFromObj(words[i-1], &length); +	    PushLiteral(envPtr, bytes, length);  	    continue;  	} @@ -3441,11 +3427,11 @@ CompileToInvokedCommand(      TclNewObj(objPtr);      Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr, objPtr); -    bytes = TclGetString(objPtr); +    bytes = TclGetStringFromObj(objPtr, &length);      if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) {  	extraLiteralFlags |= LITERAL_UNSHARED;      } -    cmdLit = TclRegisterLiteral(envPtr, bytes, objPtr->length, extraLiteralFlags); +    cmdLit = TclRegisterLiteral(envPtr, bytes, length, extraLiteralFlags);      TclSetCmdNameObj(interp, TclFetchLiteral(envPtr, cmdLit), cmdPtr);      TclEmitPush(cmdLit, envPtr);      TclDecrRefCount(objPtr); | 
