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