- replaced G.{edve,eded,edvl} with G.editMesh, atm just a structure to
[blender.git] / source / blender / blenlib / intern / dynlib.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file, with exception of below:
27  *
28  * Contributor(s): Peter O'Gorman
29  * The functions osxdlopen() and osxerror() 
30  * are Copyright (c) 2002 Peter O'Gorman <ogorman@users.sourceforge.net>
31  *
32  * ***** END GPL/BL DUAL LICENSE BLOCK *****
33  */
34 #include <stdlib.h>
35 #include "../PIL_dynlib.h"
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #if !defined(CHAR_MAX)
42 #define CHAR_MAX 255
43 #endif
44
45 /*
46  * XXX, should use mallocN so we can see
47  * handle's not being released. fixme zr
48  */
49  
50 #ifdef WIN32
51
52 #include <windows.h>
53
54 struct PILdynlib {
55         void *handle;
56 };
57
58 PILdynlib *PIL_dynlib_open(char *name) {
59         void *handle= LoadLibrary(name);
60
61         if (handle) {   
62                 PILdynlib *lib= malloc(sizeof(*lib));
63                 lib->handle= handle;
64                 
65                 return lib;
66         } else {
67                 return NULL;
68         }
69 }
70
71 void *PIL_dynlib_find_symbol(PILdynlib* lib, char *symname) {
72         return GetProcAddress(lib->handle, symname);
73 }
74
75 char *PIL_dynlib_get_error_as_string(PILdynlib* lib) {
76         int err;
77
78         /* if lib is NULL reset the last error code */
79         if (!lib) {
80                 SetLastError(ERROR_SUCCESS);
81                 return NULL;
82         }
83
84         err= GetLastError();
85         if (err) {
86                 static char buf[1024];
87
88                 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 
89                                         NULL, 
90                                         err, 
91                                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
92                                         buf, 
93                                         sizeof(buf), 
94                                         NULL))
95                         return buf;
96         }
97         
98         return NULL;
99 }
100
101 void PIL_dynlib_close(PILdynlib *lib) {
102         FreeLibrary(lib->handle);
103         
104         free(lib);
105 }
106
107 #else
108 #ifdef __APPLE__        /* MacOS X */
109
110 #include <mach-o/dyld.h>
111 #include <dlfcn.h>
112 #include <stdarg.h>
113
114 #define ERR_STR_LEN 256
115
116 struct PILdynlib {
117         void *handle;
118 };
119
120 char *osxerror(int setget, const char *str, ...)
121 {
122         static char errstr[ERR_STR_LEN];
123         static int err_filled = 0;
124         char *retval;
125         NSLinkEditErrors ler;
126         int lerno;
127         const char *dylderrstr;
128         const char *file;
129         va_list arg;
130         if (setget <= 0)
131         {
132                 va_start(arg, str);
133                 strncpy(errstr, "dlsimple: ", ERR_STR_LEN);
134                 vsnprintf(errstr + 10, ERR_STR_LEN - 10, str, arg);
135                 va_end(arg);
136         /* We prefer to use the dyld error string if setget is 0 */
137                 if (setget == 0) {
138                         NSLinkEditError(&ler, &lerno, &file, &dylderrstr);
139                         printf("dyld: %s\n",dylderrstr);
140                         if (dylderrstr && strlen(dylderrstr))
141                                 strncpy(errstr,dylderrstr,ERR_STR_LEN);
142                 }               
143                 err_filled = 1;
144                 retval = NULL;
145         }
146         else
147         {
148                 if (!err_filled)
149                         retval = NULL;
150                 else
151                         retval = errstr;
152                 err_filled = 0;
153         }
154         return retval;
155 }
156
157 void *osxdlopen(const char *path, int mode)
158 {
159         void *module = 0;
160         NSObjectFileImage ofi = 0;
161         NSObjectFileImageReturnCode ofirc;
162         static int (*make_private_module_public) (NSModule module) = 0;
163         unsigned int flags =  NSLINKMODULE_OPTION_RETURN_ON_ERROR | NSLINKMODULE_OPTION_PRIVATE;
164
165         /* If we got no path, the app wants the global namespace, use -1 as the marker
166            in this case */
167         if (!path)
168                 return (void *)-1;
169
170         /* Create the object file image, works for things linked with the -bundle arg to ld */
171         ofirc = NSCreateObjectFileImageFromFile(path, &ofi);
172         switch (ofirc)
173         {
174                 case NSObjectFileImageSuccess:
175                         /* It was okay, so use NSLinkModule to link in the image */
176                         if (!(mode & RTLD_LAZY)) flags += NSLINKMODULE_OPTION_BINDNOW;
177                         module = NSLinkModule(ofi, path,flags);
178                         /* Don't forget to destroy the object file image, unless you like leaks */
179                         NSDestroyObjectFileImage(ofi);
180                         /* If the mode was global, then change the module, this avoids
181                            multiply defined symbol errors to first load private then make
182                            global. Silly, isn't it. */
183                         if ((mode & RTLD_GLOBAL))
184                         {
185                           if (!make_private_module_public)
186                           {
187                             _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", 
188                                 (unsigned long *)&make_private_module_public);
189                           }
190                           make_private_module_public(module);
191                         }
192                         break;
193                 case NSObjectFileImageInappropriateFile:
194                         /* It may have been a dynamic library rather than a bundle, try to load it */
195                         module = (void *)NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
196                         break;
197                 case NSObjectFileImageFailure:
198                         osxerror(0,"Object file setup failure :  \"%s\"", path);
199                         return 0;
200                 case NSObjectFileImageArch:
201                         osxerror(0,"No object for this architecture :  \"%s\"", path);
202                         return 0;
203                 case NSObjectFileImageFormat:
204                         osxerror(0,"Bad object file format :  \"%s\"", path);
205                         return 0;
206                 case NSObjectFileImageAccess:
207                         osxerror(0,"Can't read object file :  \"%s\"", path);
208                         return 0;               
209         }
210         if (!module)
211                 osxerror(0, "Can not open \"%s\"", path);
212         return module;
213 }
214
215 PILdynlib *PIL_dynlib_open(char *name) {
216         void *handle= osxdlopen(name, RTLD_LAZY);
217
218         if (handle) {   
219                 PILdynlib *lib= malloc(sizeof(*lib));
220                 lib->handle= handle;
221                 
222                 return lib;
223         } else {
224                 return NULL;
225         }
226 }
227
228 void *PIL_dynlib_find_symbol(PILdynlib* lib, char *symname) 
229 {
230         int sym_len = strlen(symname);
231         void *value = NULL;
232         char *malloc_sym = NULL;
233         NSSymbol *nssym = 0;
234         malloc_sym = malloc(sym_len + 2);
235         if (malloc_sym)
236         {
237                 sprintf(malloc_sym, "_%s", symname);
238                 /* If the lib->handle is -1, if is the app global context */
239                 if (lib->handle == (void *)-1)
240                 {
241                         /* Global context, use NSLookupAndBindSymbol */
242                         if (NSIsSymbolNameDefined(malloc_sym))
243                         {
244                                 nssym = NSLookupAndBindSymbol(malloc_sym);
245                         }
246                 }
247                 /* Now see if the lib->handle is a struch mach_header* or not, use NSLookupSymbol in image
248                    for libraries, and NSLookupSymbolInModule for bundles */
249                 else
250                 {
251                         /* Check for both possible magic numbers depending on x86/ppc byte order */
252                         if ((((struct mach_header *)lib->handle)->magic == MH_MAGIC) ||
253                                 (((struct mach_header *)lib->handle)->magic == MH_CIGAM))
254                         {
255                                 if (NSIsSymbolNameDefinedInImage((struct mach_header *)lib->handle, malloc_sym))
256                                 {
257                                         nssym = NSLookupSymbolInImage((struct mach_header *)lib->handle,
258                                                                                                   malloc_sym,
259                                                                                                   NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
260                                                                                                   | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR);
261                                 }
262         
263                         }
264                         else
265                         {
266                                 nssym = NSLookupSymbolInModule(lib->handle, malloc_sym);
267                         }
268                 }
269                 if (!nssym)
270                 {
271                         osxerror(0, "symname \"%s\" Not found", symname);
272                 }
273                 value = NSAddressOfSymbol(nssym);
274                 free(malloc_sym);
275         }
276         else
277         {
278                 osxerror(-1, "Unable to allocate memory");
279         }
280         return value;
281 }
282
283 char *PIL_dynlib_get_error_as_string(PILdynlib* lib) 
284 {
285         return osxerror(1, (char *)NULL);
286 }
287         
288 void PIL_dynlib_close(PILdynlib *lib) 
289 {
290         if ((((struct mach_header *)lib->handle)->magic == MH_MAGIC) ||
291                 (((struct mach_header *)lib->handle)->magic == MH_CIGAM))
292         {
293                 osxerror(-1, "Can't remove dynamic libraries on darwin");
294         }
295         if (!NSUnLinkModule(lib->handle, 0))
296         {
297                 osxerror(0, "unable to unlink module %s", NSNameOfModule(lib->handle));
298         }
299         
300         free(lib);
301 }
302
303 #else   /* Unix */
304
305 #include <dlfcn.h>
306
307 struct PILdynlib {
308         void *handle;
309 };
310
311 PILdynlib *PIL_dynlib_open(char *name) {
312         void *handle= dlopen(name, RTLD_LAZY);
313
314         if (handle) {   
315                 PILdynlib *lib= malloc(sizeof(*lib));
316                 lib->handle= handle;
317                 
318                 return lib;
319         } else {
320                 return NULL;
321         }
322 }
323
324 void *PIL_dynlib_find_symbol(PILdynlib* lib, char *symname) {
325         return dlsym(lib->handle, symname);
326 }
327
328 char *PIL_dynlib_get_error_as_string(PILdynlib* lib) {
329         return dlerror();
330 }
331         
332 void PIL_dynlib_close(PILdynlib *lib) {
333         dlclose(lib->handle);
334         
335         free(lib);
336 }
337
338 #endif
339 #endif