OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [generic/] [tclLoad.c] - Diff between revs 578 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 578 Rev 1765
/*
/*
 * tclLoad.c --
 * tclLoad.c --
 *
 *
 *      This file provides the generic portion (those that are the same
 *      This file provides the generic portion (those that are the same
 *      on all platforms) of Tcl's dynamic loading facilities.
 *      on all platforms) of Tcl's dynamic loading facilities.
 *
 *
 * Copyright (c) 1995 Sun Microsystems, Inc.
 * Copyright (c) 1995 Sun Microsystems, Inc.
 *
 *
 * See the file "license.terms" for information on usage and redistribution
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 *
 * RCS: @(#) $Id: tclLoad.c,v 1.1.1.1 2002-01-16 10:25:28 markom Exp $
 * RCS: @(#) $Id: tclLoad.c,v 1.1.1.1 2002-01-16 10:25:28 markom Exp $
 */
 */
 
 
#include "tclInt.h"
#include "tclInt.h"
 
 
/*
/*
 * The following structure describes a package that has been loaded
 * The following structure describes a package that has been loaded
 * either dynamically (with the "load" command) or statically (as
 * either dynamically (with the "load" command) or statically (as
 * indicated by a call to Tcl_PackageLoaded).  All such packages
 * indicated by a call to Tcl_PackageLoaded).  All such packages
 * are linked together into a single list for the process.  Packages
 * are linked together into a single list for the process.  Packages
 * are never unloaded, so these structures are never freed.
 * are never unloaded, so these structures are never freed.
 */
 */
 
 
typedef struct LoadedPackage {
typedef struct LoadedPackage {
    char *fileName;             /* Name of the file from which the
    char *fileName;             /* Name of the file from which the
                                 * package was loaded.  An empty string
                                 * package was loaded.  An empty string
                                 * means the package is loaded statically.
                                 * means the package is loaded statically.
                                 * Malloc-ed. */
                                 * Malloc-ed. */
    char *packageName;          /* Name of package prefix for the package,
    char *packageName;          /* Name of package prefix for the package,
                                 * properly capitalized (first letter UC,
                                 * properly capitalized (first letter UC,
                                 * others LC), no "_", as in "Net".
                                 * others LC), no "_", as in "Net".
                                 * Malloc-ed. */
                                 * Malloc-ed. */
    Tcl_PackageInitProc *initProc;
    Tcl_PackageInitProc *initProc;
                                /* Initialization procedure to call to
                                /* Initialization procedure to call to
                                 * incorporate this package into a trusted
                                 * incorporate this package into a trusted
                                 * interpreter. */
                                 * interpreter. */
    Tcl_PackageInitProc *safeInitProc;
    Tcl_PackageInitProc *safeInitProc;
                                /* Initialization procedure to call to
                                /* Initialization procedure to call to
                                 * incorporate this package into a safe
                                 * incorporate this package into a safe
                                 * interpreter (one that will execute
                                 * interpreter (one that will execute
                                 * untrusted scripts).   NULL means the
                                 * untrusted scripts).   NULL means the
                                 * package can't be used in unsafe
                                 * package can't be used in unsafe
                                 * interpreters. */
                                 * interpreters. */
    struct LoadedPackage *nextPtr;
    struct LoadedPackage *nextPtr;
                                /* Next in list of all packages loaded into
                                /* Next in list of all packages loaded into
                                 * this application process.  NULL means
                                 * this application process.  NULL means
                                 * end of list. */
                                 * end of list. */
} LoadedPackage;
} LoadedPackage;
 
 
static LoadedPackage *firstPackagePtr = NULL;
static LoadedPackage *firstPackagePtr = NULL;
                                /* First in list of all packages loaded into
                                /* First in list of all packages loaded into
                                 * this process. */
                                 * this process. */
 
 
/*
/*
 * The following structure represents a particular package that has
 * The following structure represents a particular package that has
 * been incorporated into a particular interpreter (by calling its
 * been incorporated into a particular interpreter (by calling its
 * initialization procedure).  There is a list of these structures for
 * initialization procedure).  There is a list of these structures for
 * each interpreter, with an AssocData value (key "load") for the
 * each interpreter, with an AssocData value (key "load") for the
 * interpreter that points to the first package (if any).
 * interpreter that points to the first package (if any).
 */
 */
 
 
typedef struct InterpPackage {
typedef struct InterpPackage {
    LoadedPackage *pkgPtr;      /* Points to detailed information about
    LoadedPackage *pkgPtr;      /* Points to detailed information about
                                 * package. */
                                 * package. */
    struct InterpPackage *nextPtr;
    struct InterpPackage *nextPtr;
                                /* Next package in this interpreter, or
                                /* Next package in this interpreter, or
                                 * NULL for end of list. */
                                 * NULL for end of list. */
} InterpPackage;
} InterpPackage;
 
 
/*
/*
 * Prototypes for procedures that are private to this file:
 * Prototypes for procedures that are private to this file:
 */
 */
 
 
