alias: don't rely on internal list never shimmering
[jimtcl.git] / jim-load.c
bloba449931fd63a4bc83bab2383b6815c05fa3179a4
1 #include <string.h>
3 #include "jimautoconf.h"
4 #include <jim.h>
6 /* -----------------------------------------------------------------------------
7 * Dynamic libraries support (WIN32 not supported)
8 * ---------------------------------------------------------------------------*/
10 #if defined(HAVE_DLOPEN) || defined(HAVE_DLOPEN_COMPAT)
12 #ifdef HAVE_DLFCN_H
13 #include <dlfcn.h>
14 #endif
16 #ifndef RTLD_NOW
17 #define RTLD_NOW 0
18 #endif
19 #ifndef RTLD_LOCAL
20 #define RTLD_LOCAL 0
21 #endif
23 static void JimFreeLoadHandles(Jim_Interp *interp, void *data);
25 /**
26 * Note that Jim_LoadLibrary() requires a path to an existing file.
28 * If it is necessary to search JIM_LIBPATH, use Jim_PackageRequire() instead.
30 int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName)
32 void *handle = dlopen(pathName, RTLD_NOW | RTLD_LOCAL);
33 if (handle == NULL) {
34 Jim_SetResultFormatted(interp, "error loading extension \"%s\": %s", pathName,
35 dlerror());
37 else {
38 /* We use a unique init symbol depending on the extension name.
39 * This is done for compatibility between static and dynamic extensions.
40 * For extension readline.so, the init symbol is "Jim_readlineInit"
42 const char *pt;
43 const char *pkgname;
44 int pkgnamelen;
45 char initsym[40];
46 typedef int jim_module_init_func_type(Jim_Interp *);
47 jim_module_init_func_type *onload;
49 pt = strrchr(pathName, '/');
50 if (pt) {
51 pkgname = pt + 1;
53 else {
54 pkgname = pathName;
56 pt = strchr(pkgname, '.');
57 if (pt) {
58 pkgnamelen = pt - pkgname;
60 else {
61 pkgnamelen = strlen(pkgname);
63 snprintf(initsym, sizeof(initsym), "Jim_%.*sInit", pkgnamelen, pkgname);
65 if ((onload = (jim_module_init_func_type *)dlsym(handle, initsym)) == NULL) {
66 Jim_SetResultFormatted(interp,
67 "No %s symbol found in extension %s", initsym, pathName);
69 else if (onload(interp) != JIM_ERR) {
70 /* Add this handle to the stack of handles to be freed */
71 Jim_Stack *loadHandles = Jim_GetAssocData(interp, "load::handles");
72 if (loadHandles == NULL) {
73 loadHandles = Jim_Alloc(sizeof(*loadHandles));
74 Jim_InitStack(loadHandles);
75 Jim_SetAssocData(interp, "load::handles", JimFreeLoadHandles, loadHandles);
77 Jim_StackPush(loadHandles, handle);
79 Jim_SetEmptyResult(interp);
81 return JIM_OK;
84 if (handle) {
85 dlclose(handle);
87 return JIM_ERR;
90 static void JimFreeOneLoadHandle(void *handle)
92 dlclose(handle);
95 static void JimFreeLoadHandles(Jim_Interp *interp, void *data)
97 Jim_Stack *handles = data;
99 if (handles) {
100 Jim_FreeStackElements(handles, JimFreeOneLoadHandle);
101 Jim_FreeStack(handles);
102 Jim_Free(handles);
106 #else /* JIM_DYNLIB */
107 int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName)
109 JIM_NOTUSED(interp);
110 JIM_NOTUSED(pathName);
112 Jim_SetResultString(interp, "the Jim binary has no support for [load]", -1);
113 return JIM_ERR;
116 void Jim_FreeLoadHandles(Jim_Interp *interp)
119 #endif /* JIM_DYNLIB */
121 /* [load] */
122 static int Jim_LoadCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
124 if (argc < 2) {
125 Jim_WrongNumArgs(interp, 1, argv, "libaryFile");
126 return JIM_ERR;
128 return Jim_LoadLibrary(interp, Jim_String(argv[1]));
131 int Jim_loadInit(Jim_Interp *interp)
133 Jim_CreateCommand(interp, "load", Jim_LoadCoreCommand, NULL, NULL);
134 return JIM_OK;