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