os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclLoadDl.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* 
     2  * tclLoadDl.c --
     3  *
     4  *	This procedure provides a version of the TclLoadFile that
     5  *	works with the "dlopen" and "dlsym" library procedures for
     6  *	dynamic loading.
     7  *
     8  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
     9  *
    10  * See the file "license.terms" for information on usage and redistribution
    11  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    12  *
    13  * RCS: @(#) $Id: tclLoadDl.c,v 1.13.2.1 2006/06/13 22:54:01 dkf Exp $
    14  */
    15 
    16 #include "tclInt.h"
    17 #ifdef NO_DLFCN_H
    18 #   include "../compat/dlfcn.h"
    19 #else
    20 #   include <dlfcn.h>
    21 #endif
    22 
    23 /*
    24  * In some systems, like SunOS 4.1.3, the RTLD_NOW flag isn't defined
    25  * and this argument to dlopen must always be 1.  The RTLD_GLOBAL
    26  * flag is needed on some systems (e.g. SCO and UnixWare) but doesn't
    27  * exist on others;  if it doesn't exist, set it to 0 so it has no effect.
    28  */
    29 
    30 #ifndef RTLD_NOW
    31 #   define RTLD_NOW 1
    32 #endif
    33 
    34 #ifndef RTLD_GLOBAL
    35 #   define RTLD_GLOBAL 0
    36 #endif
    37 
    38 /*
    39  *---------------------------------------------------------------------------
    40  *
    41  * TclpDlopen --
    42  *
    43  *	Dynamically loads a binary code file into memory and returns
    44  *	a handle to the new code.
    45  *
    46  * Results:
    47  *	A standard Tcl completion code.  If an error occurs, an error
    48  *	message is left in the interp's result. 
    49  *
    50  * Side effects:
    51  *	New code suddenly appears in memory.
    52  *
    53  *---------------------------------------------------------------------------
    54  */
    55 
    56 int
    57 TclpDlopen(interp, pathPtr, loadHandle, unloadProcPtr)
    58     Tcl_Interp *interp;		/* Used for error reporting. */
    59     Tcl_Obj *pathPtr;		/* Name of the file containing the desired
    60 				 * code (UTF-8). */
    61     Tcl_LoadHandle *loadHandle;	/* Filled with token for dynamically loaded
    62 				 * file which will be passed back to 
    63 				 * (*unloadProcPtr)() to unload the file. */
    64     Tcl_FSUnloadFileProc **unloadProcPtr;	
    65 				/* Filled with address of Tcl_FSUnloadFileProc
    66 				 * function which should be used for
    67 				 * this file. */
    68 {
    69     VOID *handle;
    70     CONST char *native;
    71 
    72     /* 
    73      * First try the full path the user gave us.  This is particularly
    74      * important if the cwd is inside a vfs, and we are trying to load
    75      * using a relative path.
    76      */
    77     native = Tcl_FSGetNativePath(pathPtr);
    78     handle = dlopen(native, RTLD_NOW | RTLD_GLOBAL);
    79     if (handle == NULL) {
    80 	/* 
    81 	 * Let the OS loader examine the binary search path for
    82 	 * whatever string the user gave us which hopefully refers
    83 	 * to a file on the binary path
    84 	 */
    85 	Tcl_DString ds;
    86 	char *fileName = Tcl_GetString(pathPtr);
    87 	native = Tcl_UtfToExternalDString(NULL, fileName, -1, &ds);
    88 	handle = dlopen(native, RTLD_NOW | RTLD_GLOBAL);
    89 	Tcl_DStringFree(&ds);
    90     }
    91     
    92     if (handle == NULL) {
    93 	/*
    94 	 * Write the string to a variable first to work around a compiler bug
    95 	 * in the Sun Forte 6 compiler. [Bug 1503729]
    96 	 */
    97 
    98 	CONST char *errorStr = dlerror();
    99 
   100 	Tcl_AppendResult(interp, "couldn't load file \"", 
   101 		Tcl_GetString(pathPtr), "\": ", errorStr, (char *) NULL);
   102 	return TCL_ERROR;
   103     }
   104 
   105     *unloadProcPtr = &TclpUnloadFile;
   106     *loadHandle = (Tcl_LoadHandle)handle;
   107     return TCL_OK;
   108 }
   109 
   110 /*
   111  *----------------------------------------------------------------------
   112  *
   113  * TclpFindSymbol --
   114  *
   115  *	Looks up a symbol, by name, through a handle associated with
   116  *	a previously loaded piece of code (shared library).
   117  *
   118  * Results:
   119  *	Returns a pointer to the function associated with 'symbol' if
   120  *	it is found.  Otherwise returns NULL and may leave an error
   121  *	message in the interp's result.
   122  *
   123  *----------------------------------------------------------------------
   124  */
   125 Tcl_PackageInitProc*
   126 TclpFindSymbol(interp, loadHandle, symbol) 
   127     Tcl_Interp *interp;
   128     Tcl_LoadHandle loadHandle;
   129     CONST char *symbol;
   130 {
   131     CONST char *native;
   132     Tcl_DString newName, ds;
   133     VOID *handle = (VOID*)loadHandle;
   134     Tcl_PackageInitProc *proc;
   135     /* 
   136      * Some platforms still add an underscore to the beginning of symbol
   137      * names.  If we can't find a name without an underscore, try again
   138      * with the underscore.
   139      */
   140 
   141     native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);
   142     proc = (Tcl_PackageInitProc *) dlsym(handle,	/* INTL: Native. */
   143 	    native);	
   144     if (proc == NULL) {
   145 	Tcl_DStringInit(&newName);
   146 	Tcl_DStringAppend(&newName, "_", 1);
   147 	native = Tcl_DStringAppend(&newName, native, -1);
   148 	proc = (Tcl_PackageInitProc *) dlsym(handle, /* INTL: Native. */
   149 		native);
   150 	Tcl_DStringFree(&newName);
   151     }
   152     Tcl_DStringFree(&ds);
   153 
   154     return proc;
   155 }
   156 
   157 /*
   158  *----------------------------------------------------------------------
   159  *
   160  * TclpUnloadFile --
   161  *
   162  *	Unloads a dynamically loaded binary code file from memory.
   163  *	Code pointers in the formerly loaded file are no longer valid
   164  *	after calling this function.
   165  *
   166  * Results:
   167  *	None.
   168  *
   169  * Side effects:
   170  *	Code removed from memory.
   171  *
   172  *----------------------------------------------------------------------
   173  */
   174 
   175 void
   176 TclpUnloadFile(loadHandle)
   177     Tcl_LoadHandle loadHandle;	/* loadHandle returned by a previous call
   178 				 * to TclpDlopen().  The loadHandle is 
   179 				 * a token that represents the loaded 
   180 				 * file. */
   181 {
   182     VOID *handle;
   183 
   184     handle = (VOID *) loadHandle;
   185     dlclose(handle);
   186 }
   187 
   188 /*
   189  *----------------------------------------------------------------------
   190  *
   191  * TclGuessPackageName --
   192  *
   193  *	If the "load" command is invoked without providing a package
   194  *	name, this procedure is invoked to try to figure it out.
   195  *
   196  * Results:
   197  *	Always returns 0 to indicate that we couldn't figure out a
   198  *	package name;  generic code will then try to guess the package
   199  *	from the file name.  A return value of 1 would have meant that
   200  *	we figured out the package name and put it in bufPtr.
   201  *
   202  * Side effects:
   203  *	None.
   204  *
   205  *----------------------------------------------------------------------
   206  */
   207 
   208 int
   209 TclGuessPackageName(fileName, bufPtr)
   210     CONST char *fileName;	/* Name of file containing package (already
   211 				 * translated to local form if needed). */
   212     Tcl_DString *bufPtr;	/* Initialized empty dstring.  Append
   213 				 * package name to this if possible. */
   214 {
   215     return 0;
   216 }