static void             LoadCleanupProc _ANSI_ARGS_((ClientData clientData,
static void             LoadCleanupProc _ANSI_ARGS_((ClientData clientData,
                            Tcl_Interp *interp));
                            Tcl_Interp *interp));
static void             LoadExitProc _ANSI_ARGS_((ClientData clientData));
static void             LoadExitProc _ANSI_ARGS_((ClientData clientData));


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * Tcl_LoadCmd --
 * Tcl_LoadCmd --
 *
 *
 *      This procedure is invoked to process the "load" Tcl command.
 *      This procedure is invoked to process the "load" Tcl command.
 *      See the user documentation for details on what it does.
 *      See the user documentation for details on what it does.
 *
 *
 * Results:
 * Results:
 *      A standard Tcl result.
 *      A standard Tcl result.
 *
 *
 * Side effects:
 * Side effects:
 *      See the user documentation.
 *      See the user documentation.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
int
int
Tcl_LoadCmd(dummy, interp, argc, argv)
Tcl_LoadCmd(dummy, interp, argc, argv)
    ClientData dummy;                   /* Not used. */
    ClientData dummy;                   /* Not used. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    Tcl_Interp *interp;                 /* Current interpreter. */
    int argc;                           /* Number of arguments. */
    int argc;                           /* Number of arguments. */
    char **argv;                        /* Argument strings. */
    char **argv;                        /* Argument strings. */
{
{
    Tcl_Interp *target;
    Tcl_Interp *target;
    LoadedPackage *pkgPtr, *defaultPtr;
    LoadedPackage *pkgPtr, *defaultPtr;
    Tcl_DString pkgName, initName, safeInitName, fileName;
    Tcl_DString pkgName, initName, safeInitName, fileName;
    Tcl_PackageInitProc *initProc, *safeInitProc;
    Tcl_PackageInitProc *initProc, *safeInitProc;
    InterpPackage *ipFirstPtr, *ipPtr;
    InterpPackage *ipFirstPtr, *ipPtr;
    int code, c, gotPkgName, namesMatch, filesMatch;
    int code, c, gotPkgName, namesMatch, filesMatch;
    char *p, *fullFileName, *p1, *p2;
    char *p, *fullFileName, *p1, *p2;
 
 
    if ((argc < 2) || (argc > 4)) {
    if ((argc < 2) || (argc > 4)) {
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                " fileName ?packageName? ?interp?\"", (char *) NULL);
                " fileName ?packageName? ?interp?\"", (char *) NULL);
        return TCL_ERROR;
        return TCL_ERROR;
    }
    }
    fullFileName = Tcl_TranslateFileName(interp, argv[1], &fileName);
    fullFileName = Tcl_TranslateFileName(interp, argv[1], &fileName);
    if (fullFileName == NULL) {
    if (fullFileName == NULL) {
        return TCL_ERROR;
        return TCL_ERROR;
    }
    }
    Tcl_DStringInit(&pkgName);
    Tcl_DStringInit(&pkgName);
    Tcl_DStringInit(&initName);
    Tcl_DStringInit(&initName);
    Tcl_DStringInit(&safeInitName);
    Tcl_DStringInit(&safeInitName);
    if ((argc >= 3) && (argv[2][0] != 0)) {
    if ((argc >= 3) && (argv[2][0] != 0)) {
        gotPkgName = 1;
        gotPkgName = 1;
    } else {
    } else {
        gotPkgName = 0;
        gotPkgName = 0;
    }
    }
    if ((fullFileName[0] == 0) && !gotPkgName) {
    if ((fullFileName[0] == 0) && !gotPkgName) {
        Tcl_SetResult(interp,
        Tcl_SetResult(interp,
                "must specify either file name or package name",
                "must specify either file name or package name",
                TCL_STATIC);
                TCL_STATIC);
        code = TCL_ERROR;
        code = TCL_ERROR;
        goto done;
        goto done;
    }
    }
 
 
    /*
    /*
     * Figure out which interpreter we're going to load the package into.
     * Figure out which interpreter we're going to load the package into.
     */
     */
 
 
    target = interp;
    target = interp;
    if (argc == 4) {
    if (argc == 4) {
        target = Tcl_GetSlave(interp, argv[3]);
        target = Tcl_GetSlave(interp, argv[3]);
        if (target == NULL) {
        if (target == NULL) {
            Tcl_AppendResult(interp, "couldn't find slave interpreter named \"",
            Tcl_AppendResult(interp, "couldn't find slave interpreter named \"",
                    argv[3], "\"", (char *) NULL);
                    argv[3], "\"", (char *) NULL);
            return TCL_ERROR;
            return TCL_ERROR;
        }
        }
    }
    }
 
 
    /*
    /*
     * Scan through the packages that are currently loaded to see if the
     * Scan through the packages that are currently loaded to see if the
     * package we want is already loaded.  We'll use a loaded package if
     * package we want is already loaded.  We'll use a loaded package if
     * it meets any of the following conditions:
     * it meets any of the following conditions:
     *  - Its name and file match the once we're looking for.
     *  - Its name and file match the once we're looking for.
     *  - Its file matches, and we weren't given a name.
     *  - Its file matches, and we weren't given a name.
     *  - Its name matches, the file name was specified as empty, and there
     *  - Its name matches, the file name was specified as empty, and there
     *    is only no statically loaded package with the same name.
     *    is only no statically loaded package with the same name.
     */
     */
 
 
    defaultPtr = NULL;
    defaultPtr = NULL;
    for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
    for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
        if (!gotPkgName) {
        if (!gotPkgName) {
            namesMatch = 0;
            namesMatch = 0;
        } else {
        } else {
            namesMatch = 1;
            namesMatch = 1;
            for (p1 = argv[2], p2 = pkgPtr->packageName; ; p1++, p2++) {
            for (p1 = argv[2], p2 = pkgPtr->packageName; ; p1++, p2++) {
                if ((isupper(UCHAR(*p1)) ? tolower(UCHAR(*p1)) : *p1)
                if ((isupper(UCHAR(*p1)) ? tolower(UCHAR(*p1)) : *p1)
                        != (isupper(UCHAR(*p2)) ? tolower(UCHAR(*p2)) : *p2)) {
                        != (isupper(UCHAR(*p2)) ? tolower(UCHAR(*p2)) : *p2)) {
                    namesMatch = 0;
                    namesMatch = 0;
                    break;
                    break;
                }
                }
                if (*p1 == 0) {
                if (*p1 == 0) {
                    break;
                    break;
                }
                }
            }
            }
        }
        }
        filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0);
        filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0);
        if (filesMatch && (namesMatch || !gotPkgName)) {
        if (filesMatch && (namesMatch || !gotPkgName)) {
            break;
            break;
        }
        }
        if (namesMatch && (fullFileName[0] == 0)) {
        if (namesMatch && (fullFileName[0] == 0)) {
            defaultPtr = pkgPtr;
            defaultPtr = pkgPtr;
        }
        }
        if (filesMatch && !namesMatch && (fullFileName[0] != 0)) {
        if (filesMatch && !namesMatch && (fullFileName[0] != 0)) {
            /*
            /*
             * Can't have two different packages loaded from the same
             * Can't have two different packages loaded from the same
             * file.
             * file.
             */
             */
 
 
            Tcl_AppendResult(interp, "file \"", fullFileName,
            Tcl_AppendResult(interp, "file \"", fullFileName,
                    "\" is already loaded for package \"",
                    "\" is already loaded for package \"",
                    pkgPtr->packageName, "\"", (char *) NULL);
                    pkgPtr->packageName, "\"", (char *) NULL);
            code = TCL_ERROR;
            code = TCL_ERROR;
            goto done;
            goto done;
        }
        }
    }
    }
    if (pkgPtr == NULL) {
    if (pkgPtr == NULL) {
        pkgPtr = defaultPtr;
        pkgPtr = defaultPtr;
    }
    }
 
 
    /*
    /*
     * Scan through the list of packages already loaded in the target
     * Scan through the list of packages already loaded in the target
     * interpreter.  If the package we want is already loaded there,
     * interpreter.  If the package we want is already loaded there,
     * then there's nothing for us to to.
     * then there's nothing for us to to.
     */
     */
 
 
    if (pkgPtr != NULL) {
    if (pkgPtr != NULL) {
        ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
        ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
                (Tcl_InterpDeleteProc **) NULL);
                (Tcl_InterpDeleteProc **) NULL);
        for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
        for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
            if (ipPtr->pkgPtr == pkgPtr) {
            if (ipPtr->pkgPtr == pkgPtr) {
                code = TCL_OK;
                code = TCL_OK;
                goto done;
                goto done;
            }
            }
        }
        }
    }
    }
 
 
    if (pkgPtr == NULL) {
    if (pkgPtr == NULL) {
        /*
        /*
         * The desired file isn't currently loaded, so load it.  It's an
         * The desired file isn't currently loaded, so load it.  It's an
         * error if the desired package is a static one.
         * error if the desired package is a static one.
         */
         */
 
 
        if (fullFileName[0] == 0) {
        if (fullFileName[0] == 0) {
            Tcl_AppendResult(interp, "package \"", argv[2],
            Tcl_AppendResult(interp, "package \"", argv[2],
                    "\" isn't loaded statically", (char *) NULL);
                    "\" isn't loaded statically", (char *) NULL);
            code = TCL_ERROR;
            code = TCL_ERROR;
            goto done;
            goto done;
        }
        }
 
 
        /*
        /*
         * Figure out the module name if it wasn't provided explicitly.
         * Figure out the module name if it wasn't provided explicitly.
         */
         */
 
 
        if (gotPkgName) {
        if (gotPkgName) {
            Tcl_DStringAppend(&pkgName, argv[2], -1);
            Tcl_DStringAppend(&pkgName, argv[2], -1);
        } else {
        } else {
            if (!TclGuessPackageName(fullFileName, &pkgName)) {
            if (!TclGuessPackageName(fullFileName, &pkgName)) {
                int pargc;
                int pargc;
                char **pargv, *pkgGuess;
                char **pargv, *pkgGuess;
 
 
                /*
                /*
                 * The platform-specific code couldn't figure out the
                 * The platform-specific code couldn't figure out the
                 * module name.  Make a guess by taking the last element
                 * module name.  Make a guess by taking the last element
                 * of the file name, stripping off any leading "lib",
                 * of the file name, stripping off any leading "lib",
                 * and then using all of the alphabetic and underline
                 * and then using all of the alphabetic and underline
                 * characters that follow that.
                 * characters that follow that.
                 */
                 */
 
 
                Tcl_SplitPath(fullFileName, &pargc, &pargv);
                Tcl_SplitPath(fullFileName, &pargc, &pargv);
                pkgGuess = pargv[pargc-1];
                pkgGuess = pargv[pargc-1];
                if ((pkgGuess[0] == 'l') && (pkgGuess[1] == 'i')
                if ((pkgGuess[0] == 'l') && (pkgGuess[1] == 'i')
                        && (pkgGuess[2] == 'b')) {
                        && (pkgGuess[2] == 'b')) {
                    pkgGuess += 3;
                    pkgGuess += 3;
                }
                }
                for (p = pkgGuess; isalpha(UCHAR(*p)) || (*p == '_'); p++) {
                for (p = pkgGuess; isalpha(UCHAR(*p)) || (*p == '_'); p++) {
                    /* Empty loop body. */
                    /* Empty loop body. */
                }
                }
                if (p == pkgGuess) {
                if (p == pkgGuess) {
                    ckfree((char *)pargv);
                    ckfree((char *)pargv);
                    Tcl_AppendResult(interp,
                    Tcl_AppendResult(interp,
                            "couldn't figure out package name for ",
                            "couldn't figure out package name for ",
                            fullFileName, (char *) NULL);
                            fullFileName, (char *) NULL);
                    code = TCL_ERROR;
                    code = TCL_ERROR;
                    goto done;
                    goto done;
                }
                }
                Tcl_DStringAppend(&pkgName, pkgGuess, (p - pkgGuess));
                Tcl_DStringAppend(&pkgName, pkgGuess, (p - pkgGuess));
                ckfree((char *)pargv);
                ckfree((char *)pargv);
            }
            }
        }
        }
 
 
        /*
        /*
         * Fix the capitalization in the package name so that the first
         * Fix the capitalization in the package name so that the first
         * character is in caps but the others are all lower-case.
         * character is in caps but the others are all lower-case.
         */
         */
 
 
        p = Tcl_DStringValue(&pkgName);
        p = Tcl_DStringValue(&pkgName);
        c = UCHAR(*p);
        c = UCHAR(*p);
        if (c != 0) {
        if (c != 0) {
            if (islower(c)) {
            if (islower(c)) {
                *p = (char) toupper(c);
                *p = (char) toupper(c);
            }
            }
            p++;
            p++;
            while (1) {
            while (1) {
                c = UCHAR(*p);
                c = UCHAR(*p);
                if (c == 0) {
                if (c == 0) {
                    break;
                    break;
                }
                }
                if (isupper(c)) {
                if (isupper(c)) {
                    *p = (char) tolower(c);
                    *p = (char) tolower(c);
                }
                }
                p++;
                p++;
            }
            }
        }
        }
 
 
        /*
        /*
         * Compute the names of the two initialization procedures,
         * Compute the names of the two initialization procedures,
         * based on the package name.
         * based on the package name.
         */
         */
 
 
        Tcl_DStringAppend(&initName, Tcl_DStringValue(&pkgName), -1);
        Tcl_DStringAppend(&initName, Tcl_DStringValue(&pkgName), -1);
        Tcl_DStringAppend(&initName, "_Init", 5);
        Tcl_DStringAppend(&initName, "_Init", 5);
        Tcl_DStringAppend(&safeInitName, Tcl_DStringValue(&pkgName), -1);
        Tcl_DStringAppend(&safeInitName, Tcl_DStringValue(&pkgName), -1);
        Tcl_DStringAppend(&safeInitName, "_SafeInit", 9);
        Tcl_DStringAppend(&safeInitName, "_SafeInit", 9);
 
 
        /*
        /*
         * Call platform-specific code to load the package and find the
         * Call platform-specific code to load the package and find the
         * two initialization procedures.
         * two initialization procedures.
         */
         */
 
 
        code = TclLoadFile(interp, fullFileName, Tcl_DStringValue(&initName),
        code = TclLoadFile(interp, fullFileName, Tcl_DStringValue(&initName),
                Tcl_DStringValue(&safeInitName), &initProc, &safeInitProc);
                Tcl_DStringValue(&safeInitName), &initProc, &safeInitProc);
        if (code != TCL_OK) {
        if (code != TCL_OK) {
            goto done;
            goto done;
        }
        }
        if (initProc  == NULL) {
        if (initProc  == NULL) {
            Tcl_AppendResult(interp, "couldn't find procedure ",
            Tcl_AppendResult(interp, "couldn't find procedure ",
                    Tcl_DStringValue(&initName), (char *) NULL);
                    Tcl_DStringValue(&initName), (char *) NULL);
            code = TCL_ERROR;
            code = TCL_ERROR;
            goto done;
            goto done;
        }
        }
 
 
        /*
        /*
         * Create a new record to describe this package.
         * Create a new record to describe this package.
         */
         */
 
 
        if (firstPackagePtr == NULL) {
        if (firstPackagePtr == NULL) {
            Tcl_CreateExitHandler(LoadExitProc, (ClientData) NULL);
            Tcl_CreateExitHandler(LoadExitProc, (ClientData) NULL);
        }
        }
        pkgPtr = (LoadedPackage *) ckalloc(sizeof(LoadedPackage));
        pkgPtr = (LoadedPackage *) ckalloc(sizeof(LoadedPackage));
        pkgPtr->fileName = (char *) ckalloc((unsigned)
        pkgPtr->fileName = (char *) ckalloc((unsigned)
                (strlen(fullFileName) + 1));
                (strlen(fullFileName) + 1));
        strcpy(pkgPtr->fileName, fullFileName);
        strcpy(pkgPtr->fileName, fullFileName);
        pkgPtr->packageName = (char *) ckalloc((unsigned)
        pkgPtr->packageName = (char *) ckalloc((unsigned)
                (Tcl_DStringLength(&pkgName) + 1));
                (Tcl_DStringLength(&pkgName) + 1));
        strcpy(pkgPtr->packageName, Tcl_DStringValue(&pkgName));
        strcpy(pkgPtr->packageName, Tcl_DStringValue(&pkgName));
        pkgPtr->initProc = initProc;
        pkgPtr->initProc = initProc;
        pkgPtr->safeInitProc = safeInitProc;
        pkgPtr->safeInitProc = safeInitProc;
        pkgPtr->nextPtr = firstPackagePtr;
        pkgPtr->nextPtr = firstPackagePtr;
        firstPackagePtr = pkgPtr;
        firstPackagePtr = pkgPtr;
    }
    }
 
 
    /*
    /*
     * Invoke the package's initialization procedure (either the
     * Invoke the package's initialization procedure (either the
     * normal one or the safe one, depending on whether or not the
     * normal one or the safe one, depending on whether or not the
     * interpreter is safe).
     * interpreter is safe).
     */
     */
 
 
    if (Tcl_IsSafe(target)) {
    if (Tcl_IsSafe(target)) {
        if (pkgPtr->safeInitProc != NULL) {
        if (pkgPtr->safeInitProc != NULL) {
            code = (*pkgPtr->safeInitProc)(target);
            code = (*pkgPtr->safeInitProc)(target);
        } else {
        } else {
            Tcl_AppendResult(interp,
            Tcl_AppendResult(interp,
                    "can't use package in a safe interpreter: ",
                    "can't use package in a safe interpreter: ",
                    "no ", pkgPtr->packageName, "_SafeInit procedure",
                    "no ", pkgPtr->packageName, "_SafeInit procedure",
                    (char *) NULL);
                    (char *) NULL);
            code = TCL_ERROR;
            code = TCL_ERROR;
            goto done;
            goto done;
        }
        }
    } else {
    } else {
        code = (*pkgPtr->initProc)(target);
        code = (*pkgPtr->initProc)(target);
    }
    }
    if ((code == TCL_ERROR) && (target != interp)) {
    if ((code == TCL_ERROR) && (target != interp)) {
        /*
        /*
         * An error occurred, so transfer error information from the
         * An error occurred, so transfer error information from the
         * destination interpreter back to our interpreter.  Must clear
         * destination interpreter back to our interpreter.  Must clear
         * interp's result before calling Tcl_AddErrorInfo, since
         * interp's result before calling Tcl_AddErrorInfo, since
         * Tcl_AddErrorInfo will store the interp's result in errorInfo
         * Tcl_AddErrorInfo will store the interp's result in errorInfo
         * before appending target's $errorInfo;  we've already got
         * before appending target's $errorInfo;  we've already got
         * everything we need in target's $errorInfo.
         * everything we need in target's $errorInfo.
         */
         */
 
 
        /*
        /*
         * It is (abusively) assumed that errorInfo and errorCode vars exists.
         * It is (abusively) assumed that errorInfo and errorCode vars exists.
         * we changed SetVar2 to accept NULL values to avoid crashes. --dl
         * we changed SetVar2 to accept NULL values to avoid crashes. --dl
         */
         */
        Tcl_ResetResult(interp);
        Tcl_ResetResult(interp);
        Tcl_AddErrorInfo(interp, Tcl_GetVar2(target,
        Tcl_AddErrorInfo(interp, Tcl_GetVar2(target,
                "errorInfo", (char *) NULL, TCL_GLOBAL_ONLY));
                "errorInfo", (char *) NULL, TCL_GLOBAL_ONLY));
        Tcl_SetVar2(interp, "errorCode", (char *) NULL,
        Tcl_SetVar2(interp, "errorCode", (char *) NULL,
                Tcl_GetVar2(target, "errorCode", (char *) NULL,
                Tcl_GetVar2(target, "errorCode", (char *) NULL,
                TCL_GLOBAL_ONLY), TCL_GLOBAL_ONLY);
                TCL_GLOBAL_ONLY), TCL_GLOBAL_ONLY);
        Tcl_SetResult(interp, target->result, TCL_VOLATILE);
        Tcl_SetResult(interp, target->result, TCL_VOLATILE);
    }
    }
 
 
    /*
    /*
     * Record the fact that the package has been loaded in the
     * Record the fact that the package has been loaded in the
     * target interpreter.
     * target interpreter.
     */
     */
 
 
    if (code == TCL_OK) {
    if (code == TCL_OK) {
        /*
        /*
         * Refetch ipFirstPtr: loading the package may have introduced
         * Refetch ipFirstPtr: loading the package may have introduced
         * additional static packages at the head of the linked list!
         * additional static packages at the head of the linked list!
         */
         */
 
 
        ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
        ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
                (Tcl_InterpDeleteProc **) NULL);
                (Tcl_InterpDeleteProc **) NULL);
        ipPtr = (InterpPackage *) ckalloc(sizeof(InterpPackage));
        ipPtr = (InterpPackage *) ckalloc(sizeof(InterpPackage));
        ipPtr->pkgPtr = pkgPtr;
        ipPtr->pkgPtr = pkgPtr;
        ipPtr->nextPtr = ipFirstPtr;
        ipPtr->nextPtr = ipFirstPtr;
        Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc,
        Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc,
                (ClientData) ipPtr);
                (ClientData) ipPtr);
    }
    }
 
 
    done:
    done:
    Tcl_DStringFree(&pkgName);
    Tcl_DStringFree(&pkgName);
    Tcl_DStringFree(&initName);
    Tcl_DStringFree(&initName);
    Tcl_DStringFree(&safeInitName);
    Tcl_DStringFree(&safeInitName);
    Tcl_DStringFree(&fileName);
    Tcl_DStringFree(&fileName);
    return code;
    return code;
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * Tcl_StaticPackage --
 * Tcl_StaticPackage --
 *
 *
 *      This procedure is invoked to indicate that a particular
 *      This procedure is invoked to indicate that a particular
 *      package has been linked statically with an application.
 *      package has been linked statically with an application.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Once this procedure completes, the package becomes loadable
 *      Once this procedure completes, the package becomes loadable
 *      via the "load" command with an empty file name.
 *      via the "load" command with an empty file name.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
