From 7074d76f2ba74ea9a53f47fb4815145982285625 Mon Sep 17 00:00:00 2001 From: vincentdarley Date: Wed, 17 Jul 2002 20:00:44 +0000 Subject: load internals refactoring --- ChangeLog | 18 +++++ generic/tclIOUtil.c | 44 +++++++++++- generic/tclInt.h | 13 +++- generic/tclLoadNone.c | 29 +++++--- mac/tclMacLoad.c | 186 +++++++++++++++++++++++++++++++------------------- unix/tclLoadAout.c | 33 ++++----- unix/tclLoadDl.c | 54 ++++++--------- unix/tclLoadDld.c | 29 ++++---- unix/tclLoadDyld.c | 69 ++++++++----------- unix/tclLoadNext.c | 44 ++++++------ unix/tclLoadOSF.c | 33 +++++---- unix/tclLoadShl.c | 53 +++++++------- win/tclWinLoad.c | 48 ++++++------- 13 files changed, 370 insertions(+), 283 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b3b350..d2ea46b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2002-07-17 Vince Darley + + * generic/tclInt.h: + * generic/tclIOUtil.c: + * generic/tclLoadNone.c: + * unix/tclLoadAout.c: + * unix/tclLoadDl.c: + * unix/tclLoadDld.c: + * unix/tclLoadDyld.c: + * unix/tclLoadNext.c: + * unix/tclLoadOSF.c: + * unix/tclLoadShl.c: + * mac/tclMacLoad.c: + * win/tclWinLoad.c: modified to move more functionality + to the generic code and avoid duplication. Partial replacement + of internal uses of clientData with opaque TclLoadHandle. A + little further work still needed, but significant changes are done. + 2002-07-17 D. Richard Hipp * library/msgcat/msgcat.tcl: fix a comment that was causing diff --git a/generic/tclIOUtil.c b/generic/tclIOUtil.c index 5b82f7e..c875292 100644 --- a/generic/tclIOUtil.c +++ b/generic/tclIOUtil.c @@ -17,7 +17,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclIOUtil.c,v 1.55 2002/07/15 14:16:43 vincentdarley Exp $ + * RCS: @(#) $Id: tclIOUtil.c,v 1.56 2002/07/17 20:00:44 vincentdarley Exp $ */ #include "tclInt.h" @@ -2626,6 +2626,48 @@ Tcl_FSLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, Tcl_SetErrno(ENOENT); return -1; } +/* + * This function used to be in the platform specific directories, but it + * has now been made to work cross-platform + */ +int +TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, + clientDataPtr, unloadProcPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Obj *pathPtr; /* Name of the file containing the desired + * code (UTF-8). */ + CONST char *sym1, *sym2; /* Names of two procedures to look up in + * the file's symbol table. */ + Tcl_PackageInitProc **proc1Ptr, **proc2Ptr; + /* Where to return the addresses corresponding + * to sym1 and sym2. */ + ClientData *clientDataPtr; /* Filled with token for dynamically loaded + * file which will be passed back to + * (*unloadProcPtr)() to unload the file. */ + Tcl_FSUnloadFileProc **unloadProcPtr; + /* Filled with address of Tcl_FSUnloadFileProc + * function which should be used for + * this file. */ +{ + TclLoadHandle handle = NULL; + int res; + + res = TclpDlopen(interp, pathPtr, &handle, unloadProcPtr); + + if (res != TCL_OK) { + return res; + } + + if (handle == NULL) { + return TCL_ERROR; + } + + *clientDataPtr = (ClientData)handle; + + *proc1Ptr = TclpFindSymbol(interp, handle, sym1); + *proc2Ptr = TclpFindSymbol(interp, handle, sym2); + return TCL_OK; +} /* *--------------------------------------------------------------------------- diff --git a/generic/tclInt.h b/generic/tclInt.h index 3fca93b..ba9ebc3 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -12,7 +12,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.101 2002/07/17 10:36:23 msofer Exp $ + * RCS: @(#) $Id: tclInt.h,v 1.102 2002/07/17 20:00:45 vincentdarley Exp $ */ #ifndef _TCLINT @@ -1563,7 +1563,8 @@ typedef struct TclFile_ *TclFile; * Opaque names for platform specific types. */ -typedef struct TclpTime_t_ *TclpTime_t; +typedef struct TclpTime_t_ *TclpTime_t; +typedef struct TclLoadHandle_ *TclLoadHandle; /* * The "globParameters" argument of the function TclGlob is an @@ -1829,8 +1830,14 @@ EXTERN void TclTransferResult _ANSI_ARGS_((Tcl_Interp *sourceInterp, int result, Tcl_Interp *targetInterp)); EXTERN Tcl_Obj* TclpNativeToNormalized _ANSI_ARGS_((ClientData clientData)); -EXTERN Tcl_Obj* TclpFilesystemPathType +EXTERN Tcl_Obj* TclpFilesystemPathType _ANSI_ARGS_((Tcl_Obj* pathObjPtr)); +EXTERN Tcl_PackageInitProc* TclpFindSymbol _ANSI_ARGS_((Tcl_Interp *interp, + TclLoadHandle loadHandle, CONST char *symbol)); +EXTERN int TclpDlopen _ANSI_ARGS_((Tcl_Interp *interp, + Tcl_Obj *pathPtr, + TclLoadHandle *loadHandle, + Tcl_FSUnloadFileProc **unloadProcPtr)); /* *---------------------------------------------------------------- diff --git a/generic/tclLoadNone.c b/generic/tclLoadNone.c index ee79130..9d93ba1 100644 --- a/generic/tclLoadNone.c +++ b/generic/tclLoadNone.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: tclLoadNone.c,v 1.8 2002/01/21 22:47:52 davygrvy Exp $ + * RCS: @(#) $Id: tclLoadNone.c,v 1.9 2002/07/17 20:00:46 vincentdarley Exp $ */ #include "tclInt.h" @@ -35,19 +35,17 @@ */ int -TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, clientDataPtr, unloadProcPtr) +TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr) Tcl_Interp *interp; /* Used for error reporting. */ Tcl_Obj *pathPtr; /* Name of the file containing the desired - * code. */ - CONST char *sym1, *sym2; /* Names of two procedures to look up in - * the file's symbol table. */ - Tcl_PackageInitProc **proc1Ptr, **proc2Ptr; - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - ClientData *clientDataPtr; /* Filled with token for dynamically loaded + * code (UTF-8). */ + TclLoadHandle *loadHandle; /* Filled with token for dynamically loaded * file which will be passed back to - * TclpUnloadFile() to unload the file. */ - Tcl_FSUnloadFileProc **unloadProcPtr; + * (*unloadProcPtr)() to unload the file. */ + Tcl_FSUnloadFileProc **unloadProcPtr; + /* Filled with address of Tcl_FSUnloadFileProc + * function which should be used for + * this file. */ { Tcl_SetResult(interp, "dynamic loading is not currently available on this system", @@ -55,6 +53,15 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, clientDataPtr, unl return TCL_ERROR; } +Tcl_PackageInitProc* +TclpFindSymbol(interp, loadHandle, symbol) + Tcl_Interp *interp; + TclLoadHandle loadHandle; + CONST char *symbol; +{ + return NULL; +} + /* *---------------------------------------------------------------------- * diff --git a/mac/tclMacLoad.c b/mac/tclMacLoad.c index e767651..a36e151 100644 --- a/mac/tclMacLoad.c +++ b/mac/tclMacLoad.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: tclMacLoad.c,v 1.12 2002/01/27 11:09:58 das Exp $ + * RCS: @(#) $Id: tclMacLoad.c,v 1.13 2002/07/17 20:00:46 vincentdarley Exp $ */ #include @@ -76,6 +76,16 @@ struct CfrgItem { Str255 name; /* This is actually variable sized. */ }; typedef struct CfrgItem CfrgItem; + +typedef struct TclMacLoadInfo { + int loaded; + CFragConnectionID connID; + FSSpec fileSpec; +} TclMacLoadInfo; + +static int TryToLoad(Tcl_Interp *interp, TclMacLoadInfo *loadInfo, + CONST char *sym /* native */) + /* *---------------------------------------------------------------------- @@ -97,18 +107,11 @@ typedef struct CfrgItem CfrgItem; */ int -TclpLoadFile( - Tcl_Interp *interp, /* Used for error reporting. */ - Tcl_Obj *pathPtr, /* Name of the file containing the desired - * code. */ - CONST char *sym1, - CONST char *sym2, /* Names of two procedures to look up in - * the file's symbol table. */ - Tcl_PackageInitProc **proc1Ptr, - Tcl_PackageInitProc **proc2Ptr, - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - ClientData *clientDataPtr, /* Filled with token for dynamically loaded +TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr) + Tcl_Interp *interp; /* Used for error reporting. */ + Tcl_Obj *pathPtr; /* Name of the file containing the desired + * code (UTF-8). */ + TclLoadHandle *loadHandle; /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr) @@ -116,19 +119,11 @@ TclpLoadFile( * function which should be used for * this file. */ { - CFragConnectionID connID; - Ptr dummy; OSErr err; - CFragSymbolClass symClass; FSSpec fileSpec; - short fragFileRef, saveFileRef; - Handle fragResource; - UInt32 offset = 0; - UInt32 length = kCFragGoesToEOF; - StringPtr fragName=NULL; - Str255 errName, symbolName; Tcl_DString ds; CONST char *native; + TclMacLoadInfo *loadInfo; native = Tcl_FSGetNativePath(pathPtr); err = FSpLocationFromPath(strlen(native), native, &fileSpec); @@ -138,15 +133,37 @@ TclpLoadFile( return TCL_ERROR; } - /* - * First thing we must do is infer the package name from the sym1 - * variable (by removing the "_Init" suffix). This is kind of dumb - * since the caller actually knows this value, it just doesn't give - * it to us. - */ - native = Tcl_UtfToExternalDString(NULL, sym1, -1, &ds); - Tcl_DStringSetLength(&ds, Tcl_DStringLength(&ds) - 5); + loadInfo = (TclMacLoadInfo *) ckalloc(sizeof(TclMacLoadInfo)); + loadInfo->loaded = 0; + loadInfo->fileSpec = fileSpec; + loadInfo->connID = NULL; + if (TryToLoad(interp, loadInfo, NULL) != TCL_OK) { + ckfree(loadInfo); + return TCL_ERROR; + } + + *loadHandle = (TclLoadHandle)loadInfo; + *unloadProcPtr = &TclpUnloadFile; + return TCL_OK; +} +static int +TryToLoad(Tcl_Interp *interp, TclMacLoadInfo *loadInfo, + CONST char *sym /* native */) +{ + CFragConnectionID connID; + Ptr dummy; + short fragFileRef, saveFileRef; + Handle fragResource; + UInt32 offset = 0; + UInt32 length = kCFragGoesToEOF; + Str255 errName; + StringPtr fragName=NULL; + + if (loadInfo->loaded == 1) { + return TCL_OK; + } + /* * See if this fragment has a 'cfrg' resource. It will tell us where * to look for the fragment in the file. If it doesn't exist we will @@ -160,25 +177,27 @@ TclpLoadFile( fragFileRef = FSpOpenResFile(&fileSpec, fsRdPerm); SetResLoad(true); if (fragFileRef != -1) { - UseResFile(fragFileRef); - fragResource = Get1Resource(kCFragResourceType, kCFragResourceID); - HLock(fragResource); - if (ResError() == noErr) { - CfrgItem* srcItem; - long itemCount, index; - Ptr itemStart; + if (sym != NULL) { + UseResFile(fragFileRef); + fragResource = Get1Resource(kCFragResourceType, kCFragResourceID); + HLock(fragResource); + if (ResError() == noErr) { + CfrgItem* srcItem; + long itemCount, index; + Ptr itemStart; - itemCount = (*(CfrgHeaderPtrHand)fragResource)->itemCount; - itemStart = &(*(CfrgHeaderPtrHand)fragResource)->arrayStart; - for (index = 0; index < itemCount; - index++, itemStart += srcItem->itemSize) { - srcItem = (CfrgItem*)itemStart; - if (srcItem->archType != OUR_ARCH_TYPE) continue; - if (!strncasecmp(native, (char *) srcItem->name + 1, - strlen(native))) { - offset = srcItem->codeOffset; - length = srcItem->codeLength; - fragName=srcItem->name; + itemCount = (*(CfrgHeaderPtrHand)fragResource)->itemCount; + itemStart = &(*(CfrgHeaderPtrHand)fragResource)->arrayStart; + for (index = 0; index < itemCount; + index++, itemStart += srcItem->itemSize) { + srcItem = (CfrgItem*)itemStart; + if (srcItem->archType != OUR_ARCH_TYPE) continue; + if (!strncasecmp(sym, (char *) srcItem->name + 1, + strlen(sym))) { + offset = srcItem->codeOffset; + length = srcItem->codeLength; + fragName=srcItem->name; + } } } } @@ -191,20 +210,21 @@ TclpLoadFile( ReleaseResource(fragResource); CloseResFile(fragFileRef); UseResFile(saveFileRef); + if (sym == NULL) { + /* We just return */ + return TCL_OK; + } } - Tcl_DStringFree(&ds); /* - * Now we can attempt to load the fragement using the offset & length + * Now we can attempt to load the fragment using the offset & length * obtained from the resource. We don't worry about the main entry point * as we are going to search for specific entry points passed to us. */ err = GetDiskFragment(&fileSpec, offset, length, fragName, kLoadCFrag, &connID, &dummy, errName); - - *clientDataPtr = (ClientData) connID; - + if (err != fragNoErr) { p2cstr(errName); Tcl_AppendResult(interp, "couldn't load file \"", @@ -212,31 +232,53 @@ TclpLoadFile( "\": ", errName, (char *) NULL); return TCL_ERROR; } - - *unloadProcPtr = &TclpUnloadFile; + + loadInfo->connID = connID; + loadInfo->loaded = 1; + + return TCL_OK; +} + +Tcl_PackageInitProc* +TclpFindSymbol(interp, loadHandle, symbol) + Tcl_Interp *interp; + TclLoadHandle loadHandle; + CONST char *symbol; +{ + Tcl_DString ds; + Tcl_PackageInitProc *proc=NULL; + TclMacLoadInfo *loadInfo = (TclMacLoadInfo *)loadHandle; + Str255 symbolName; + CFragSymbolClass symClass; + OSErr err; - Tcl_UtfToExternalDString(NULL, sym1, -1, &ds); + if (loadInfo->loaded == 0) { + int res; + /* + * First thing we must do is infer the package name from the + * sym variable. We do this by removing the '_Init'. + */ + Tcl_UtfToExternalDString(NULL, symbol, -1, &ds); + Tcl_DStringSetLength(&ds, Tcl_DStringLength(&ds) - 5); + res = TryToLoad(interp, loadInfo, Tcl_DStringValue(&ds)); + Tcl_DStringFree(&ds); + if (res != TCL_OK) { + return NULL; + } + } + + Tcl_UtfToExternalDString(NULL, symbol, -1, &ds); strcpy((char *) symbolName + 1, Tcl_DStringValue(&ds)); symbolName[0] = (unsigned) Tcl_DStringLength(&ds); - err = FindSymbol(connID, symbolName, (Ptr *) proc1Ptr, &symClass); + err = FindSymbol(loadInfo->connID, symbolName, (Ptr *) &proc, &symClass); Tcl_DStringFree(&ds); if (err != fragNoErr || symClass == kDataCFragSymbol) { Tcl_SetResult(interp, "could not find Initialization routine in library", TCL_STATIC); - return TCL_ERROR; + return NULL; } - - Tcl_UtfToExternalDString(NULL, sym2, -1, &ds); - strcpy((char *) symbolName + 1, Tcl_DStringValue(&ds)); - symbolName[0] = (unsigned) Tcl_DStringLength(&ds); - err = FindSymbol(connID, symbolName, (Ptr *) proc2Ptr, &symClass); - Tcl_DStringFree(&ds); - if (err != fragNoErr || symClass == kDataCFragSymbol) { - *proc2Ptr = NULL; - } - - return TCL_OK; + return proc; } /* @@ -264,7 +306,11 @@ TclpUnloadFile(clientData) * a token that represents the loaded * file. */ { - CloseConnection((CFragConnectionID*) &clientData); + TclMacLoadInfo *loadInfo = (TclMacLoadInfo *)clientData; + if (loadInfo->loaded) { + CloseConnection((CFragConnectionID*) &(loadInfo->connID)); + } + ckfree(loadInfo); } /* diff --git a/unix/tclLoadAout.c b/unix/tclLoadAout.c index afd956c..c4d6254 100644 --- a/unix/tclLoadAout.c +++ b/unix/tclLoadAout.c @@ -14,7 +14,7 @@ * and Design Engineering (MADE) Initiative through ARPA contract * F33615-94-C-4400. * - * RCS: @(#) $Id: tclLoadAout.c,v 1.10 2002/02/15 14:28:50 dkf Exp $ + * RCS: @(#) $Id: tclLoadAout.c,v 1.11 2002/07/17 20:00:46 vincentdarley Exp $ */ #include "tclInt.h" @@ -141,17 +141,11 @@ static void UnlinkSymbolTable _ANSI_ARGS_((void)); */ int -TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, - clientDataPtr, unloadProcPtr) +TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr) Tcl_Interp *interp; /* Used for error reporting. */ Tcl_Obj *pathPtr; /* Name of the file containing the desired * code (UTF-8). */ - CONST char *sym1, *sym2; /* Names of two procedures to look up in - * the file's symbol table. */ - Tcl_PackageInitProc **proc1Ptr, **proc2Ptr; - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - ClientData *clientDataPtr; /* Filled with token for dynamically loaded + TclLoadHandle *loadHandle; /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr; @@ -172,12 +166,9 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, struct exec relocatedHead; /* Header of the relocated text */ unsigned long relocatedSize; /* Size of the relocated text */ char * startAddress; /* Starting address of the module */ - DictFn dictionary; /* Dictionary function in the load module */ int status; /* Status return from Tcl_ calls */ char * p; - *clientDataPtr = NULL; - /* Find the file that contains the symbols for the run-time link. */ if (SymbolTableFile != NULL) { @@ -317,15 +308,21 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, SymbolTableFile = ckalloc (strlen (relocatedFileName) + 1); strcpy (SymbolTableFile, relocatedFileName); - /* Look up the entry points in the load module's dictionary. */ - - dictionary = (DictFn) startAddress; - *proc1Ptr = dictionary (sym1); - *proc2Ptr = dictionary (sym2); - + *loadHandle = startAddress; return TCL_OK; } +TclpFindSymbol(interp, loadHandle, symbol) + Tcl_Interp *interp; + TclLoadHandle loadHandle; + CONST char *symbol; +{ + /* Look up the entry point in the load module's dictionary. */ + DictFn dictionary = (DictFn) loadHandle; + return (Tcl_PackageInitProc*) dictionary(sym1); +} + + /* *------------------------------------------------------------------------ * diff --git a/unix/tclLoadDl.c b/unix/tclLoadDl.c index 3578695..951a8cb 100644 --- a/unix/tclLoadDl.c +++ b/unix/tclLoadDl.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: tclLoadDl.c,v 1.8 2002/01/09 19:09:28 kennykb Exp $ + * RCS: @(#) $Id: tclLoadDl.c,v 1.9 2002/07/17 20:00:46 vincentdarley Exp $ */ #include "tclInt.h" @@ -57,17 +57,11 @@ */ int -TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, - clientDataPtr, unloadProcPtr) +TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr) Tcl_Interp *interp; /* Used for error reporting. */ Tcl_Obj *pathPtr; /* Name of the file containing the desired - * code. */ - CONST char *sym1, *sym2; /* Names of two procedures to look up in - * the file's symbol table. */ - Tcl_PackageInitProc **proc1Ptr, **proc2Ptr; - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - ClientData *clientDataPtr; /* Filled with token for dynamically loaded + * code (UTF-8). */ + TclLoadHandle *loadHandle; /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr; @@ -76,14 +70,11 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, * this file. */ { VOID *handle; - Tcl_DString newName, ds; CONST char *native; native = Tcl_FSGetNativePath(pathPtr); handle = dlopen(native, RTLD_NOW | RTLD_GLOBAL); /* INTL: Native. */ - *clientDataPtr = (ClientData) handle; - if (handle == NULL) { Tcl_AppendResult(interp, "couldn't load file \"", Tcl_GetString(pathPtr), @@ -92,40 +83,39 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, } *unloadProcPtr = &TclpUnloadFile; - + *loadHandle = (TclLoadHandle)handle; +} + +Tcl_PackageInitProc* +TclpFindSymbol(interp, loadHandle, symbol) + Tcl_Interp *interp; + TclLoadHandle loadHandle; + CONST char *symbol; +{ + CONST char *native; + Tcl_DString newName, ds; + VOID *handle = (VOID*)loadHandle; + Tcl_PackageInitProc *proc; /* * Some platforms still add an underscore to the beginning of symbol * names. If we can't find a name without an underscore, try again * with the underscore. */ - native = Tcl_UtfToExternalDString(NULL, sym1, -1, &ds); - *proc1Ptr = (Tcl_PackageInitProc *) dlsym(handle, /* INTL: Native. */ + native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds); + proc = (Tcl_PackageInitProc *) dlsym(handle, /* INTL: Native. */ native); - if (*proc1Ptr == NULL) { + if (proc == NULL) { Tcl_DStringInit(&newName); Tcl_DStringAppend(&newName, "_", 1); native = Tcl_DStringAppend(&newName, native, -1); - *proc1Ptr = (Tcl_PackageInitProc *) dlsym(handle, /* INTL: Native. */ + proc = (Tcl_PackageInitProc *) dlsym(handle, /* INTL: Native. */ native); Tcl_DStringFree(&newName); } Tcl_DStringFree(&ds); - native = Tcl_UtfToExternalDString(NULL, sym2, -1, &ds); - *proc2Ptr = (Tcl_PackageInitProc *) dlsym(handle, /* INTL: Native. */ - native); - if (*proc2Ptr == NULL) { - Tcl_DStringInit(&newName); - Tcl_DStringAppend(&newName, "_", 1); - native = Tcl_DStringAppend(&newName, native, -1); - *proc2Ptr = (Tcl_PackageInitProc *) dlsym(handle, /* INTL: Native. */ - native); - Tcl_DStringFree(&newName); - } - Tcl_DStringFree(&ds); - - return TCL_OK; + return proc; } /* diff --git a/unix/tclLoadDld.c b/unix/tclLoadDld.c index f1c1589..99fee26 100644 --- a/unix/tclLoadDld.c +++ b/unix/tclLoadDld.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclLoadDld.c,v 1.8 2002/01/10 22:03:12 kennykb Exp $ + * RCS: @(#) $Id: tclLoadDld.c,v 1.9 2002/07/17 20:00:46 vincentdarley Exp $ */ #include "tclInt.h" @@ -49,17 +49,11 @@ */ int -TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, - clientDataPtr, unloadProcPtr) +TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr) Tcl_Interp *interp; /* Used for error reporting. */ Tcl_Obj *pathPtr; /* Name of the file containing the desired - * code. */ - CONST char *sym1, *sym2; /* Names of two procedures to look up in - * the file's symbol table. */ - Tcl_PackageInitProc **proc1Ptr, **proc2Ptr; - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - ClientData *clientDataPtr; /* Filled with token for dynamically loaded + * code (UTF-8). */ + TclLoadHandle *loadHandle; /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr; @@ -73,7 +67,7 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, /* * The dld package needs to know the pathname to the tcl binary. - * If that's not know, return an error. + * If that's not known, return an error. */ if (firstTime) { @@ -99,14 +93,21 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, "\": ", dld_strerror(returnCode), (char *) NULL); return TCL_ERROR; } - *proc1Ptr = (Tcl_PackageInitProc *) dld_get_func(sym1); - *proc2Ptr = (Tcl_PackageInitProc *) dld_get_func(sym2); - *clientDataPtr = strcpy( + *loadHandle = strcpy( (char *) ckalloc((unsigned) (strlen(fileName) + 1)), fileName); *unloadProcPtr = &TclpUnloadFile; return TCL_OK; } +Tcl_PackageInitProc* +TclpFindSymbol(interp, loadHandle, symbol) + Tcl_Interp *interp; + TclLoadHandle loadHandle; + CONST char *symbol; +{ + return (Tcl_PackageInitProc *) dld_get_func(symbol); +} + /* *---------------------------------------------------------------------- * diff --git a/unix/tclLoadDyld.c b/unix/tclLoadDyld.c index 8541416..9eefd91 100644 --- a/unix/tclLoadDyld.c +++ b/unix/tclLoadDyld.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclLoadDyld.c,v 1.8 2002/02/25 15:21:59 das Exp $ + * RCS: @(#) $Id: tclLoadDyld.c,v 1.9 2002/07/17 20:00:46 vincentdarley Exp $ */ #include "tclInt.h" @@ -40,17 +40,11 @@ */ int -TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, - clientDataPtr, unloadProcPtr) +TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr) Tcl_Interp *interp; /* Used for error reporting. */ Tcl_Obj *pathPtr; /* Name of the file containing the desired - * code. */ - CONST char *sym1, *sym2; /* Names of two procedures to look up in - * the file's symbol table. */ - Tcl_PackageInitProc **proc1Ptr, **proc2Ptr; - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - ClientData *clientDataPtr; /* Filled with token for dynamically loaded + * code (UTF-8). */ + TclLoadHandle *loadHandle; /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr; @@ -58,9 +52,7 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, * function which should be used for * this file. */ { - NSSymbol symbol; const struct mach_header *dyld_lib; - Tcl_DString newName, ds; char *native; native = Tcl_FSGetNativePath(pathPtr); @@ -75,46 +67,41 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, Tcl_AppendResult(interp, msg, (char *) NULL); return TCL_ERROR; } - + *loadHandle = (TclLoadHandle)dyld_lib; *unloadProcPtr = &TclpUnloadFile; - + return TCL_OK; +} + +Tcl_PackageInitProc* +TclpFindSymbol(interp, loadHandle, symbol) + Tcl_Interp *interp; + TclLoadHandle loadHandle; + CONST char *symbol; +{ + NSSymbol nsSymbol; + CONST char *native; + Tcl_DString newName, ds; + Tcl_PackageInitProc* proc = NULL; + const struct mach_header *dyld_lib = (mach_header *)loadHandle; /* * dyld adds an underscore to the beginning of symbol names. */ - native = Tcl_UtfToExternalDString(NULL, sym1, -1, &ds); + native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds); Tcl_DStringInit(&newName); Tcl_DStringAppend(&newName, "_", 1); native = Tcl_DStringAppend(&newName, native, -1); - symbol = NSLookupSymbolInImage(dyld_lib, native, - NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW | - NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); - if(symbol) { - *proc1Ptr = NSAddressOfSymbol(symbol); - *clientDataPtr = NSModuleForSymbol(symbol); - } else { - *proc1Ptr=NULL; - *clientDataPtr=NULL; + nsSymbol = NSLookupSymbolInImage(dyld_lib, native, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + if(nsSymbol) { + proc = NSAddressOfSymbol(nsSymbol); + /* *clientDataPtr = NSModuleForSymbol(nsSymbol); */ } Tcl_DStringFree(&newName); Tcl_DStringFree(&ds); - - native = Tcl_UtfToExternalDString(NULL, sym2, -1, &ds); - Tcl_DStringInit(&newName); - Tcl_DStringAppend(&newName, "_", 1); - native = Tcl_DStringAppend(&newName, native, -1); - symbol = NSLookupSymbolInImage(dyld_lib, native, - NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW | - NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); - if(symbol) { - *proc2Ptr = NSAddressOfSymbol(symbol); - } else { - *proc2Ptr=NULL; - } - Tcl_DStringFree(&newName); - Tcl_DStringFree(&ds); - - return TCL_OK; + + return proc; } /* diff --git a/unix/tclLoadNext.c b/unix/tclLoadNext.c index d19b22e..cb09d38 100644 --- a/unix/tclLoadNext.c +++ b/unix/tclLoadNext.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: tclLoadNext.c,v 1.7 2002/01/09 19:09:28 kennykb Exp $ + * RCS: @(#) $Id: tclLoadNext.c,v 1.8 2002/07/17 20:00:46 vincentdarley Exp $ */ #include "tclInt.h" @@ -39,17 +39,11 @@ */ int -TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, - clientDataPtr, unloadProcPtr) +TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr) Tcl_Interp *interp; /* Used for error reporting. */ Tcl_Obj *pathPtr; /* Name of the file containing the desired - * code. */ - CONST char *sym1, *sym2; /* Names of two procedures to look up in - * the file's symbol table. */ - Tcl_PackageInitProc **proc1Ptr, **proc2Ptr; - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - ClientData *clientDataPtr; /* Filled with token for dynamically loaded + * code (UTF-8). */ + TclLoadHandle *loadHandle; /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr; @@ -72,25 +66,27 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, } NXCloseMemory(errorStream,NX_FREEBUFFER); - *proc1Ptr=NULL; - if(sym1) { - char sym[strlen(sym1)+2]; - sym[0]='_'; sym[1]=0; strcat(sym,sym1); - rld_lookup(NULL,sym,(unsigned long *)proc1Ptr); - } - - *proc2Ptr=NULL; - if(sym2) { - char sym[strlen(sym2)+2]; - sym[0]='_'; sym[1]=0; strcat(sym,sym2); - rld_lookup(NULL,sym,(unsigned long *)proc2Ptr); - } - *clientDataPtr = NULL; + *loadHandle = (TclLoadHandle)1; /* A dummy non-NULL value */ *unloadProcPtr = &TclpUnloadFile; return TCL_OK; } +Tcl_PackageInitProc* +TclpFindSymbol(interp, loadHandle, symbol) + Tcl_Interp *interp; + TclLoadHandle loadHandle; + CONST char *symbol; +{ + Tcl_PackageInitProc *proc=NULL; + if(symbol) { + char sym[strlen(symbol)+2]; + sym[0]='_'; sym[1]=0; strcat(sym,symbol); + rld_lookup(NULL,sym,(unsigned long *)&proc); + } + return proc; +} + /* *---------------------------------------------------------------------- * diff --git a/unix/tclLoadOSF.c b/unix/tclLoadOSF.c index 76c0c7c..8740feb 100644 --- a/unix/tclLoadOSF.c +++ b/unix/tclLoadOSF.c @@ -31,7 +31,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclLoadOSF.c,v 1.7 2002/01/09 19:09:28 kennykb Exp $ + * RCS: @(#) $Id: tclLoadOSF.c,v 1.8 2002/07/17 20:00:46 vincentdarley Exp $ */ #include "tclInt.h" @@ -60,17 +60,11 @@ */ int -TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, - clientDataPtr, unloadProcPtr) +TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr) Tcl_Interp *interp; /* Used for error reporting. */ Tcl_Obj *pathPtr; /* Name of the file containing the desired - * code. */ - CONST char *sym1, *sym2; /* Names of two procedures to look up in - * the file's symbol table. */ - Tcl_PackageInitProc **proc1Ptr, **proc2Ptr; - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - ClientData *clientDataPtr; /* Filled with token for dynamically loaded + * code (UTF-8). */ + TclLoadHandle *loadHandle; /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr; @@ -99,16 +93,25 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, * I build loadable modules with a makefile rule like * ld ... -export $@: -o $@ $(OBJS) */ - if ((pkg = strrchr(fileName, '/')) == NULL) - pkg = fileName; - else + if ((pkg = strrchr(fileName, '/')) == NULL) { + pkg = fileName; + } else { pkg++; - *proc1Ptr = ldr_lookup_package(pkg, sym1); - *proc2Ptr = ldr_lookup_package(pkg, sym2); + } + *loadHandle = pkg; *unloadProcPtr = &TclpUnloadFile; return TCL_OK; } +Tcl_PackageInitProc* +TclpFindSymbol(interp, loadHandle, symbol) + Tcl_Interp *interp; + TclLoadHandle loadHandle; + CONST char *symbol; +{ + return ldr_lookup_package((char *)loadHandle, symbol); +} + /* *---------------------------------------------------------------------- * diff --git a/unix/tclLoadShl.c b/unix/tclLoadShl.c index cb222bb..14e5b2d 100644 --- a/unix/tclLoadShl.c +++ b/unix/tclLoadShl.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: tclLoadShl.c,v 1.9 2002/01/09 19:09:28 kennykb Exp $ + * RCS: @(#) $Id: tclLoadShl.c,v 1.10 2002/07/17 20:00:46 vincentdarley Exp $ */ #include @@ -47,17 +47,11 @@ */ int -TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, - clientDataPtr, unloadProcPtr) +TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr) Tcl_Interp *interp; /* Used for error reporting. */ Tcl_Obj *pathPtr; /* Name of the file containing the desired - * code. */ - CONST char *sym1, *sym2; /* Names of two procedures to look up in - * the file's symbol table. */ - Tcl_PackageInitProc **proc1Ptr, **proc2Ptr; - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - ClientData *clientDataPtr; /* Filled with token for dynamically loaded + * code (UTF-8). */ + TclLoadHandle *loadHandle; /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr; @@ -66,7 +60,6 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, * this file. */ { shl_t handle; - Tcl_DString newName; char *fileName = Tcl_GetString(pathPtr); /* @@ -87,38 +80,38 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, "\": ", Tcl_PosixError(interp), (char *) NULL); return TCL_ERROR; } - *clientDataPtr = (ClientData) handle; - + *loadHandle = (TclLoadHandle) handle; + *unloadProcPtr = &TclpUnloadFile; + return TCL_OK; +} + +Tcl_PackageInitProc* +TclpFindSymbol(interp, loadHandle, symbol) + Tcl_Interp *interp; + TclLoadHandle loadHandle; + CONST char *symbol; +{ + Tcl_DString newName; + Tcl_PackageInitProc *proc=NULL; + shl_t handle = (shl_t)loadHandle; /* * Some versions of the HP system software still use "_" at the * beginning of exported symbols while others don't; try both * forms of each name. */ - if (shl_findsym(&handle, sym1, (short) TYPE_PROCEDURE, (void *) proc1Ptr) + if (shl_findsym(&handle, symbol, (short) TYPE_PROCEDURE, (void *) &proc) != 0) { Tcl_DStringInit(&newName); Tcl_DStringAppend(&newName, "_", 1); - Tcl_DStringAppend(&newName, sym1, -1); + Tcl_DStringAppend(&newName, symbol, -1); if (shl_findsym(&handle, Tcl_DStringValue(&newName), - (short) TYPE_PROCEDURE, (void *) proc1Ptr) != 0) { - *proc1Ptr = NULL; + (short) TYPE_PROCEDURE, (void *) &proc) != 0) { + proc = NULL; } Tcl_DStringFree(&newName); } - if (shl_findsym(&handle, sym2, (short) TYPE_PROCEDURE, (void *) proc2Ptr) - != 0) { - Tcl_DStringInit(&newName); - Tcl_DStringAppend(&newName, "_", 1); - Tcl_DStringAppend(&newName, sym2, -1); - if (shl_findsym(&handle, Tcl_DStringValue(&newName), - (short) TYPE_PROCEDURE, (void *) proc2Ptr) != 0) { - *proc2Ptr = NULL; - } - Tcl_DStringFree(&newName); - } - *unloadProcPtr = &TclpUnloadFile; - return TCL_OK; + return proc; } /* diff --git a/win/tclWinLoad.c b/win/tclWinLoad.c index 8e23490..48a6c3b 100644 --- a/win/tclWinLoad.c +++ b/win/tclWinLoad.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: tclWinLoad.c,v 1.11 2002/01/25 21:36:10 dgp Exp $ + * RCS: @(#) $Id: tclWinLoad.c,v 1.12 2002/07/17 20:00:46 vincentdarley Exp $ */ #include "tclWinInt.h" @@ -36,17 +36,11 @@ */ int -TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, - clientDataPtr, unloadProcPtr) +TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr) Tcl_Interp *interp; /* Used for error reporting. */ Tcl_Obj *pathPtr; /* Name of the file containing the desired - * code. */ - CONST char *sym1, *sym2; /* Names of two procedures to look up in - * the file's symbol table. */ - Tcl_PackageInitProc **proc1Ptr, **proc2Ptr; - /* Where to return the addresses corresponding - * to sym1 and sym2. */ - ClientData *clientDataPtr; /* Filled with token for dynamically loaded + * code (UTF-8). */ + TclLoadHandle *loadHandle; /* Filled with token for dynamically loaded * file which will be passed back to * (*unloadProcPtr)() to unload the file. */ Tcl_FSUnloadFileProc **unloadProcPtr; @@ -63,7 +57,7 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, handle = (*tclWinProcs->loadLibraryProc)(nativeName); Tcl_DStringFree(&ds); - *clientDataPtr = (ClientData) handle; + *loadHandle = (TclLoadHandle) handle; if (handle == NULL) { DWORD lastError = GetLastError(); @@ -117,27 +111,33 @@ TclpLoadFile(interp, pathPtr, sym1, sym2, proc1Ptr, proc2Ptr, } else { *unloadProcPtr = &TclpUnloadFile; } + return TCL_OK; +} + +Tcl_PackageInitProc* +TclpFindSymbol(interp, loadHandle, symbol) + Tcl_Interp *interp; + TclLoadHandle loadHandle; + CONST char *symbol; +{ + Tcl_PackageInitProc *proc = NULL; + HINSTANCE handle = (HINSTANCE)loadHandle; + /* * For each symbol, check for both Symbol and _Symbol, since Borland * generates C symbols with a leading '_' by default. */ - *proc1Ptr = (Tcl_PackageInitProc *) GetProcAddress(handle, sym1); - if (*proc1Ptr == NULL) { + proc = (Tcl_PackageInitProc *) GetProcAddress(handle, symbol); + if (proc == NULL) { + Tcl_DString ds; + Tcl_DStringInit(&ds); Tcl_DStringAppend(&ds, "_", 1); - sym1 = Tcl_DStringAppend(&ds, sym1, -1); - *proc1Ptr = (Tcl_PackageInitProc *) GetProcAddress(handle, sym1); + symbol = Tcl_DStringAppend(&ds, symbol, -1); + proc = (Tcl_PackageInitProc *) GetProcAddress(handle, symbol); Tcl_DStringFree(&ds); } - - *proc2Ptr = (Tcl_PackageInitProc *) GetProcAddress(handle, sym2); - if (*proc2Ptr == NULL) { - Tcl_DStringAppend(&ds, "_", 1); - sym2 = Tcl_DStringAppend(&ds, sym2, -1); - *proc2Ptr = (Tcl_PackageInitProc *) GetProcAddress(handle, sym2); - Tcl_DStringFree(&ds); - } - return TCL_OK; + return proc; } /* -- cgit v0.12