aboutsummaryrefslogtreecommitdiff
path: root/jim-load.c
blob: 84a7d439da3e8fdaffe862fdbb78131233a3fa61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <jim.h>
#include <string.h>

/* -----------------------------------------------------------------------------
 * Dynamic libraries support (WIN32 not supported)
 * ---------------------------------------------------------------------------*/

#ifdef JIM_DYNLIB

#include <dlfcn.h>

int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName)
{
    Jim_Obj *libPathObjPtr;
    int prefixc, i;
    void *handle;
    int (*onload)(Jim_Interp *interp);

    libPathObjPtr = Jim_GetGlobalVariableStr(interp, JIM_LIBPATH, JIM_NONE);
    if (libPathObjPtr == NULL) {
        prefixc = 0;
        libPathObjPtr = NULL;
    } else {
        Jim_IncrRefCount(libPathObjPtr);
        prefixc = Jim_ListLength(interp, libPathObjPtr);
    }

    for (i = -1; i < prefixc; i++) {
        if (i < 0) {
            handle = dlopen(pathName, RTLD_LAZY);
        } else {
            FILE *fp;
            char buf[JIM_PATH_LEN];
            const char *prefix;
            int prefixlen;
            Jim_Obj *prefixObjPtr;
            
            buf[0] = '\0';
            if (Jim_ListIndex(interp, libPathObjPtr, i,
                    &prefixObjPtr, JIM_NONE) != JIM_OK)
                continue;
            prefix = Jim_GetString(prefixObjPtr, &prefixlen);
            if (prefixlen+strlen(pathName)+1 >= JIM_PATH_LEN)
                continue;
            if (*pathName == '/') {
                strcpy(buf, pathName);
            }    
            else if (prefixlen && prefix[prefixlen-1] == '/')
                sprintf(buf, "%s%s", prefix, pathName);
            else
                sprintf(buf, "%s/%s", prefix, pathName);
            fp = fopen(buf, "r");
            if (fp == NULL)
                continue;
            fclose(fp);
            handle = dlopen(buf, RTLD_LAZY);
        }
        if (handle == NULL) {
            Jim_SetResultFormatted(interp, "error loading extension \"%s\": %s", pathName, dlerror());
            if (i < 0)
                continue;
            goto err;
        }
        if ((onload = dlsym(handle, "Jim_OnLoad")) == NULL) {
            Jim_SetResultString(interp,
                    "No Jim_OnLoad symbol found on extension", -1);
            goto err;
        }
        if (onload(interp) == JIM_ERR) {
            dlclose(handle);
            goto err;
        }
        Jim_SetEmptyResult(interp);
        if (libPathObjPtr != NULL)
            Jim_DecrRefCount(interp, libPathObjPtr);
        return JIM_OK;
    }
err:
    if (libPathObjPtr != NULL)
        Jim_DecrRefCount(interp, libPathObjPtr);
    return JIM_ERR;
}
#else /* JIM_DYNLIB */
int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName)
{
    JIM_NOTUSED(interp);
    JIM_NOTUSED(pathName);

    Jim_SetResultString(interp, "the Jim binary has no support for [load]", -1);
    return JIM_ERR;
}
#endif/* JIM_DYNLIB */

/* [load] */
static int Jim_LoadCoreCommand(Jim_Interp *interp, int argc, 
        Jim_Obj *const *argv)
{
    if (argc < 2) {
        Jim_WrongNumArgs(interp, 1, argv, "libaryFile");
        return JIM_ERR;
    }
    return Jim_LoadLibrary(interp, Jim_GetString(argv[1], NULL));
}

int Jim_loadInit(Jim_Interp *interp)
{
    Jim_CreateCommand(interp, "load", Jim_LoadCoreCommand, NULL, NULL);
    return JIM_OK;
}