provide no operation implementation for the underlying _g_module_*
[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;
40   GModuleDeInit de_init;
41   GModule *next;
42 };
43
44
45 /* --- prototypes --- */
46 static gpointer         _g_module_open          (const gchar    *file_name,
47                                                  gboolean        bind_lazy);
48 static void             _g_module_close         (gpointer        handle,
49                                                  gboolean        is_unref);
50 static gpointer         _g_module_self          (void);
51 static gpointer         _g_module_symbol        (gpointer        handle,
52                                                  const gchar    *symbol_name);
53 static inline void      g_module_set_error      (const gchar    *error);
54 static inline GModule*  g_module_find_by_handle (gpointer        handle);
55 static inline GModule*  g_module_find_by_name   (const gchar    *name);
56
57
58 /* --- variables --- */
59 const char      *g_log_domain_gmodule = "GModule";
60 static GModule  *modules = NULL;
61 static GModule  *main_module = NULL;
62 static gchar    *module_error = NULL;
63
64
65 /* --- inline functions --- */
66 static inline GModule*
67 g_module_find_by_handle (gpointer handle)
68 {
69   GModule *module;
70   
71   if (main_module && main_module->handle == handle)
72     return main_module;
73   
74   for (module = modules; module; module = module->next)
75     if (handle == module->handle)
76       return module;
77   return NULL;
78 }
79
80 static inline GModule*
81 g_module_find_by_name (const gchar *name)
82 {
83   GModule *module;
84   
85   for (module = modules; module; module = module->next)
86     if (strcmp (name, module->file_name) == 0)
87       return module;
88   return NULL;
89 }
90
91 static inline void
92 g_module_set_error (const gchar *error)
93 {
94   if (module_error)
95     g_free (module_error);
96   if (error)
97     module_error = g_strdup (error);
98   else
99     module_error = NULL;
100   errno = 0;
101 }
102
103
104 /* --- include platform specifc code --- */
105 #define CHECK_ERROR(rv) { g_module_set_error (NULL); }
106 #if     (G_MODULE_IMPL == G_MODULE_IMPL_DL)
107 #include "gmodule-dl.c"
108 #elif   (G_MODULE_IMPL == G_MODULE_IMPL_DLD)
109 #include "gmodule-dld.c"
110 #else
111 #undef  CHECK_ERROR
112 #define CHECK_ERROR(rv) { g_module_set_error ("unsupported"); return rv; }
113 static gpointer
114 _g_module_open (const gchar     *file_name,
115                 gboolean         bind_lazy)
116 {
117   return NULL;
118 }
119 static void
120 _g_module_close (gpointer        handle,
121                  gboolean        is_unref)
122 {
123 }
124 static gpointer
125 _g_module_self (void)
126 {
127   return NULL;
128 }
129 static gpointer
130 _g_module_symbol (gpointer       handle,
131                   const gchar   *symbol_name)
132 {
133   return NULL;
134 }
135 #endif  /* no implementation */
136
137
138 /* --- functions --- */
139 gboolean
140 g_module_supported (void)
141 {
142   CHECK_ERROR (FALSE);
143   
144   return TRUE;
145 }
146
147 GModule*
148 g_module_open (const gchar    *file_name,
149                GModuleFlags    flags)
150 {
151   GModule *module;
152   gpointer handle;
153   
154   CHECK_ERROR (NULL);
155   
156   if (!file_name)
157     {
158       if (!main_module)
159         {
160           handle = _g_module_self ();
161           if (handle)
162             {
163               main_module = g_new (GModule, 1);
164               main_module->file_name = NULL;
165               main_module->handle = handle;
166               main_module->ref_count = 1;
167               main_module->de_init = NULL;
168               main_module->next = NULL;
169             }
170         }
171       
172       return main_module;
173     }
174   
175   /* we first search the module list by name */
176   module = g_module_find_by_name (file_name);
177   if (module)
178     {
179       module->ref_count++;
180       
181       return module;
182     }
183   
184   /* open the module */
185   handle = _g_module_open (file_name, (flags & G_MODULE_BIND_LAZY) != 0);
186   if (handle)
187     {
188       gchar *saved_error;
189       GModuleCheckInit check_init;
190       const gchar *check_failed = NULL;
191       
192       /* search the module list by handle, since file names are not unique */
193       module = g_module_find_by_handle (handle);
194       if (module)
195         {
196           _g_module_close (module->handle, TRUE);
197           module->ref_count++;
198           g_module_set_error (NULL);
199           
200           return module;
201         }
202       
203       saved_error = module_error;
204       module_error = NULL;
205       g_module_set_error (NULL);
206       
207       module = g_new (GModule, 1);
208       module->file_name = g_strdup (file_name);
209       module->handle = handle;
210       module->ref_count = 1;
211       module->de_init = NULL;
212       module->next = modules;
213       modules = module;
214       
215       /* check initialization */
216       if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init))
217         check_failed = check_init (module);
218       
219       /* we don't call de_init() if the initialization check failed. */
220       if (!check_failed)
221         g_module_symbol (module, "g_module_de_init", (gpointer) &module->de_init);
222       
223       if (check_failed)
224         {
225           gchar *error;
226
227           error = g_strconcat ("GModule initialization check failed: ", check_failed, NULL);
228           g_module_close (module);
229           module = NULL;
230           g_module_set_error (error);
231           g_free (error);
232         }
233       else
234         g_module_set_error (saved_error);
235       g_free (saved_error);
236     }
237   
238   return module;
239 }
240
241 gboolean
242 g_module_close (GModule        *module)
243 {
244   CHECK_ERROR (FALSE);
245   
246   g_return_val_if_fail (module != NULL, FALSE);
247   g_return_val_if_fail (module->ref_count > 0, FALSE);
248   
249   if (module != main_module)
250     module->ref_count--;
251   
252   if (!module->ref_count && module->de_init)
253     module->de_init (module);
254   if (!module->ref_count)
255     {
256       GModule *last;
257       GModule *node;
258       
259       last = NULL;
260       node = modules;
261       while (node)
262         {
263           if (node == module)
264             {
265               if (last)
266                 last->next = node->next;
267               else
268                 modules = node->next;
269               break;
270             }
271           last = node;
272           node = last->next;
273         }
274       module->next = NULL;
275       
276       _g_module_close (module->handle, FALSE);
277       g_free (module->file_name);
278       
279       g_free (module);
280     }
281   
282   return module_error == NULL;
283 }
284
285 gchar*
286 g_module_error (void)
287 {
288   return module_error;
289 }
290
291 gboolean
292 g_module_symbol (GModule        *module,
293                  const gchar    *symbol_name,
294                  gpointer       *symbol)
295 {
296   if (symbol)
297     *symbol = NULL;
298   CHECK_ERROR (FALSE);
299   
300   g_return_val_if_fail (module != NULL, FALSE);
301   g_return_val_if_fail (symbol_name != NULL, FALSE);
302   g_return_val_if_fail (symbol != NULL, FALSE);
303   
304 #ifdef  G_MODULE_NEED_USCORE
305   symbol_name = g_strconcat ("_", symbol_name, NULL);
306   *symbol = _g_module_symbol (module->handle, symbol_name);
307   g_free (symbol_name);
308 #else   /* !G_MODULE_NEED_USCORE */
309   *symbol = _g_module_symbol (module->handle, symbol_name);
310 #endif  /* !G_MODULE_NEED_USCORE */
311   
312   if (module_error)
313     {
314       gchar *error;
315
316       error = g_strconcat ("`", symbol_name, "': ", module_error, NULL);
317       g_module_set_error (error);
318       g_free (error);
319       *symbol = NULL;
320       return FALSE;
321     }
322   
323   return TRUE;
324 }
325
326 gchar*
327 g_module_name (GModule *module)
328 {
329   g_return_val_if_fail (module != NULL, NULL);
330   
331   if (module == main_module)
332     return "main";
333   
334   return module->file_name;
335 }