os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclLoad.c
Update contrib.
4 * This file provides the generic portion (those that are the same
5 * on all platforms) of Tcl's dynamic loading facilities.
7 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
8 * Portions Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiaries. All rights reserved.
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * RCS: @(#) $Id: tclLoad.c,v 1.9 2003/02/01 23:37:29 kennykb Exp $
19 * The following structure describes a package that has been loaded
20 * either dynamically (with the "load" command) or statically (as
21 * indicated by a call to TclGetLoadedPackages). All such packages
22 * are linked together into a single list for the process. Packages
23 * are never unloaded, until the application exits, when
24 * TclFinalizeLoad is called, and these structures are freed.
27 typedef struct LoadedPackage {
28 char *fileName; /* Name of the file from which the
29 * package was loaded. An empty string
30 * means the package is loaded statically.
32 char *packageName; /* Name of package prefix for the package,
33 * properly capitalized (first letter UC,
34 * others LC), no "_", as in "Net".
36 Tcl_LoadHandle loadHandle; /* Token for the loaded file which should be
37 * passed to (*unLoadProcPtr)() when the file
38 * is no longer needed. If fileName is NULL,
39 * then this field is irrelevant. */
40 Tcl_PackageInitProc *initProc;
41 /* Initialization procedure to call to
42 * incorporate this package into a trusted
44 Tcl_PackageInitProc *safeInitProc;
45 /* Initialization procedure to call to
46 * incorporate this package into a safe
47 * interpreter (one that will execute
48 * untrusted scripts). NULL means the
49 * package can't be used in unsafe
51 Tcl_FSUnloadFileProc *unLoadProcPtr;
52 /* Procedure to use to unload this package.
53 * If NULL, then we do not attempt to unload
54 * the package. If fileName is NULL, then
55 * this field is irrelevant. */
56 struct LoadedPackage *nextPtr;
57 /* Next in list of all packages loaded into
58 * this application process. NULL means
64 * There is a global list of packages that is anchored at firstPackagePtr.
65 * Access to this list is governed by a mutex.
68 static LoadedPackage *firstPackagePtr = NULL;
69 /* First in list of all packages loaded into
72 TCL_DECLARE_MUTEX(packageMutex)
75 * The following structure represents a particular package that has
76 * been incorporated into a particular interpreter (by calling its
77 * initialization procedure). There is a list of these structures for
78 * each interpreter, with an AssocData value (key "load") for the
79 * interpreter that points to the first package (if any).
82 typedef struct InterpPackage {
83 LoadedPackage *pkgPtr; /* Points to detailed information about
85 struct InterpPackage *nextPtr;
86 /* Next package in this interpreter, or
87 * NULL for end of list. */
91 * Prototypes for procedures that are private to this file:
94 static void LoadCleanupProc _ANSI_ARGS_((ClientData clientData,
98 *----------------------------------------------------------------------
102 * This procedure is invoked to process the "load" Tcl command.
103 * See the user documentation for details on what it does.
106 * A standard Tcl result.
109 * See the user documentation.
111 *----------------------------------------------------------------------
115 Tcl_LoadObjCmd(dummy, interp, objc, objv)
116 ClientData dummy; /* Not used. */
117 Tcl_Interp *interp; /* Current interpreter. */
118 int objc; /* Number of arguments. */
119 Tcl_Obj *CONST objv[]; /* Argument objects. */
122 LoadedPackage *pkgPtr, *defaultPtr;
123 Tcl_DString pkgName, tmp, initName, safeInitName;
124 Tcl_PackageInitProc *initProc, *safeInitProc;
125 InterpPackage *ipFirstPtr, *ipPtr;
126 int code, namesMatch, filesMatch;
127 char *p, *fullFileName, *packageName;
128 Tcl_LoadHandle loadHandle;
129 Tcl_FSUnloadFileProc *unLoadProcPtr = NULL;
133 if ((objc < 2) || (objc > 4)) {
134 Tcl_WrongNumArgs(interp, 1, objv, "fileName ?packageName? ?interp?");
137 if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) {
140 fullFileName = Tcl_GetString(objv[1]);
142 Tcl_DStringInit(&pkgName);
143 Tcl_DStringInit(&initName);
144 Tcl_DStringInit(&safeInitName);
145 Tcl_DStringInit(&tmp);
149 packageName = Tcl_GetString(objv[2]);
150 if (packageName[0] == '\0') {
154 if ((fullFileName[0] == 0) && (packageName == NULL)) {
155 Tcl_SetResult(interp,
156 "must specify either file name or package name",
163 * Figure out which interpreter we're going to load the package into.
169 slaveIntName = Tcl_GetString(objv[3]);
170 target = Tcl_GetSlave(interp, slaveIntName);
171 if (target == NULL) {
177 * Scan through the packages that are currently loaded to see if the
178 * package we want is already loaded. We'll use a loaded package if
179 * it meets any of the following conditions:
180 * - Its name and file match the once we're looking for.
181 * - Its file matches, and we weren't given a name.
182 * - Its name matches, the file name was specified as empty, and there
183 * is only no statically loaded package with the same name.
185 Tcl_MutexLock(&packageMutex);
188 for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
189 if (packageName == NULL) {
192 Tcl_DStringSetLength(&pkgName, 0);
193 Tcl_DStringAppend(&pkgName, packageName, -1);
194 Tcl_DStringSetLength(&tmp, 0);
195 Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1);
196 Tcl_UtfToLower(Tcl_DStringValue(&pkgName));
197 Tcl_UtfToLower(Tcl_DStringValue(&tmp));
198 if (strcmp(Tcl_DStringValue(&tmp),
199 Tcl_DStringValue(&pkgName)) == 0) {
205 Tcl_DStringSetLength(&pkgName, 0);
207 filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0);
208 if (filesMatch && (namesMatch || (packageName == NULL))) {
211 if (namesMatch && (fullFileName[0] == 0)) {
214 if (filesMatch && !namesMatch && (fullFileName[0] != 0)) {
216 * Can't have two different packages loaded from the same
220 Tcl_AppendResult(interp, "file \"", fullFileName,
221 "\" is already loaded for package \"",
222 pkgPtr->packageName, "\"", (char *) NULL);
224 Tcl_MutexUnlock(&packageMutex);
228 Tcl_MutexUnlock(&packageMutex);
229 if (pkgPtr == NULL) {
234 * Scan through the list of packages already loaded in the target
235 * interpreter. If the package we want is already loaded there,
236 * then there's nothing for us to to.
239 if (pkgPtr != NULL) {
240 ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
241 (Tcl_InterpDeleteProc **) NULL);
242 for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
243 if (ipPtr->pkgPtr == pkgPtr) {
250 if (pkgPtr == NULL) {
252 * The desired file isn't currently loaded, so load it. It's an
253 * error if the desired package is a static one.
256 if (fullFileName[0] == 0) {
257 Tcl_AppendResult(interp, "package \"", packageName,
258 "\" isn't loaded statically", (char *) NULL);
264 * Figure out the module name if it wasn't provided explicitly.
267 if (packageName != NULL) {
268 Tcl_DStringAppend(&pkgName, packageName, -1);
272 * Threading note - this call used to be protected by a mutex.
274 retc = TclGuessPackageName(fullFileName, &pkgName);
277 Tcl_Obj *pkgGuessPtr;
282 * The platform-specific code couldn't figure out the
283 * module name. Make a guess by taking the last element
284 * of the file name, stripping off any leading "lib",
285 * and then using all of the alphabetic and underline
286 * characters that follow that.
289 splitPtr = Tcl_FSSplitPath(objv[1], &pElements);
290 Tcl_ListObjIndex(NULL, splitPtr, pElements -1, &pkgGuessPtr);
291 pkgGuess = Tcl_GetString(pkgGuessPtr);
292 if ((pkgGuess[0] == 'l') && (pkgGuess[1] == 'i')
293 && (pkgGuess[2] == 'b')) {
296 for (p = pkgGuess; *p != 0; p += offset) {
297 offset = Tcl_UtfToUniChar(p, &ch);
299 || !(isalpha(UCHAR(ch)) /* INTL: ISO only */
300 || (UCHAR(ch) == '_'))) {
305 Tcl_DecrRefCount(splitPtr);
306 Tcl_AppendResult(interp,
307 "couldn't figure out package name for ",
308 fullFileName, (char *) NULL);
312 Tcl_DStringAppend(&pkgName, pkgGuess, (p - pkgGuess));
313 Tcl_DecrRefCount(splitPtr);
318 * Fix the capitalization in the package name so that the first
319 * character is in caps (or title case) but the others are all
323 Tcl_DStringSetLength(&pkgName,
324 Tcl_UtfToTitle(Tcl_DStringValue(&pkgName)));
327 * Compute the names of the two initialization procedures,
328 * based on the package name.
331 Tcl_DStringAppend(&initName, Tcl_DStringValue(&pkgName), -1);
332 Tcl_DStringAppend(&initName, "_Init", 5);
333 Tcl_DStringAppend(&safeInitName, Tcl_DStringValue(&pkgName), -1);
334 Tcl_DStringAppend(&safeInitName, "_SafeInit", 9);
337 * Call platform-specific code to load the package and find the
338 * two initialization procedures.
341 Tcl_MutexLock(&packageMutex);
342 code = Tcl_FSLoadFile(interp, objv[1], Tcl_DStringValue(&initName),
343 Tcl_DStringValue(&safeInitName), &initProc, &safeInitProc,
344 &loadHandle,&unLoadProcPtr);
345 Tcl_MutexUnlock(&packageMutex);
346 if (code != TCL_OK) {
349 if (initProc == NULL) {
350 Tcl_AppendResult(interp, "couldn't find procedure ",
351 Tcl_DStringValue(&initName), (char *) NULL);
352 if (unLoadProcPtr != NULL) {
353 (*unLoadProcPtr)(loadHandle);
360 * Create a new record to describe this package.
363 pkgPtr = (LoadedPackage *) ckalloc(sizeof(LoadedPackage));
364 pkgPtr->fileName = (char *) ckalloc((unsigned)
365 (strlen(fullFileName) + 1));
366 strcpy(pkgPtr->fileName, fullFileName);
367 pkgPtr->packageName = (char *) ckalloc((unsigned)
368 (Tcl_DStringLength(&pkgName) + 1));
369 strcpy(pkgPtr->packageName, Tcl_DStringValue(&pkgName));
370 pkgPtr->loadHandle = loadHandle;
371 pkgPtr->unLoadProcPtr = unLoadProcPtr;
372 pkgPtr->initProc = initProc;
373 pkgPtr->safeInitProc = safeInitProc;
374 Tcl_MutexLock(&packageMutex);
375 pkgPtr->nextPtr = firstPackagePtr;
376 firstPackagePtr = pkgPtr;
377 Tcl_MutexUnlock(&packageMutex);
381 * Invoke the package's initialization procedure (either the
382 * normal one or the safe one, depending on whether or not the
383 * interpreter is safe).
386 if (Tcl_IsSafe(target)) {
387 if (pkgPtr->safeInitProc != NULL) {
388 code = (*pkgPtr->safeInitProc)(target);
390 Tcl_AppendResult(interp,
391 "can't use package in a safe interpreter: ",
392 "no ", pkgPtr->packageName, "_SafeInit procedure",
398 code = (*pkgPtr->initProc)(target);
402 * Record the fact that the package has been loaded in the
403 * target interpreter.
406 if (code == TCL_OK) {
408 * Refetch ipFirstPtr: loading the package may have introduced
409 * additional static packages at the head of the linked list!
412 ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
413 (Tcl_InterpDeleteProc **) NULL);
414 ipPtr = (InterpPackage *) ckalloc(sizeof(InterpPackage));
415 ipPtr->pkgPtr = pkgPtr;
416 ipPtr->nextPtr = ipFirstPtr;
417 Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc,
420 TclTransferResult(target, code, interp);
424 Tcl_DStringFree(&pkgName);
425 Tcl_DStringFree(&initName);
426 Tcl_DStringFree(&safeInitName);
427 Tcl_DStringFree(&tmp);
432 *----------------------------------------------------------------------
434 * Tcl_StaticPackage --
436 * This procedure is invoked to indicate that a particular
437 * package has been linked statically with an application.
443 * Once this procedure completes, the package becomes loadable
444 * via the "load" command with an empty file name.
446 *----------------------------------------------------------------------
450 Tcl_StaticPackage(interp, pkgName, initProc, safeInitProc)
451 Tcl_Interp *interp; /* If not NULL, it means that the
452 * package has already been loaded
453 * into the given interpreter by
454 * calling the appropriate init proc. */
455 CONST char *pkgName; /* Name of package (must be properly
456 * capitalized: first letter upper
457 * case, others lower case). */
458 Tcl_PackageInitProc *initProc; /* Procedure to call to incorporate
459 * this package into a trusted
461 Tcl_PackageInitProc *safeInitProc; /* Procedure to call to incorporate
462 * this package into a safe interpreter
463 * (one that will execute untrusted
464 * scripts). NULL means the package
465 * can't be used in safe
468 LoadedPackage *pkgPtr;
469 InterpPackage *ipPtr, *ipFirstPtr;
472 * Check to see if someone else has already reported this package as
473 * statically loaded in the process.
476 Tcl_MutexLock(&packageMutex);
477 for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
478 if ((pkgPtr->initProc == initProc)
479 && (pkgPtr->safeInitProc == safeInitProc)
480 && (strcmp(pkgPtr->packageName, pkgName) == 0)) {
484 Tcl_MutexUnlock(&packageMutex);
487 * If the package is not yet recorded as being loaded statically,
488 * add it to the list now.
491 if ( pkgPtr == NULL ) {
492 pkgPtr = (LoadedPackage *) ckalloc(sizeof(LoadedPackage));
493 pkgPtr->fileName = (char *) ckalloc((unsigned) 1);
494 pkgPtr->fileName[0] = 0;
495 pkgPtr->packageName = (char *) ckalloc((unsigned)
496 (strlen(pkgName) + 1));
497 strcpy(pkgPtr->packageName, pkgName);
498 pkgPtr->loadHandle = NULL;
499 pkgPtr->initProc = initProc;
500 pkgPtr->safeInitProc = safeInitProc;
501 Tcl_MutexLock(&packageMutex);
502 pkgPtr->nextPtr = firstPackagePtr;
503 firstPackagePtr = pkgPtr;
504 Tcl_MutexUnlock(&packageMutex);
507 if (interp != NULL) {
510 * If we're loading the package into an interpreter,
511 * determine whether it's already loaded.
514 ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(interp, "tclLoad",
515 (Tcl_InterpDeleteProc **) NULL);
516 for ( ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr ) {
517 if ( ipPtr->pkgPtr == pkgPtr ) {
523 * Package isn't loade in the current interp yet. Mark it as
527 ipPtr = (InterpPackage *) ckalloc(sizeof(InterpPackage));
528 ipPtr->pkgPtr = pkgPtr;
529 ipPtr->nextPtr = ipFirstPtr;
530 Tcl_SetAssocData(interp, "tclLoad", LoadCleanupProc,
536 *----------------------------------------------------------------------
538 * TclGetLoadedPackages --
540 * This procedure returns information about all of the files
541 * that are loaded (either in a particular intepreter, or
542 * for all interpreters).
545 * The return value is a standard Tcl completion code. If
546 * successful, a list of lists is placed in the interp's result.
547 * Each sublist corresponds to one loaded file; its first
548 * element is the name of the file (or an empty string for
549 * something that's statically loaded) and the second element
550 * is the name of the package in that file.
555 *----------------------------------------------------------------------
559 TclGetLoadedPackages(interp, targetName)
560 Tcl_Interp *interp; /* Interpreter in which to return
561 * information or error message. */
562 char *targetName; /* Name of target interpreter or NULL.
563 * If NULL, return info about all interps;
564 * otherwise, just return info about this
568 LoadedPackage *pkgPtr;
569 InterpPackage *ipPtr;
572 if (targetName == NULL) {
574 * Return information about all of the available packages.
578 Tcl_MutexLock(&packageMutex);
579 for (pkgPtr = firstPackagePtr; pkgPtr != NULL;
580 pkgPtr = pkgPtr->nextPtr) {
581 Tcl_AppendResult(interp, prefix, (char *) NULL);
582 Tcl_AppendElement(interp, pkgPtr->fileName);
583 Tcl_AppendElement(interp, pkgPtr->packageName);
584 Tcl_AppendResult(interp, "}", (char *) NULL);
587 Tcl_MutexUnlock(&packageMutex);
592 * Return information about only the packages that are loaded in
593 * a given interpreter.
596 target = Tcl_GetSlave(interp, targetName);
597 if (target == NULL) {
600 ipPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
601 (Tcl_InterpDeleteProc **) NULL);
603 for ( ; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
604 pkgPtr = ipPtr->pkgPtr;
605 Tcl_AppendResult(interp, prefix, (char *) NULL);
606 Tcl_AppendElement(interp, pkgPtr->fileName);
607 Tcl_AppendElement(interp, pkgPtr->packageName);
608 Tcl_AppendResult(interp, "}", (char *) NULL);
615 *----------------------------------------------------------------------
619 * This procedure is called to delete all of the InterpPackage
620 * structures for an interpreter when the interpreter is deleted.
621 * It gets invoked via the Tcl AssocData mechanism.
627 * Storage for all of the InterpPackage procedures for interp
630 *----------------------------------------------------------------------
634 LoadCleanupProc(clientData, interp)
635 ClientData clientData; /* Pointer to first InterpPackage structure
637 Tcl_Interp *interp; /* Interpreter that is being deleted. */
639 InterpPackage *ipPtr, *nextPtr;
641 ipPtr = (InterpPackage *) clientData;
642 while (ipPtr != NULL) {
643 nextPtr = ipPtr->nextPtr;
644 ckfree((char *) ipPtr);
650 *----------------------------------------------------------------------
654 * This procedure is invoked just before the application exits.
655 * It frees all of the LoadedPackage structures.
663 *----------------------------------------------------------------------
669 LoadedPackage *pkgPtr;
672 * No synchronization here because there should just be
673 * one thread alive at this point. Logically,
674 * packageMutex should be grabbed at this point, but
675 * the Mutexes get finalized before the call to this routine.
676 * The only subsystem left alive at this point is the
680 while (firstPackagePtr != NULL) {
681 pkgPtr = firstPackagePtr;
682 firstPackagePtr = pkgPtr->nextPtr;
683 #if defined(TCL_UNLOAD_DLLS) || defined(__WIN32__)
685 * Some Unix dlls are poorly behaved - registering things like
686 * atexit calls that can't be unregistered. If you unload
687 * such dlls, you get a core on exit because it wants to
688 * call a function in the dll after it's been unloaded.
690 if (pkgPtr->fileName[0] != '\0') {
691 Tcl_FSUnloadFileProc *unLoadProcPtr = pkgPtr->unLoadProcPtr;
692 if (unLoadProcPtr != NULL) {
693 (*unLoadProcPtr)(pkgPtr->loadHandle);
697 ckfree(pkgPtr->fileName);
698 ckfree(pkgPtr->packageName);
699 ckfree((char *) pkgPtr);