removed dummy structure definitions for struct _GCache, _GTree, _GTimer,
[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 #endif  /* no implementation */
141
142 #if defined (NATIVE_WIN32) && defined (__LCC__)
143 int __stdcall 
144 LibMain (void         *hinstDll,
145          unsigned long dwReason,
146          void         *reserved)
147 {
148   return 1;
149 }
150 #endif /* NATIVE_WIN32 && __LCC__ */
151
152
153 /* --- functions --- */
154 gboolean
155 g_module_supported (void)
156 {
157   CHECK_ERROR (FALSE);
158   
159   return TRUE;
160 }
161
162 GModule*
163 g_module_open (const gchar    *file_name,
164                GModuleFlags    flags)
165 {
166   GModule *module;
167   gpointer handle;
168   
169   CHECK_ERROR (NULL);
170   
171   if (!file_name)
172     {
173       if (!main_module)
174         {
175           handle = _g_module_self ();
176           if (handle)
177             {
178               main_module = g_new (GModule, 1);
179               main_module->file_name = NULL;
180               main_module->handle = handle;
181               main_module->ref_count = 1;
182               main_module->is_resident = TRUE;
183               main_module->unload = NULL;
184               main_module->next = NULL;
185             }
186         }
187       
188       return main_module;
189     }
190   
191   /* we first search the module list by name */
192   module = g_module_find_by_name (file_name);
193   if (module)
194     {
195       module->ref_count++;
196       
197       return module;
198     }
199   
200   /* open the module */
201   handle = _g_module_open (file_name, (flags & G_MODULE_BIND_LAZY) != 0);
202   if (handle)
203     {
204       gchar *saved_error;
205       GModuleCheckInit check_init;
206       const gchar *check_failed = NULL;
207       
208       /* search the module list by handle, since file names are not unique */
209       module = g_module_find_by_handle (handle);
210       if (module)
211         {
212           _g_module_close (module->handle, TRUE);
213           module->ref_count++;
214           g_module_set_error (NULL);
215           
216           return module;
217         }
218       
219       saved_error = module_error;
220       module_error = NULL;
221       g_module_set_error (NULL);
222       
223       module = g_new (GModule, 1);
224       module->file_name = g_strdup (file_name);
225       module->handle = handle;
226       module->ref_count = 1;
227       module->is_resident = FALSE;
228       module->unload = NULL;
229       module->next = modules;
230       modules = module;
231       
232       /* check initialization */
233       if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init))
234         check_failed = check_init (module);
235       
236       /* we don't call unload() if the initialization check failed. */
237       if (!check_failed)
238         g_module_symbol (module, "g_module_unload", (gpointer) &module->unload);
239       
240       if (check_failed)
241         {
242           gchar *error;
243
244           error = g_strconcat ("GModule initialization check failed: ", check_failed, NULL);
245           g_module_close (module);
246           module = NULL;
247           g_module_set_error (error);
248           g_free (error);
249         }
250       else
251         g_module_set_error (saved_error);
252       g_free (saved_error);
253     }
254   
255   return module;
256 }
257
258 gboolean
259 g_module_close (GModule        *module)
260 {
261   CHECK_ERROR (FALSE);
262   
263   g_return_val_if_fail (module != NULL, FALSE);
264   g_return_val_if_fail (module->ref_count > 0, FALSE);
265   
266   module->ref_count--;
267   
268   if (!module->ref_count && !module->is_resident && module->unload)
269     {
270       GModuleUnload unload;
271
272       unload = module->unload;
273       module->unload = NULL;
274       unload (module);
275     }
276
277   if (!module->ref_count && !module->is_resident)
278     {
279       GModule *last;
280       GModule *node;
281       
282       last = NULL;
283       node = modules;
284       while (node)
285         {
286           if (node == module)
287             {
288               if (last)
289                 last->next = node->next;
290               else
291                 modules = node->next;
292               break;
293             }
294           last = node;
295           node = last->next;
296         }
297       module->next = NULL;
298       
299       _g_module_close (module->handle, FALSE);
300       g_free (module->file_name);
301       
302       g_free (module);
303     }
304   
305   return module_error == NULL;
306 }
307
308 void
309 g_module_make_resident (GModule *module)
310 {
311   g_return_if_fail (module != NULL);
312
313   module->is_resident = TRUE;
314 }
315
316 gchar*
317 g_module_error (void)
318 {
319   return module_error;
320 }
321
322 gboolean
323 g_module_symbol (GModule        *module,
324                  const gchar    *symbol_name,
325                  gpointer       *symbol)
326 {
327   if (symbol)
328     *symbol = NULL;
329   CHECK_ERROR (FALSE);
330   
331   g_return_val_if_fail (module != NULL, FALSE);
332   g_return_val_if_fail (symbol_name != NULL, FALSE);
333   g_return_val_if_fail (symbol != NULL, FALSE);
334   
335 #ifdef  G_MODULE_NEED_USCORE
336   {
337     gchar *name;
338
339     name = g_strconcat ("_", symbol_name, NULL);
340     *symbol = _g_module_symbol (module->handle, name);
341     g_free (name);
342   }
343 #else   /* !G_MODULE_NEED_USCORE */
344   *symbol = _g_module_symbol (module->handle, symbol_name);
345 #endif  /* !G_MODULE_NEED_USCORE */
346   
347   if (module_error)
348     {
349       gchar *error;
350
351       error = g_strconcat ("`", symbol_name, "': ", module_error, NULL);
352       g_module_set_error (error);
353       g_free (error);
354       *symbol = NULL;
355       return FALSE;
356     }
357   
358   return TRUE;
359 }
360
361 gchar*
362 g_module_name (GModule *module)
363 {
364   g_return_val_if_fail (module != NULL, NULL);
365   
366   if (module == main_module)
367     return "main";
368   
369   return module->file_name;
370 }
371
372 gchar*
373 g_module_build_path (const gchar *directory,
374                      const gchar *module_name)
375 {
376   g_return_val_if_fail (module_name != NULL, NULL);
377   
378   return _g_module_build_path (directory, module_name);
379 }