Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Put the baseline cloning (oo::object-><cloned>) of objects in C. |
|---|---|
| Timelines: | family | ancestors | descendants | both | trunk | main |
| Files: | files | file ages | folders |
| SHA3-256: |
162e1d77e5b500a44484ae2cdc62bf4b |
| User & Date: | dkf 2025-08-30 15:13:31.432 |
Context
|
2025-08-30
| ||
| 21:20 | merge core-9-0-branch check-in: 1e75862cd4 user: dkf tags: trunk, main | |
| 15:13 | Put the baseline cloning (oo::object-><cloned>) of objects in C. check-in: 162e1d77e5 user: dkf tags: trunk, main | |
| 14:36 | Sorry Ashok, but I object to changing a right-shift (as it originally was) to a left-shift. Will exp... check-in: 442c3e7366 user: jan.nijtmans tags: trunk, main | |
| 14:16 | Put the baseline cloning of objects in C. I'd been putting off doing this for over a decade, as it w... Closed-Leaf check-in: 41e23633da user: dkf tags: object-clone-in-c | |
Changes
Changes to generic/tclInt.h.
| ︙ | ︙ | |||
740 741 742 743 744 745 746 747 748 749 750 751 752 753 | * in precompiled scripts keep working. */ /* Type of value (0 is scalar) */ #define VAR_ARRAY 0x1 #define VAR_LINK 0x2 #define VAR_CONSTANT 0x10000 /* Type of storage (0 is compiled local) */ #define VAR_IN_HASHTABLE 0x4 #define VAR_DEAD_HASH 0x8 #define VAR_ARRAY_ELEMENT 0x1000 #define VAR_NAMESPACE_VAR 0x80 /* KEEP OLD VALUE for Itcl */ | > > | 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 | * in precompiled scripts keep working. */ /* Type of value (0 is scalar) */ #define VAR_ARRAY 0x1 #define VAR_LINK 0x2 #define VAR_CONSTANT 0x10000 #define VAR_TYPE \ (VAR_ARRAY | VAR_LINK | VAR_CONSTANT) /* Type of storage (0 is compiled local) */ #define VAR_IN_HASHTABLE 0x4 #define VAR_DEAD_HASH 0x8 #define VAR_ARRAY_ELEMENT 0x1000 #define VAR_NAMESPACE_VAR 0x80 /* KEEP OLD VALUE for Itcl */ |
| ︙ | ︙ | |||
3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 | MODULE_SCOPE void TclContinuationsEnterDerived(Tcl_Obj *objPtr, Tcl_Size start, Tcl_Size *clNext); MODULE_SCOPE ContLineLoc *TclContinuationsGet(Tcl_Obj *objPtr); MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr, Tcl_Obj *originObjPtr); MODULE_SCOPE Tcl_Size TclConvertElement(const char *src, Tcl_Size length, char *dst, int flags); MODULE_SCOPE Tcl_Command TclCreateObjCommandInNs(Tcl_Interp *interp, const char *cmdName, Tcl_Namespace *nsPtr, Tcl_ObjCmdProc *proc, void *clientData, Tcl_CmdDeleteProc *deleteProc); MODULE_SCOPE Tcl_Command TclCreateEnsembleInNs(Tcl_Interp *interp, const char *name, Tcl_Namespace *nameNamespacePtr, Tcl_Namespace *ensembleNamespacePtr, int flags); | > > > > | 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 | MODULE_SCOPE void TclContinuationsEnterDerived(Tcl_Obj *objPtr, Tcl_Size start, Tcl_Size *clNext); MODULE_SCOPE ContLineLoc *TclContinuationsGet(Tcl_Obj *objPtr); MODULE_SCOPE void TclContinuationsCopy(Tcl_Obj *objPtr, Tcl_Obj *originObjPtr); MODULE_SCOPE Tcl_Size TclConvertElement(const char *src, Tcl_Size length, char *dst, int flags); MODULE_SCOPE int TclCopyNamespaceProcedures(Tcl_Interp *interp, Namespace *srcNsPtr, Namespace *tgtNsPtr); MODULE_SCOPE int TclCopyNamespaceVariables(Tcl_Interp *interp, Namespace *originNs, Namespace *targetNs); MODULE_SCOPE Tcl_Command TclCreateObjCommandInNs(Tcl_Interp *interp, const char *cmdName, Tcl_Namespace *nsPtr, Tcl_ObjCmdProc *proc, void *clientData, Tcl_CmdDeleteProc *deleteProc); MODULE_SCOPE Tcl_Command TclCreateEnsembleInNs(Tcl_Interp *interp, const char *name, Tcl_Namespace *nameNamespacePtr, Tcl_Namespace *ensembleNamespacePtr, int flags); |
| ︙ | ︙ |
Changes to generic/tclOO.c.
| ︙ | ︙ | |||
130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
*/
#define DCM(name,visibility,proc) \
{name,visibility,\
{TCL_OO_METHOD_VERSION_CURRENT,"core method: "#name,proc,NULL,NULL}}
static const DeclaredClassMethod objMethods[] = {
DCM("destroy", 1, TclOO_Object_Destroy),
DCM("eval", 0, TclOO_Object_Eval),
DCM("unknown", 0, TclOO_Object_Unknown),
DCM("variable", 0, TclOO_Object_LinkVar),
DCM("varname", 0, TclOO_Object_VarName),
{NULL, 0, {0, NULL, NULL, NULL, NULL}}
}, clsMethods[] = {
| > | 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
*/
#define DCM(name,visibility,proc) \
{name,visibility,\
{TCL_OO_METHOD_VERSION_CURRENT,"core method: "#name,proc,NULL,NULL}}
static const DeclaredClassMethod objMethods[] = {
DCM("<cloned>", 0, TclOO_Object_Cloned),
DCM("destroy", 1, TclOO_Object_Destroy),
DCM("eval", 0, TclOO_Object_Eval),
DCM("unknown", 0, TclOO_Object_Unknown),
DCM("variable", 0, TclOO_Object_LinkVar),
DCM("varname", 0, TclOO_Object_VarName),
{NULL, 0, {0, NULL, NULL, NULL, NULL}}
}, clsMethods[] = {
|
| ︙ | ︙ | |||
190 191 192 193 194 195 196 |
"package ifneeded tcl::oo " TCLOO_PATCHLEVEL " {# Already present, OK?};"
"namespace eval ::oo {"
" variable version " TCLOO_VERSION " patchlevel " TCLOO_PATCHLEVEL
"};";
/* "tcl_findLibrary tcloo $oo::version $oo::version" */
/* " tcloo.tcl OO_LIBRARY oo::library;"; */
| < < < < < < | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
"package ifneeded tcl::oo " TCLOO_PATCHLEVEL " {# Already present, OK?};"
"namespace eval ::oo {"
" variable version " TCLOO_VERSION " patchlevel " TCLOO_PATCHLEVEL
"};";
/* "tcl_findLibrary tcloo $oo::version $oo::version" */
/* " tcloo.tcl OO_LIBRARY oo::library;"; */
/*
* The actual definition of the variable holding the TclOO stub table.
*/
MODULE_SCOPE const TclOOStubs tclOOStubs;
/*
|
| ︙ | ︙ | |||
500 501 502 503 504 505 506 |
*/
if (TclOODefineSlots(fPtr) != TCL_OK) {
return TCL_ERROR;
}
MakeAdditionalClasses(fPtr, define, objdef);
| | < < < < < | 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 |
*/
if (TclOODefineSlots(fPtr) != TCL_OK) {
return TCL_ERROR;
}
MakeAdditionalClasses(fPtr, define, objdef);
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* InitClassSystemRoots --
*
|
| ︙ | ︙ |
Changes to generic/tclOOBasic.c.
| ︙ | ︙ | |||
598 599 600 601 602 603 604 605 606 607 608 609 610 611 |
TclOOClassSetMixins(interp, oPtr->classPtr, 1, &mixin);
return TclNRObjectContextInvokeNext(interp, context, objc, objv, skip);
}
/*
* ----------------------------------------------------------------------
*
* TclOO_Object_Destroy --
*
* Implementation for oo::object->destroy method.
*
* ----------------------------------------------------------------------
*/
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 |
TclOOClassSetMixins(interp, oPtr->classPtr, 1, &mixin);
return TclNRObjectContextInvokeNext(interp, context, objc, objv, skip);
}
/*
* ----------------------------------------------------------------------
*
* TclOO_Object_Cloned --
*
* Handler for cloning objects that clones basic bits (only!) of the
* object's namespace. Non-procedures, traces, sub-namespaces, etc. need
* more complex (and class-specific) handling.
*
* ----------------------------------------------------------------------
*/
int
TclOO_Object_Cloned(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Interpreter for error reporting. */
Tcl_ObjectContext context, /* The object/call context. */
int objc, /* Number of arguments. */
Tcl_Obj *const *objv) /* The actual arguments. */
{
int skip = Tcl_ObjectContextSkippedArgs(context);
if (objc != skip + 1) {
Tcl_WrongNumArgs(interp, skip, objv, "originObject");
return TCL_ERROR;
}
Object *targetObject = (Object *) Tcl_ObjectContextObject(context);
Object *originObject = (Object *) Tcl_GetObjectFromObj(interp, objv[skip]);
if (!originObject) {
return TCL_ERROR;
}
Namespace *originNs = (Namespace *) originObject->namespacePtr;
Namespace *targetNs = (Namespace *) targetObject->namespacePtr;
if (TclCopyNamespaceProcedures(interp, originNs, targetNs) != TCL_OK) {
return TCL_ERROR;
}
return TclCopyNamespaceVariables(interp, originNs, targetNs);
}
/*
* ----------------------------------------------------------------------
*
* TclOO_Object_Destroy --
*
* Implementation for oo::object->destroy method.
*
* ----------------------------------------------------------------------
*/
|
| ︙ | ︙ | |||
1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 |
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s:: oo ::delegate",
clsPtr->thisPtr->namespacePtr->fullName));
return TCL_OK;
}
int
TclOO_Singleton_New(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Interpreter in which to create the object;
* also used for error reporting. */
Tcl_ObjectContext context, /* The object/call context. */
int objc, /* Number of arguments. */
| > > > > > > > > > > | 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 |
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s:: oo ::delegate",
clsPtr->thisPtr->namespacePtr->fullName));
return TCL_OK;
}
/*
* ----------------------------------------------------------------------
*
* TclOO_Singleton_New, MarkAsSingleton --
*
* Implementation for oo::singleton->new method.
*
* ----------------------------------------------------------------------
*/
int
TclOO_Singleton_New(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Interpreter in which to create the object;
* also used for error reporting. */
Tcl_ObjectContext context, /* The object/call context. */
int objc, /* Number of arguments. */
|
| ︙ | ︙ | |||
1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 |
mixins[0] = singInst;
TclOOObjectSetMixins(oPtr, mixinc + 1, mixins);
TclStackFree(interp, mixins);
}
return result;
}
int
TclOO_SingletonInstance_Destroy(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Interpreter for error reporting. */
TCL_UNUSED(Tcl_ObjectContext),
TCL_UNUSED(int),
TCL_UNUSED(Tcl_Obj *const *))
| > > > > > > > > > > > | 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 |
mixins[0] = singInst;
TclOOObjectSetMixins(oPtr, mixinc + 1, mixins);
TclStackFree(interp, mixins);
}
return result;
}
/*
* ----------------------------------------------------------------------
*
* TclOO_SingletonInstance_Destroy, TclOO_SingletonInstance_Cloned --
*
* Implementation for oo::SingletonInstance->destroy method and its
* cloning callback method.
*
* ----------------------------------------------------------------------
*/
int
TclOO_SingletonInstance_Destroy(
TCL_UNUSED(void *),
Tcl_Interp *interp, /* Interpreter for error reporting. */
TCL_UNUSED(Tcl_ObjectContext),
TCL_UNUSED(int),
TCL_UNUSED(Tcl_Obj *const *))
|
| ︙ | ︙ |
Changes to generic/tclOOInt.h.
| ︙ | ︙ | |||
534 535 536 537 538 539 540 541 542 543 544 545 546 547 | */ MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Cloned; MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Constructor; MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Create; MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_CreateNs; MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_New; MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Destroy; MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Eval; MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_LinkVar; MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Unknown; MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_VarName; MODULE_SCOPE Tcl_MethodCallProc TclOO_Configurable_Configure; MODULE_SCOPE Tcl_MethodCallProc TclOO_Configurable_Constructor; | > | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 | */ MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Cloned; MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Constructor; MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_Create; MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_CreateNs; MODULE_SCOPE Tcl_MethodCallProc TclOO_Class_New; MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Cloned; MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Destroy; MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Eval; MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_LinkVar; MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_Unknown; MODULE_SCOPE Tcl_MethodCallProc TclOO_Object_VarName; MODULE_SCOPE Tcl_MethodCallProc TclOO_Configurable_Configure; MODULE_SCOPE Tcl_MethodCallProc TclOO_Configurable_Constructor; |
| ︙ | ︙ |
Deleted generic/tclOOScript.h.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to generic/tclProc.c.
| ︙ | ︙ | |||
2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 |
}
hePtr = Tcl_FindHashEntry(procPtr->iPtr->linePBodyPtr, procPtr);
if (hePtr == NULL) {
return NULL;
}
return (CmdFrame *) Tcl_GetHashValue(hePtr);
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 |
}
hePtr = Tcl_FindHashEntry(procPtr->iPtr->linePBodyPtr, procPtr);
if (hePtr == NULL) {
return NULL;
}
return (CmdFrame *) Tcl_GetHashValue(hePtr);
}
/*
*----------------------------------------------------------------------
*
* TclCopyNamespaceProcedures --
*
* Copy procedures from one namespace into another.
*
* Results:
* A standard Tcl result code.
*
* Side effects:
* Modifies the target namespace's commands.
*
*----------------------------------------------------------------------
*/
// Duplicate an argument to a procedure.
static inline int
DuplicateArgument(
Proc *newProc,
const CompiledLocal *origLocal,
Tcl_Size i)
{
const char *argname = origLocal->name;
Tcl_Size nameLength = origLocal->nameLength;
// Allocate an entry in the runtime procedure frame's list of local
// variables for the argument.
CompiledLocal *localPtr = (CompiledLocal *)Tcl_AttemptAlloc(
offsetof(CompiledLocal, name) + 1U + nameLength);
if (!localPtr) {
return TCL_ERROR;
}
if (newProc->firstLocalPtr == NULL) {
newProc->firstLocalPtr = newProc->lastLocalPtr = localPtr;
} else {
newProc->lastLocalPtr->nextPtr = localPtr;
newProc->lastLocalPtr = localPtr;
}
localPtr->nextPtr = NULL;
localPtr->nameLength = nameLength;
localPtr->frameIndex = i;
localPtr->flags = VAR_ARGUMENT;
localPtr->resolveInfo = NULL;
localPtr->defValuePtr = origLocal->defValuePtr;
if (localPtr->defValuePtr) {
Tcl_IncrRefCount(localPtr->defValuePtr);
}
memcpy(localPtr->name, argname, nameLength + 1);
if (origLocal->flags & VAR_IS_ARGS) {
localPtr->flags |= VAR_IS_ARGS;
}
return TCL_OK;
}
// Duplicate a procedure into a different namespace.
static int
DuplicateProc(
Tcl_Interp *interp,
Namespace *nsPtr,
const char *cmdName,
const Proc *origProc,
const Command *origCmd)
{
Interp *iPtr = (Interp *) interp;
// Duplicate the string of body, not the bytecode.
Tcl_Size length;
const char *bytes = TclGetStringFromObj(origProc->bodyPtr, &length);
Tcl_Obj *bodyPtr = Tcl_NewStringObj(bytes, length);
TclContinuationsCopy(bodyPtr, origProc->bodyPtr);
Tcl_IncrRefCount(bodyPtr);
// The new procedure record.
Proc *newProc = (Proc *) Tcl_Alloc(sizeof(Proc));
newProc->iPtr = iPtr;
newProc->refCount = 1;
newProc->bodyPtr = bodyPtr;
newProc->numArgs = origProc->numArgs;
newProc->numCompiledLocals = origProc->numArgs;
newProc->firstLocalPtr = NULL;
newProc->lastLocalPtr = NULL;
// Work through the original arguments, duplicating them.
const CompiledLocal *origLocal = origProc->firstLocalPtr;
for (Tcl_Size i = 0; i < newProc->numArgs; i++) {
if (DuplicateArgument(newProc, origLocal, i) != TCL_OK) {
// Don't set the interp result here. Since a malloc just failed,
// first clean up some memory before doing that */
goto procError;
}
origLocal = origLocal->nextPtr;
}
// Create the new command backed by the procedure.
newProc->cmdPtr = (Command *) TclNRCreateCommandInNs(interp, cmdName,
(Tcl_Namespace *) nsPtr, TclObjInterpProc, NRInterpProc, newProc,
TclProcDeleteProc);
// TIP #280: Duplicate the origin information (if we have it).
Tcl_HashEntry *origHePtr = Tcl_FindHashEntry(iPtr->linePBodyPtr, origProc);
if (origHePtr) {
CmdFrame *newCfPtr = (CmdFrame *) Tcl_Alloc(sizeof(CmdFrame));
const CmdFrame *origCfPtr = (CmdFrame *) Tcl_GetHashValue(origHePtr);
// Copy info, then fix up bits that need different treatment.
memcpy(newCfPtr, origCfPtr, sizeof(CmdFrame));
newCfPtr->line = (int *)Tcl_Alloc(sizeof(int));
newCfPtr->line[0] = origCfPtr->line[0];
Tcl_IncrRefCount(newCfPtr->data.eval.path);
Tcl_HashEntry *hePtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr,
newProc, NULL);
Tcl_SetHashValue(hePtr, newCfPtr);
}
// Optimize for no-op procs. Note that this is simpler than in [proc]; we
// just see whether we've got the compiler in the old command!
if (origCmd->compileProc == TclCompileNoOp) {
newProc->cmdPtr->compileProc = TclCompileNoOp;
}
return TCL_OK;
procError:
// Delete the data allocated so far
Tcl_DecrRefCount(bodyPtr);
while (newProc->firstLocalPtr != NULL) {
CompiledLocal *localPtr = newProc->firstLocalPtr;
newProc->firstLocalPtr = localPtr->nextPtr;
if (localPtr->defValuePtr != NULL) {
Tcl_DecrRefCount(localPtr->defValuePtr);
}
Tcl_Free(localPtr);
}
Tcl_Free(newProc);
// Complain about the failure to allocate.
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"procedure \"%s\": arg list contains too many (%"
TCL_SIZE_MODIFIER "d) entries", cmdName, origProc->numArgs));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
TOOMANYARGS, (char *)NULL);
return TCL_ERROR;
}
// Duplicate all the procedures in a namespace into another (new) namespace.
int
TclCopyNamespaceProcedures(
Tcl_Interp *interp,
Namespace *srcNsPtr, // Where to copy from.
Namespace *tgtNsPtr) // Where to copy to.
{
Tcl_HashSearch search;
if (srcNsPtr == tgtNsPtr) {
Tcl_Panic("cannot copy procedures from one namespace to itself");
}
for (Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(&srcNsPtr->cmdTable, &search);
entryPtr; entryPtr = Tcl_NextHashEntry(&search)) {
const char *cmdName = (const char *)
Tcl_GetHashKey(&srcNsPtr->cmdTable, entryPtr);
Command *cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
// For non-procedures, check if this is an import of a procedure; those
// also get copied.
if (!TclIsProc(cmdPtr)) {
Command *realCmdPtr = (Command *)
TclGetOriginalCommand((Tcl_Command) cmdPtr);
if (!realCmdPtr || !TclIsProc(realCmdPtr)) {
continue;
}
cmdPtr = realCmdPtr;
}
// Make the copy
Proc *procPtr = (Proc *) cmdPtr->objClientData;
if (DuplicateProc(interp, tgtNsPtr, cmdName, procPtr, cmdPtr) != TCL_OK) {
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
|
| ︙ | ︙ |
Changes to generic/tclVar.c.
| ︙ | ︙ | |||
7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 |
}
tablePtr->defaultObj = defaultObj;
if (tablePtr->defaultObj) {
Tcl_IncrRefCount(tablePtr->defaultObj);
Tcl_IncrRefCount(tablePtr->defaultObj);
}
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 |
}
tablePtr->defaultObj = defaultObj;
if (tablePtr->defaultObj) {
Tcl_IncrRefCount(tablePtr->defaultObj);
Tcl_IncrRefCount(tablePtr->defaultObj);
}
}
/*----------------------------------------------------------------------
*
* TclCopyNamespaceVariables --
*
* This copies the variables of one namespace (the source) to another
* (the target). It skips variables in the source that have the same name
* in the target.
*
* Results:
* Returns a standard Tcl result.
*
* Side effects:
* May run traces on the source variables.
*
*----------------------------------------------------------------------
*/
// Copy an array from one namespace to another.
// This is basically [array set $tgt [array get $src]] but optimised.
static int
CopyNSArray(
Tcl_Interp *interp,
Var *srcAryPtr,
Var *tgtAryPtr,
Tcl_Obj *arrayName)
{
// List the elements of the array prior to traces.
Tcl_Obj *nameList = Tcl_NewObj();
Tcl_HashSearch search;
for (Var *varPtr2 = VarHashFirstVar(srcAryPtr->value.tablePtr, &search);
varPtr2; varPtr2 = VarHashNextVar(&search)) {
if (TclIsVarUndefined(varPtr2)) {
continue;
}
Tcl_ListObjAppendElement(NULL, nameList, VarHashGetKey(varPtr2));
}
// Make sure the Var structure of the array is not removed by a trace
// while we're working.
VarHashRefCount(srcAryPtr)++;
Tcl_Size count;
Tcl_Obj **names;
TclListObjGetElements(NULL, nameList, &count, &names);
// Init the target array if necessary
if (!TclIsVarArray(tgtAryPtr)) {
TclInitArrayVar(tgtAryPtr);
}
// Make sure it won't go away
VarHashRefCount(tgtAryPtr)++;
// Copy elements!
for (Tcl_Size i=0 ; i<count ; i++) {
Tcl_Obj *elemName = names[i];
// Read the element in the source; may invoke read traces.
Var *srcElem = TclLookupArrayElement(interp, arrayName, elemName,
TCL_LEAVE_ERR_MSG, "read", 0, 0, srcAryPtr, TCL_INDEX_NONE);
if (!srcElem) {
if (TclIsVarArray(srcAryPtr)) {
continue;
}
goto errorCopyingElement;
}
Tcl_Obj *valueObj = TclPtrGetVarIdx(interp, srcElem, srcAryPtr,
arrayName, elemName, TCL_LEAVE_ERR_MSG, TCL_INDEX_NONE);
if (!valueObj) {
if (TclIsVarArray(srcAryPtr)) {
continue;
}
goto errorCopyingElement;
}
// Write the element in the target; may invoke write traces
Var *tgtElem = TclLookupArrayElement(interp, arrayName, elemName,
TCL_LEAVE_ERR_MSG, "write", 0, 1, tgtAryPtr, TCL_INDEX_NONE);
if (!tgtElem) {
goto errorCopyingElement;
}
if (TclPtrSetVarIdx(interp, tgtElem, tgtAryPtr, arrayName, elemName,
valueObj, TCL_LEAVE_ERR_MSG, TCL_INDEX_NONE) == NULL) {
goto errorCopyingElement;
}
}
// Clean up
VarHashRefCount(srcAryPtr)--;
VarHashRefCount(tgtAryPtr)--;
Tcl_BounceRefCount(nameList);
return TCL_OK;
errorCopyingElement:
VarHashRefCount(srcAryPtr)--;
VarHashRefCount(tgtAryPtr)--;
Tcl_BounceRefCount(nameList);
return TCL_ERROR;
}
// Copy variables from one namespace to another.
int
TclCopyNamespaceVariables(
Tcl_Interp *interp,
Namespace *originNs,
Namespace *targetNs)
{
Var *srcVarPtr;
Tcl_HashSearch search;
if (targetNs == originNs) {
Tcl_Panic("cannot copy namespace variables to itself");
}
restartScan:
for (srcVarPtr=VarHashFirstVar(&originNs->varTable, &search);
srcVarPtr!=NULL ; srcVarPtr=VarHashNextVar(&search)) {
Tcl_Obj *nameObj = VarHashGetKey(srcVarPtr), *valueObj;
int isNew, restart = 0;
Var *tgtVarPtr = VarHashCreateVar(&targetNs->varTable, nameObj, &isNew);
if (!tgtVarPtr || !isNew) {
// If we couldn't make it or it existed, we skip.
// This means that a variable that triggered a rescan because of
// a trace won't do the second time round.
continue;
}
// Mark this like [variable] does
TclSetVarNamespaceVar(tgtVarPtr);
if (TclIsVarUndefined(srcVarPtr)) {
continue;
}
switch (srcVarPtr->flags & VAR_TYPE) {
case VAR_ARRAY:
if (srcVarPtr->flags & VAR_ALL_TRACES) {
restart = 1;
}
if (CopyNSArray(interp, srcVarPtr, tgtVarPtr, nameObj) != TCL_OK) {
return TCL_ERROR;
}
break;
case VAR_LINK:
// Links don't have traces
while (TclIsVarLink(srcVarPtr)) {
srcVarPtr = srcVarPtr->value.linkPtr;
}
TclSetVarLink(tgtVarPtr);
tgtVarPtr->value.linkPtr = srcVarPtr;
if (TclIsVarInHash(srcVarPtr)) {
VarHashRefCount(srcVarPtr)++;
}
break;
default:
if (srcVarPtr->flags & VAR_ALL_TRACES) {
restart = 1;
}
valueObj = TclPtrGetVarIdx(interp, srcVarPtr, NULL, nameObj, NULL,
TCL_LEAVE_ERR_MSG, TCL_INDEX_NONE);
if (!valueObj) {
return TCL_ERROR;
}
tgtVarPtr->value.objPtr = valueObj;
Tcl_IncrRefCount(valueObj);
if (srcVarPtr->flags & VAR_CONSTANT) {
tgtVarPtr->flags |= VAR_CONSTANT;
}
break;
}
if (restart) {
// A trace existed on a variable we touched, so we must rescan
goto restartScan;
}
}
return TCL_OK;
}
/*
* Local Variables:
* mode: c
* c-basic-offset: 4
* fill-column: 78
* End:
|
| ︙ | ︙ |
Deleted tools/makeHeader.tcl.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted tools/tclOOScript.tcl.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to unix/Makefile.in.
| ︙ | ︙ | |||
1471 1472 1473 1474 1475 1476 1477 | tclNamesp.o: $(GENERIC_DIR)/tclNamesp.c $(COMPILEHDR) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclNamesp.c tclNotify.o: $(GENERIC_DIR)/tclNotify.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclNotify.c | | | 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 | tclNamesp.o: $(GENERIC_DIR)/tclNamesp.c $(COMPILEHDR) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclNamesp.c tclNotify.o: $(GENERIC_DIR)/tclNotify.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclNotify.c tclOO.o: $(GENERIC_DIR)/tclOO.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOO.c tclOOBasic.o: $(GENERIC_DIR)/tclOOBasic.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOOBasic.c tclOOCall.o: $(GENERIC_DIR)/tclOOCall.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclOOCall.c |
| ︙ | ︙ | |||
2187 2188 2189 2190 2191 2192 2193 | @echo "This warning can be safely ignored, do not report as a bug!" $(GENERIC_DIR)/tclOOStubInit.c: $(GENERIC_DIR)/tclOO.decls @echo "Warning: tclOOStubInit.c may be out of date." @echo "Developers may want to run \"make genstubs\" to regenerate." @echo "This warning can be safely ignored, do not report as a bug!" | < < < < < < < < < | 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 | @echo "This warning can be safely ignored, do not report as a bug!" $(GENERIC_DIR)/tclOOStubInit.c: $(GENERIC_DIR)/tclOO.decls @echo "Warning: tclOOStubInit.c may be out of date." @echo "Developers may want to run \"make genstubs\" to regenerate." @echo "This warning can be safely ignored, do not report as a bug!" genstubs: $(NATIVE_TCLSH) $(TOOL_DIR)/genStubs.tcl $(GENERIC_DIR) \ $(GENERIC_DIR)/tcl.decls $(GENERIC_DIR)/tclInt.decls \ $(GENERIC_DIR)/tclTomMath.decls $(NATIVE_TCLSH) $(TOOL_DIR)/genStubs.tcl $(GENERIC_DIR) \ $(GENERIC_DIR)/tclOO.decls # # Target to check that all exported functions have an entry in the stubs # tables. # checkstubs: $(TCL_LIB_FILE) -@for i in `nm -p $(TCL_LIB_FILE) \ |
| ︙ | ︙ |
Changes to win/Makefile.in.
| ︙ | ︙ | |||
758 759 760 761 762 763 764 |
%.${OBJEXT}: %.c
$(CC) -c $(CC_SWITCHES) -DBUILD_tcl @DEPARG@ $(CC_OBJNAME)
.rc.$(RES):
$(RC) @RC_OUT@ $@ @RC_TYPE@ @RC_DEFINES@ @RC_INCLUDE@ "$(GENERIC_DIR_NATIVE)" @RC_INCLUDE@ "$(WIN_DIR_NATIVE)" @DEPARG@
| < < | 758 759 760 761 762 763 764 765 766 767 768 769 770 771 |
%.${OBJEXT}: %.c
$(CC) -c $(CC_SWITCHES) -DBUILD_tcl @DEPARG@ $(CC_OBJNAME)
.rc.$(RES):
$(RC) @RC_OUT@ $@ @RC_TYPE@ @RC_DEFINES@ @RC_INCLUDE@ "$(GENERIC_DIR_NATIVE)" @RC_INCLUDE@ "$(WIN_DIR_NATIVE)" @DEPARG@
#--------------------------------------------------------------------------
# Minizip implementation
#--------------------------------------------------------------------------
adler32.$(HOST_OBJEXT):
$(HOST_CC) -o $@ -I$(ZLIB_DIR) -c $(ZLIB_DIR)/adler32.c
compress.$(HOST_OBJEXT):
|
| ︙ | ︙ | |||
1138 1139 1140 1141 1142 1143 1144 | $(GENERIC_DIR)/tclStubInit.c: $(GENERIC_DIR)/tcl.decls \ $(GENERIC_DIR)/tclInt.decls @echo "Warning: tclStubInit.c may be out of date." @echo "Developers may want to run \"make genstubs\" to regenerate." @echo "This warning can be safely ignored, do not report as a bug!" | < < < < < < < < < < | 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 | $(GENERIC_DIR)/tclStubInit.c: $(GENERIC_DIR)/tcl.decls \ $(GENERIC_DIR)/tclInt.decls @echo "Warning: tclStubInit.c may be out of date." @echo "Developers may want to run \"make genstubs\" to regenerate." @echo "This warning can be safely ignored, do not report as a bug!" genstubs: $(TCL_EXE) "$(TOOL_DIR_NATIVE)/genStubs.tcl" \ "$(GENERIC_DIR_NATIVE)" \ "$(GENERIC_DIR_NATIVE)/tcl.decls" \ "$(GENERIC_DIR_NATIVE)/tclInt.decls" \ "$(GENERIC_DIR_NATIVE)/tclTomMath.decls" $(TCL_EXE) "$(TOOL_DIR_NATIVE)/genStubs.tcl" \ "$(GENERIC_DIR_NATIVE)" \ "$(GENERIC_DIR_NATIVE)/tclOO.decls" # # This target creates the HTML folder for Tcl & Tk and places it in # DISTDIR/html. It uses the tcltk-man2html.tcl tool from the Tcl group's tool # workspace. It depends on the Tcl & Tk being in directories called tcl9.* & # tk8.* up two directories from the TOOL_DIR. # |
| ︙ | ︙ |