/* Copyright (c) 1997-1999 Miller Puckette. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifdef DL_OPEN #include #endif #ifdef UNISTD #include #include #endif #ifdef MSW #include #include #endif #ifdef MACOSX #include #endif #include #include "m_pd.h" #include "s_stuff.h" #include typedef void (*t_xxx)(void); static char sys_dllextent[] = #ifdef __FreeBSD__ ".pd_freebsd"; #endif #ifdef IRIX #ifdef N32 ".pd_irix6"; #else ".pd_irix5"; #endif #endif #ifdef __linux__ ".pd_linux"; #endif #ifdef MACOSX ".pd_darwin"; #endif #ifdef MSW ".dll"; #endif void class_set_extern_dir(t_symbol *s); static int sys_load_lib_alt(char *dirname, char *classname, char *altname) { char symname[MAXPDSTRING], filename[MAXPDSTRING], dirbuf[MAXPDSTRING], classname2[MAXPDSTRING], *nameptr, *lastdot, altsymname[MAXPDSTRING]; void *dlobj; t_xxx makeout = NULL; int fd; #ifdef MSW HINSTANCE ntdll; #endif #if 0 fprintf(stderr, "lib %s %s\n", dirname, classname); #endif /* try looking in the path for (classname).(sys_dllextent) ... */ if ((fd = open_via_path(dirname, classname, sys_dllextent, dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) { /* next try (classname)/(classname).(sys_dllextent) ... */ strncpy(classname2, classname, MAXPDSTRING); filename[MAXPDSTRING-2] = 0; strcat(classname2, "/"); strncat(classname2, classname, MAXPDSTRING-strlen(classname2)); filename[MAXPDSTRING-1] = 0; if ((fd = open_via_path(dirname, classname2, sys_dllextent, dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) { /* next try (alternative_classname).(sys_dllextent) */ if(altname) { if ((fd = open_via_path(dirname, altname, sys_dllextent, dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) /* next try (alternative_classname)/(alternative_classname).(sys_dllextent) ... */ strncpy(classname2, altname, MAXPDSTRING); filename[MAXPDSTRING-2] = 0; strcat(classname2, "/"); strncat(classname2, altname, MAXPDSTRING-strlen(classname2)); filename[MAXPDSTRING-1] = 0; if ((fd = open_via_path(dirname, classname2, sys_dllextent, dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) { return 0; } } else return (0); } } close(fd); class_set_extern_dir(gensym(dirbuf)); /* refabricate the pathname */ strncpy(filename, dirbuf, MAXPDSTRING); filename[MAXPDSTRING-2] = 0; strcat(filename, "/"); strncat(filename, nameptr, MAXPDSTRING-strlen(filename)); filename[MAXPDSTRING-1] = 0; /* extract the setup function name */ if (lastdot = strrchr(nameptr, '.')) *lastdot = 0; #ifdef MACOSX strcpy(symname, "_"); strcat(symname, nameptr); if(altname) { strcpy(altsymname, "_setup_"); strcat(symname, altname); } #else strcpy(symname, nameptr); if(altname) { strcpy(altsymname, "setup_"); strcat(altsymname, altname); } #endif /* if the last character is a tilde, replace with "_tilde" */ if (symname[strlen(symname) - 1] == '~') strcpy(symname + (strlen(symname) - 1), "_tilde"); /* and append _setup to form the C setup function name */ strcat(symname, "_setup"); #ifdef DL_OPEN dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); if (!dlobj) { post("%s: %s", filename, dlerror()); class_set_extern_dir(&s_); return (0); } makeout = (t_xxx)dlsym(dlobj, symname); if(!makeout)makeout = (t_xxx)dlsym(dlobj, altsymname); #endif #ifdef MSW sys_bashfilename(filename, filename); ntdll = LoadLibrary(filename); if (!ntdll) { post("%s: couldn't load", filename); class_set_extern_dir(&s_); return (0); } makeout = (t_xxx)GetProcAddress(ntdll, symname); if(!makeout)makeout = (t_xxx)GetProcAddress(ntdll, altsymname); #endif #if defined(MACOSX) && !defined(DL_OPEN) { NSObjectFileImage image; void *ret; NSSymbol s; if ( NSCreateObjectFileImageFromFile( filename, &image) != NSObjectFileImageSuccess ) { post("%s: couldn't load", filename); class_set_extern_dir(&s_); return 0; } ret = NSLinkModule( image, filename, NSLINKMODULE_OPTION_BINDNOW | NSLINKMODULE_OPTION_RETURN_ON_ERROR); if (ret == NULL) { int err; const char *fname, *errt; NSLinkEditErrors c; NSLinkEditError(&c, &err, &fname, &errt); post("link error %d %s %s", err, fname, errt); return 0; } s = NSLookupSymbolInModule(ret, symname); if(!s)s=NSLookupSymbolInModule(ret, altsymname); if (s) makeout = (t_xxx)NSAddressOfSymbol( s); else makeout = 0; } #endif if (!makeout) { post("load_object: Symbol \"%s\" not found", symname); if(altname) post("load_object: Symbol \"%s\" not found", altsymname); class_set_extern_dir(&s_); return 0; } (*makeout)(); class_set_extern_dir(&s_); return (1); } /* callback type definition */ typedef int (*loader_t)(char *dirname, char *classname, char *altname); /* linked list of loaders */ typedef struct loader_queue { loader_t loader; struct loader_queue *next; } loader_queue_t; static loader_queue_t loaders = {sys_load_lib_alt, NULL}; /* register class loader function */ void sys_register_loader(loader_t loader) { loader_queue_t *q = &loaders; while (1) { if (q->next) q = q->next; else { q->next = (loader_queue_t *)getbytes(sizeof(loader_queue_t)); q->next->loader = loader; q->next->next = NULL; break; } } } int sys_load_lib(char *dirname, char *classname, char *altname) { int dspstate = canvas_suspend_dsp(); int ok = 0; loader_queue_t *q; for(q = &loaders; q; q = q->next) if(ok = q->loader(dirname, classname, altname)) break; canvas_resume_dsp(dspstate); return ok; }