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