added empty default imlementation so gmodule.so compiles on systems that
[platform/upstream/glib.git] / gmodule / gmodule.c
1 /* GMODULE - GLIB wrapper code for dynamic module loading
2  * Copyright (C) 1998 Tim Janik
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include        "gmodule.h"
20 #include        "gmoduleconf.h"
21 #include        <errno.h>
22 #include        <string.h>
23
24
25 /* We maintain a list of modules, so we can reference count them.
26  * That's needed because some platforms don't support refernce counts on
27  * modules e.g. the shl_* implementation of HP-UX
28  * (http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html).
29  * Also, the module for the program itself is kept seperatedly for
30  * faster access and because it has special semantics.
31  */
32
33
34 /* --- structures --- */
35 struct _GModule
36 {
37   gchar *file_name;
38   gpointer handle;
39   guint ref_count : 31;
40   guint is_resident : 1;
41   GModuleUnload unload;
42   GModule *next;
43 };
44
45
46 /* --- prototypes --- */
47 static gpointer         _g_module_open          (const gchar    *file_name,
48                                                  gboolean        bind_lazy);
49 static void             _g_module_close         (gpointer        handle,
50                                                  gboolean        is_unref);
51 static gpointer         _g_module_self          (void);
52 static gpointer         _g_module_symbol        (gpointer        handle,
53                                                  const gchar    *symbol_name);
54 static gchar*           _g_module_build_path    (const gchar    *directory,
55                                                  const gchar    *module_name);
56 static inline void      g_module_set_error      (const gchar    *error);
57 static inline GModule*  g_module_find_by_handle (gpointer        handle);
58 static inline GModule*  g_module_find_by_name   (const gchar    *name);
59
60
61 /* --- variables --- */
62 const char      *g_log_domain_gmodule = "GModule";
63 static GModule  *modules = NULL;
64 static GModule  *main_module = NULL;
65 static gchar    *module_error = NULL;
66
67
68 /* --- inline functions --- */
69 static inline GModule*
70 g_module_find_by_handle (gpointer handle)
71 {
72   GModule *module;
73   
74   if (main_module && main_module->handle == handle)
75     return main_module;
76   
77   for (module = modules; module; module = module->next)
78     if (handle == module->handle)
79       return module;
80   return NULL;
81 }
82
83 static inline GModule*
84 g_module_find_by_name (const gchar *name)
85 {
86   GModule *module;
87   
88   for (module = modules; module; module = module->next)
89     if (strcmp (name, module->file_name) == 0)
90       return module;
91   return NULL;
92 }
93
94 static inline void
95 g_module_set_error (const gchar *error)
96 {
97   if (module_error)
98     g_free (module_error);
99   if (error)
100     module_error = g_strdup (error);
101   else
102     module_error = NULL;
103   errno = 0;
104 }
105
106
107 /* --- include platform specifc code --- */
108 #define CHECK_ERROR(rv) { g_module_set_error (NULL); }
109 #if     (G_MODULE_IMPL == G_MODULE_IMPL_DL)
110 #include "gmodule-dl.c"
111 #elif   (G_MODULE_IMPL == G_MODULE_IMPL_DLD)
112 #include "gmodule-dld.c"
113 #elif   (G_MODULE_IMPL == G_MODULE_IMPL_WIN32)
114 #include "gmodule-win32.c"
115 #else
116 #undef  CHECK_ERROR
117 #define CHECK_ERROR(rv) { g_module_set_error ("unsupported"); return rv; }
118 static gpointer
119 _g_module_open (const gchar     *file_name,
120                 gboolean         bind_lazy)
121 {
122   return NULL;
123 }
124 static void
125 _g_module_close (gpointer        handle,
126                  gboolean        is_unref)
127 {
128 }
129 static gpointer
130 _g_module_self (void)
131 {
132   return NULL;
133 }
134 static gpointer
135 _g_module_symbol (gpointer       handle,
136                   const gchar   *symbol_name)
137 {
138   return NULL;
139 }
140 static gchar*
141 _g_module_build_path (const gchar *directory,
142                       const gchar *module_name)
143 {
144   return NULL;
145 }
146 #endif  /* no implementation */
147
148 #if defined (NATIVE_WIN32) && defined (__LCC__)
149 int __stdcall 
150 LibMain (void         *hinstDll,
151          unsigned long dwReason,
152          void         *reserved)
153 {
154   return 1;
155 }
156 #endif /* NATIVE_WIN32 && __LCC__ */
157
158
159 /* --- functions --- */
160 gboolean
161 g_module_supported (void)
162 {
163   CHECK_ERROR (FALSE);
164   
165   return TRUE;
166 }
167
168 GModule*
169 g_module_open (const gchar    *file_name,
170                GModuleFlags    flags)
171 {
172   GModule *module;
173   gpointer handle;
174   
175   CHECK_ERROR (NULL);
176   
177   if (!file_name)
178     {
179       if (!main_module)
180         {
181           handle = _g_module_self ();
182           if (handle)
183             {
184               main_module = g_new (GModule, 1);
185               main_module->file_name = NULL;
186               main_module->handle = handle;
187               main_module->ref_count = 1;
188               main_module->is_resident = TRUE;
189               main_module->unload = NULL;
190               main_module->next = NULL;
191             }
192         }
193       
194       return main_module;
195     }
196   
197   /* we first search the module list by name */
198   module = g_module_find_by_name (file_name);
199   if (module)
200     {
201       module->ref_count++;
202       
203       return module;
204     }
205   
206   /* open the module */
207   handle = _g_module_open (file_name, (flags & G_MODULE_BIND_LAZY) != 0);
208   if (handle)
209     {
210       gchar *saved_error;
211       GModuleCheckInit check_init;
212       const gchar *check_failed = NULL;
213       
214       /* search the module list by handle, since file names are not unique */
215       module = g_module_find_by_handle (handle);
216       if (module)
217         {
218           _g_module_close (module->handle, TRUE);
219           module->ref_count++;
220           g_module_set_error (NULL);
221           
222           return module;
223         }
224       
225       saved_error = module_error;
226       module_error = NULL;
227       g_module_set_error (NULL);
228       
229       module = g_new (GModule, 1);
230       module->file_name = g_strdup (file_name);
231       module->handle = handle;
232       module->ref_count = 1;
233       module->is_resident = FALSE;
234       module->unload = NULL;
235       module->next = modules;
236       modules = module;
237       
238       /* check initialization */
239       if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init))
240         check_failed = check_init (module);
241       
242       /* we don't call unload() if the initialization check failed. */
243       if (!check_failed)
244         g_module_symbol (module, "g_module_unload", (gpointer) &module->unload);
245       
246       if (check_failed)
247         {
248           gchar *error;
249
250           error = g_strconcat ("GModule initialization check failed: ", check_failed, NULL);
251           g_module_close (module);
252           module = NULL;
253           g_module_set_error (error);
254           g_free (error);
255         }
256       else
257         g_module_set_error (saved_error);
258       g_free (saved_error);
259     }
260   
261   return module;
262 }
263
264 gboolean
265 g_module_close (GModule        *module)
266 {
267   CHECK_ERROR (FALSE);
268   
269   g_return_val_if_fail (module != NULL, FALSE);
270   g_return_val_if_fail (module->ref_count > 0, FALSE);
271   
272   module->ref_count--;
273   
274   if (!module->ref_count && !module->is_resident && module->unload)
275     {
276       GModuleUnload unload;
277
278       unload = module->unload;
279       module->unload = NULL;
280       unload (module);
281     }
282
283   if (!module->ref_count && !module->is_resident)
284     {
285       GModule *last;
286       GModule *node;
287       
288       last = NULL;
289       node = modules;
290       while (node)
291         {
292           if (node == module)
293             {
294               if (last)
295                 last->next = node->next;
296               else
297                 modules = node->next;
298               break;
299             }
300           last = node;
301           node = last->next;
302         }
303       module->next = NULL;
304       
305       _g_module_close (module->handle, FALSE);
306       g_free (module->file_name);
307       
308       g_free (module);
309     }
310   
311   return module_error == NULL;
312 }
313
314 void
315 g_module_make_resident (GModule *module)
316 {
317   g_return_if_fail (module != NULL);
318
319   module->is_resident = TRUE;
320 }
321
322 gchar*
323 g_module_error (void)
324 {
325   return module_error;
326 }
327
328 gboolean
329 g_module_symbol (GModule        *module,
330                  const gchar    *symbol_name,
331                  gpointer       *symbol)
332 {
333   if (symbol)
334     *symbol = NULL;
335   CHECK_ERROR (FALSE);
336   
337   g_return_val_if_fail (module != NULL, FALSE);
338   g_return_val_if_fail (symbol_name != NULL, FALSE);
339   g_return_val_if_fail (symbol != NULL, FALSE);
340   
341 #ifdef  G_MODULE_NEED_USCORE
342   {
343     gchar *name;
344
345     name = g_strconcat ("_", symbol_name, NULL);
346     *symbol = _g_module_symbol (module->handle, name);
347     g_free (name);
348   }
349 #else   /* !G_MODULE_NEED_USCORE */
350   *symbol = _g_module_symbol (module->handle, symbol_name);
351 #endif  /* !G_MODULE_NEED_USCORE */
352   
353   if (module_error)
354     {
355       gchar *error;
356
357       error = g_strconcat ("`", symbol_name, "': ", module_error, NULL);
358       g_module_set_error (error);
359       g_free (error);
360       *symbol = NULL;
361       return FALSE;
362     }
363   
364   return TRUE;
365 }
366
367 gchar*
368 g_module_name (GModule *module)
369 {
370   g_return_val_if_fail (module != NULL, NULL);
371   
372   if (module == main_module)
373     return "main";
374   
375   return module->file_name;
376 }
377
378 gchar*
379 g_module_build_path (const gchar *directory,
380                      const gchar *module_name)
381 {
382   g_return_val_if_fail (module_name != NULL, NULL);
383   
384   return _g_module_build_path (directory, module_name);
385 }