fix cmopiler warnings. check (de)initialization code.
[platform/upstream/glib.git] / gmodule / gmodule.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
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 (http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html).
28  * Also, the module for the program itself is kept seperatedly for
29  * faster access.
30  */
31
32
33 /* --- structures --- */
34 struct _GModule
35 {
36   gchar *file_name;
37   gpointer handle;
38   guint ref_count;
39   GModuleDeInit de_init;
40   GModule *next;
41 };
42
43
44 /* --- prototypes --- */
45 static gpointer         _g_module_open          (const gchar    *file_name,
46                                                  gboolean        bind_lazy);
47 static void             _g_module_close         (gpointer       *handle_p,
48                                                  gboolean        is_unref);
49 static gpointer         _g_module_self          (void);
50 static gpointer         _g_module_symbol        (gpointer       *handle_p,
51                                                  const gchar    *symbol_name);
52 static inline void      g_module_set_error      (const gchar    *error);
53 static inline GModule*  g_module_find_by_handle (gpointer        handle);
54 static inline GModule*  g_module_find_by_name   (const gchar    *name);
55
56
57 /* --- variables --- */
58 static GModule  *modules = NULL;
59 static GModule  *main_module = NULL;
60 static gchar    *module_error = NULL;
61
62
63 /* --- inline functions --- */
64 static inline GModule*
65 g_module_find_by_handle (gpointer handle)
66 {
67   GModule *module;
68
69   for (module = modules; module; module = module->next)
70     if (handle == module->handle)
71       return module;
72   return NULL;
73 }
74
75 static inline GModule*
76 g_module_find_by_name (const gchar *name)
77 {
78   GModule *module;
79
80   for (module = modules; module; module = module->next)
81     if (strcmp (name, module->file_name) == 0)
82       return module;
83   return NULL;
84 }
85
86 static inline void
87 g_module_set_error (const gchar *error)
88 {
89   if (module_error)
90     g_free (module_error);
91   if (error)
92     module_error = g_strdup (error);
93   else
94     module_error = NULL;
95   errno = 0;
96 }
97
98
99 /* --- include platform specifc code --- */
100 #define CHECK_ERROR(rv) { g_module_set_error (NULL); }
101 #if     (G_MODULE_IMPL == G_MODULE_IMPL_DL)
102 #include "gmodule-dl.c"
103 #elif   (G_MODULE_IMPL == G_MODULE_IMPL_DLD)
104 #include "gmodule-dld.c"
105 #else
106 #undef  CHECK_ERROR
107 #define CHECK_ERROR(rv) { g_module_set_error ("unsupported"); return rv; }
108 #endif  /* no implementation */
109
110
111 /* --- functions --- */
112 gboolean
113 g_module_supported (void)
114 {
115   CHECK_ERROR (FALSE);
116
117   return TRUE;
118 }
119
120 GModule*
121 g_module_open (const gchar    *file_name,
122                GModuleFlags    flags)
123 {
124   GModule *module;
125   gpointer handle;
126
127   CHECK_ERROR (NULL);
128
129   if (!file_name)
130     {
131       if (!main_module)
132         {
133           handle = _g_module_self ();
134           if (handle)
135             {
136               main_module = g_new (GModule, 1);
137               main_module->file_name = NULL;
138               main_module->handle = handle;
139               main_module->ref_count = 1;
140               main_module->de_init = NULL;
141               main_module->next = NULL;
142             }
143         }
144
145       return main_module;
146     }
147
148   /* we first search the module list by name */
149   module = g_module_find_by_name (file_name);
150   if (module)
151     {
152       module->ref_count++;
153
154       return module;
155     }
156
157   /* open the module */
158   handle = _g_module_open (file_name, (flags & G_MODULE_BIND_LAZY) != 0);
159   if (handle)
160     {
161       gchar *saved_error;
162       GModuleCheckInit check_init;
163       gboolean check_failed = FALSE;
164
165       /* search the module list by handle, since file names are not unique */
166       module = g_module_find_by_handle (handle);
167       if (module)
168         {
169           _g_module_close (&module->handle, TRUE);
170           module->ref_count++;
171           g_module_set_error (NULL);
172
173           return module;
174         }
175
176       saved_error = module_error;
177       module_error = NULL;
178       g_module_set_error (NULL);
179
180       module = g_new (GModule, 1);
181       module->file_name = g_strdup (file_name);
182       module->handle = handle;
183       module->ref_count = 0;
184       module->de_init = NULL;
185       module->next = NULL;
186
187       /* check initialization */
188       if (g_module_symbol (module, "g_module_check_init", &check_init))
189         check_failed = check_init (module);
190
191       /* should call de_init() on failed initializations also? */
192       if (!check_failed)
193         g_module_symbol (module, "g_module_de_init", &module->de_init);
194
195       module->ref_count += 1;
196       module->next = modules;
197       modules = module;
198
199       if (check_failed)
200         {
201           g_module_close (module);
202           module = NULL;
203           g_module_set_error ("GModule initialization check failed");
204         }
205       else
206         g_module_set_error (saved_error);
207       g_free (saved_error);
208     }
209
210   return module;
211 }
212
213 gboolean
214 g_module_close (GModule        *module)
215 {
216   CHECK_ERROR (FALSE);
217
218   g_return_val_if_fail (module != NULL, FALSE);
219   g_return_val_if_fail (module->ref_count > 0, FALSE);
220
221   if (module != main_module)
222     module->ref_count--;
223
224   if (!module->ref_count)
225     {
226       GModule *last;
227       GModule *node;
228
229       last = NULL;
230       node = modules;
231       while (node)
232         {
233           if (node == module)
234             {
235               if (last)
236                 last->next = node->next;
237               else
238                 modules = node->next;
239               break;
240             }
241           last = node;
242           node = last->next;
243         }
244       module->next = NULL;
245
246       if (module->de_init)
247         module->de_init (module);
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 }