void
void
Tcl_StaticPackage(interp, pkgName, initProc, safeInitProc)
Tcl_StaticPackage(interp, pkgName, initProc, safeInitProc)
    Tcl_Interp *interp;                 /* If not NULL, it means that the
    Tcl_Interp *interp;                 /* If not NULL, it means that the
                                         * package has already been loaded
                                         * package has already been loaded
                                         * into the given interpreter by
                                         * into the given interpreter by
                                         * calling the appropriate init proc. */
                                         * calling the appropriate init proc. */
    char *pkgName;                      /* Name of package (must be properly
    char *pkgName;                      /* Name of package (must be properly
                                         * capitalized: first letter upper
                                         * capitalized: first letter upper
                                         * case, others lower case). */
                                         * case, others lower case). */
    Tcl_PackageInitProc *initProc;      /* Procedure to call to incorporate
    Tcl_PackageInitProc *initProc;      /* Procedure to call to incorporate
                                         * this package into a trusted
                                         * this package into a trusted
                                         * interpreter. */
                                         * interpreter. */
    Tcl_PackageInitProc *safeInitProc;  /* Procedure to call to incorporate
    Tcl_PackageInitProc *safeInitProc;  /* Procedure to call to incorporate
                                         * this package into a safe interpreter
                                         * this package into a safe interpreter
                                         * (one that will execute untrusted
                                         * (one that will execute untrusted
                                         * scripts).   NULL means the package
                                         * scripts).   NULL means the package
                                         * can't be used in safe
                                         * can't be used in safe
                                         * interpreters. */
                                         * interpreters. */
{
{
    LoadedPackage *pkgPtr;
    LoadedPackage *pkgPtr;
    InterpPackage *ipPtr, *ipFirstPtr;
    InterpPackage *ipPtr, *ipFirstPtr;
 
 
    /*
    /*
     * Check to see if someone else has already reported this package as
     * Check to see if someone else has already reported this package as
     * statically loaded.  If this call is redundant then just return.
     * statically loaded.  If this call is redundant then just return.
     */
     */
 
 
    for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
    for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
        if ((pkgPtr->initProc == initProc)
        if ((pkgPtr->initProc == initProc)
                && (pkgPtr->safeInitProc == safeInitProc)
                && (pkgPtr->safeInitProc == safeInitProc)
                && (strcmp(pkgPtr->packageName, pkgName) == 0)) {
                && (strcmp(pkgPtr->packageName, pkgName) == 0)) {
            return;
            return;
        }
        }
    }
    }
 
 
    if (firstPackagePtr == NULL) {
    if (firstPackagePtr == NULL) {
        Tcl_CreateExitHandler(LoadExitProc, (ClientData) NULL);
        Tcl_CreateExitHandler(LoadExitProc, (ClientData) NULL);
    }
    }
    pkgPtr = (LoadedPackage *) ckalloc(sizeof(LoadedPackage));
    pkgPtr = (LoadedPackage *) ckalloc(sizeof(LoadedPackage));
    pkgPtr->fileName = (char *) ckalloc((unsigned) 1);
    pkgPtr->fileName = (char *) ckalloc((unsigned) 1);
    pkgPtr->fileName[0] = 0;
    pkgPtr->fileName[0] = 0;
    pkgPtr->packageName = (char *) ckalloc((unsigned)
    pkgPtr->packageName = (char *) ckalloc((unsigned)
            (strlen(pkgName) + 1));
            (strlen(pkgName) + 1));
    strcpy(pkgPtr->packageName, pkgName);
    strcpy(pkgPtr->packageName, pkgName);
    pkgPtr->initProc = initProc;
    pkgPtr->initProc = initProc;
    pkgPtr->safeInitProc = safeInitProc;
    pkgPtr->safeInitProc = safeInitProc;
    pkgPtr->nextPtr = firstPackagePtr;
    pkgPtr->nextPtr = firstPackagePtr;
    firstPackagePtr = pkgPtr;
    firstPackagePtr = pkgPtr;
 
 
    if (interp != NULL) {
    if (interp != NULL) {
        ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(interp, "tclLoad",
        ipFirstPtr = (InterpPackage *) Tcl_GetAssocData(interp, "tclLoad",
                (Tcl_InterpDeleteProc **) NULL);
                (Tcl_InterpDeleteProc **) NULL);
        ipPtr = (InterpPackage *) ckalloc(sizeof(InterpPackage));
        ipPtr = (InterpPackage *) ckalloc(sizeof(InterpPackage));
        ipPtr->pkgPtr = pkgPtr;
        ipPtr->pkgPtr = pkgPtr;
        ipPtr->nextPtr = ipFirstPtr;
        ipPtr->nextPtr = ipFirstPtr;
        Tcl_SetAssocData(interp, "tclLoad", LoadCleanupProc,
        Tcl_SetAssocData(interp, "tclLoad", LoadCleanupProc,
                (ClientData) ipPtr);
                (ClientData) ipPtr);
    }
    }
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * TclGetLoadedPackages --
 * TclGetLoadedPackages --
 *
 *
 *      This procedure returns information about all of the files
 *      This procedure returns information about all of the files
 *      that are loaded (either in a particular intepreter, or
 *      that are loaded (either in a particular intepreter, or
 *      for all interpreters).
 *      for all interpreters).
 *
 *
 * Results:
 * Results:
 *      The return value is a standard Tcl completion code.  If
 *      The return value is a standard Tcl completion code.  If
 *      successful, a list of lists is placed in interp->result.
 *      successful, a list of lists is placed in interp->result.
 *      Each sublist corresponds to one loaded file;  its first
 *      Each sublist corresponds to one loaded file;  its first
 *      element is the name of the file (or an empty string for
 *      element is the name of the file (or an empty string for
 *      something that's statically loaded) and the second element
 *      something that's statically loaded) and the second element
 *      is the name of the package in that file.
 *      is the name of the package in that file.
 *
 *
 * Side effects:
 * Side effects:
 *      None.
 *      None.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
int
int
TclGetLoadedPackages(interp, targetName)
TclGetLoadedPackages(interp, targetName)
    Tcl_Interp *interp;         /* Interpreter in which to return
    Tcl_Interp *interp;         /* Interpreter in which to return
                                 * information or error message. */
                                 * information or error message. */
    char *targetName;           /* Name of target interpreter or NULL.
    char *targetName;           /* Name of target interpreter or NULL.
                                 * If NULL, return info about all interps;
                                 * If NULL, return info about all interps;
                                 * otherwise, just return info about this
                                 * otherwise, just return info about this
                                 * interpreter. */
                                 * interpreter. */
{
{
    Tcl_Interp *target;
    Tcl_Interp *target;
    LoadedPackage *pkgPtr;
    LoadedPackage *pkgPtr;
    InterpPackage *ipPtr;
    InterpPackage *ipPtr;
    char *prefix;
    char *prefix;
 
 
    if (targetName == NULL) {
    if (targetName == NULL) {
        /*
        /*
         * Return information about all of the available packages.
         * Return information about all of the available packages.
         */
         */
 
 
        prefix = "{";
        prefix = "{";
        for (pkgPtr = firstPackagePtr; pkgPtr != NULL;
        for (pkgPtr = firstPackagePtr; pkgPtr != NULL;
                pkgPtr = pkgPtr->nextPtr) {
                pkgPtr = pkgPtr->nextPtr) {
            Tcl_AppendResult(interp, prefix, (char *) NULL);
            Tcl_AppendResult(interp, prefix, (char *) NULL);
            Tcl_AppendElement(interp, pkgPtr->fileName);
            Tcl_AppendElement(interp, pkgPtr->fileName);
            Tcl_AppendElement(interp, pkgPtr->packageName);
            Tcl_AppendElement(interp, pkgPtr->packageName);
            Tcl_AppendResult(interp, "}", (char *) NULL);
            Tcl_AppendResult(interp, "}", (char *) NULL);
            prefix = " {";
            prefix = " {";
        }
        }
        return TCL_OK;
        return TCL_OK;
    }
    }
 
 
    /*
    /*
     * Return information about only the packages that are loaded in
     * Return information about only the packages that are loaded in
     * a given interpreter.
     * a given interpreter.
     */
     */
 
 
    target = Tcl_GetSlave(interp, targetName);
    target = Tcl_GetSlave(interp, targetName);
    if (target == NULL) {
    if (target == NULL) {
        Tcl_AppendResult(interp, "couldn't find slave interpreter named \"",
        Tcl_AppendResult(interp, "couldn't find slave interpreter named \"",
                targetName, "\"", (char *) NULL);
                targetName, "\"", (char *) NULL);
        return TCL_ERROR;
        return TCL_ERROR;
    }
    }
    ipPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
    ipPtr = (InterpPackage *) Tcl_GetAssocData(target, "tclLoad",
            (Tcl_InterpDeleteProc **) NULL);
            (Tcl_InterpDeleteProc **) NULL);
    prefix = "{";
    prefix = "{";
    for ( ; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
    for ( ; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
        pkgPtr = ipPtr->pkgPtr;
        pkgPtr = ipPtr->pkgPtr;
        Tcl_AppendResult(interp, prefix, (char *) NULL);
        Tcl_AppendResult(interp, prefix, (char *) NULL);
        Tcl_AppendElement(interp, pkgPtr->fileName);
        Tcl_AppendElement(interp, pkgPtr->fileName);
        Tcl_AppendElement(interp, pkgPtr->packageName);
        Tcl_AppendElement(interp, pkgPtr->packageName);
        Tcl_AppendResult(interp, "}", (char *) NULL);
        Tcl_AppendResult(interp, "}", (char *) NULL);
        prefix = " {";
        prefix = " {";
    }
    }
    return TCL_OK;
    return TCL_OK;
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * LoadCleanupProc --
 * LoadCleanupProc --
 *
 *
 *      This procedure is called to delete all of the InterpPackage
 *      This procedure is called to delete all of the InterpPackage
 *      structures for an interpreter when the interpreter is deleted.
 *      structures for an interpreter when the interpreter is deleted.
 *      It gets invoked via the Tcl AssocData mechanism.
 *      It gets invoked via the Tcl AssocData mechanism.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Storage for all of the InterpPackage procedures for interp
 *      Storage for all of the InterpPackage procedures for interp
 *      get deleted.
 *      get deleted.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static void
static void
LoadCleanupProc(clientData, interp)
LoadCleanupProc(clientData, interp)
    ClientData clientData;      /* Pointer to first InterpPackage structure
    ClientData clientData;      /* Pointer to first InterpPackage structure
                                 * for interp. */
                                 * for interp. */
    Tcl_Interp *interp;         /* Interpreter that is being deleted. */
    Tcl_Interp *interp;         /* Interpreter that is being deleted. */
{
{
    InterpPackage *ipPtr, *nextPtr;
    InterpPackage *ipPtr, *nextPtr;
 
 
    ipPtr = (InterpPackage *) clientData;
    ipPtr = (InterpPackage *) clientData;
    while (ipPtr != NULL) {
    while (ipPtr != NULL) {
        nextPtr = ipPtr->nextPtr;
        nextPtr = ipPtr->nextPtr;
        ckfree((char *) ipPtr);
        ckfree((char *) ipPtr);
        ipPtr = nextPtr;
        ipPtr = nextPtr;
    }
    }
}
}


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * LoadExitProc --
 * LoadExitProc --
 *
 *
 *      This procedure is invoked just before the application exits.
 *      This procedure is invoked just before the application exits.
 *      It frees all of the LoadedPackage structures.
 *      It frees all of the LoadedPackage structures.
 *
 *
 * Results:
 * Results:
 *      None.
 *      None.
 *
 *
 * Side effects:
 * Side effects:
 *      Memory is freed.
 *      Memory is freed.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
static void
static void
LoadExitProc(clientData)
LoadExitProc(clientData)
    ClientData clientData;              /* Not used. */
    ClientData clientData;              /* Not used. */
{
{
    LoadedPackage *pkgPtr;
    LoadedPackage *pkgPtr;
 
 
    while (firstPackagePtr != NULL) {
    while (firstPackagePtr != NULL) {
        pkgPtr = firstPackagePtr;
        pkgPtr = firstPackagePtr;
        firstPackagePtr = pkgPtr->nextPtr;
        firstPackagePtr = pkgPtr->nextPtr;
        ckfree(pkgPtr->fileName);
        ckfree(pkgPtr->fileName);
        ckfree(pkgPtr->packageName);
        ckfree(pkgPtr->packageName);
        ckfree((char *) pkgPtr);
        ckfree((char *) pkgPtr);
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.