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