diff options
Diffstat (limited to 'generic/tclNamesp.c')
-rw-r--r-- | generic/tclNamesp.c | 115 |
1 files changed, 56 insertions, 59 deletions
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index 4b72e03..18cd07c 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -6582,6 +6582,8 @@ BuildEnsembleConfig( int i, j, isNew; Tcl_HashTable *hash = &ensemblePtr->subcommandTable; Tcl_HashEntry *hPtr; + Tcl_Obj *mapDict = ensemblePtr->subcommandDict; + Tcl_Obj *exportList = ensemblePtr->subcmdList; if (hash->numEntries != 0) { /* @@ -6601,51 +6603,67 @@ BuildEnsembleConfig( Tcl_InitHashTable(hash, TCL_STRING_KEYS); } - /* - * See if we've got an export list. If so, we will only export exactly - * those commands, which may be either implemented by the prefix in the - * subcommandDict or mapped directly onto the namespace's commands. - */ - - if (ensemblePtr->subcmdList != NULL) { - Tcl_Obj **subcmdv, *target, *cmdObj, *cmdPrefixObj; - int subcmdc; + if (mapDict) { + /* + * We have a mapping dictionary to direct filling of the subcommand + * table. Every key, value in the dict should go into the table + * unless we have an export list that holds some of the keys back. + */ - TclListObjGetElements(NULL, ensemblePtr->subcmdList, &subcmdc, - &subcmdv); - for (i=0 ; i<subcmdc ; i++) { - char *name = TclGetString(subcmdv[i]); + Tcl_DictSearch dictSearch; + Tcl_Obj *keyObj, *valueObj; + int done; - hPtr = Tcl_CreateHashEntry(hash, name, &isNew); + Tcl_DictObjFirst(NULL, mapDict, &dictSearch, &keyObj, &valueObj, &done); + while (!done) { + int nameLen, insert = 1; + char *name = TclGetStringFromObj(keyObj, &nameLen); + + if (exportList && (exportList != mapDict)) { + Tcl_Obj **subv; + int subc; + + insert = 0; + TclListObjGetElements(NULL, exportList, &subc, &subv); + for (i = 0; i < subc; i++) { + int compareLen; + const char *compare + = TclGetStringFromObj(subv[i], &compareLen); + + if ((nameLen == compareLen) + && (memcmp(name, compare, (size_t)nameLen) == 0)) { + insert = 1; + break; + } + } + } + if (insert) { + hPtr = Tcl_CreateHashEntry(hash, name, &isNew); + Tcl_SetHashValue(hPtr, valueObj); + Tcl_IncrRefCount(valueObj); + } + Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done); + } + } + if (exportList) { + /* + * We have an export list. Put into the table each element that's + * not already there. + */ + int subc; + Tcl_Obj **subv, *cmdObj, *cmdPrefixObj; - /* - * Skip non-unique cases. - */ + TclListObjGetElements(NULL, exportList, &subc, &subv); + for (i=0 ; i<subc ; i++) { + char *name = TclGetString(subv[i]); + hPtr = Tcl_CreateHashEntry(hash, name, &isNew); if (!isNew) { + /* Subcommand already in the table, from the mapDict. */ continue; } - /* - * Look in our dictionary (if present) for the command. - */ - - if (ensemblePtr->subcommandDict != NULL) { - Tcl_DictObjGet(NULL, ensemblePtr->subcommandDict, subcmdv[i], - &target); - if (target != NULL) { - Tcl_SetHashValue(hPtr, target); - Tcl_IncrRefCount(target); - continue; - } - } - - /* - * Not there, 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). - */ - + /* Need to put entry in table, but it's not in mapDict */ cmdObj = Tcl_NewStringObj(ensemblePtr->nsPtr->fullName, -1); if (ensemblePtr->nsPtr->parentPtr != NULL) { Tcl_AppendStringsToObj(cmdObj, "::", name, NULL); @@ -6656,28 +6674,7 @@ BuildEnsembleConfig( Tcl_SetHashValue(hPtr, cmdPrefixObj); Tcl_IncrRefCount(cmdPrefixObj); } - } else if (ensemblePtr->subcommandDict != NULL) { - /* - * 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. - */ - - Tcl_DictSearch dictSearch; - Tcl_Obj *keyObj, *valueObj; - int done; - - Tcl_DictObjFirst(NULL, ensemblePtr->subcommandDict, &dictSearch, - &keyObj, &valueObj, &done); - while (!done) { - char *name = TclGetString(keyObj); - - hPtr = Tcl_CreateHashEntry(hash, name, &isNew); - Tcl_SetHashValue(hPtr, valueObj); - Tcl_IncrRefCount(valueObj); - Tcl_DictObjNext(&dictSearch, &keyObj, &valueObj, &done); - } - } else { + } else if (mapDict == NULL) { /* * Discover what commands are actually exported by the namespace. * What we have is an array of patterns and a hash table whose keys |