modules: remove support for module unload and refcount.
[m4/ericb.git] / m4 / module.c
blobebedcffe81a267b8c8c1d8150a2b7f86fdba05af
1 /* GNU m4 -- A simple macro processor
2 Copyright (C) 1989-1994, 1998-1999, 2002-2008, 2010, 2013 Free
3 Software Foundation, Inc.
5 This file is part of GNU M4.
7 GNU M4 is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU M4 is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
23 #include "m4private.h"
24 #include "xvasprintf.h"
26 /* Define this to see runtime debug info. Implied by DEBUG. */
27 /*#define DEBUG_MODULES */
30 * This file implements dynamic modules in GNU M4. A module is a
31 * compiled shared object, that can be loaded into GNU M4 at run
32 * time. Information about creating modules is in ../modules/README.
34 * This implementation uses libltdl, which is in turn can open modules
35 * using either dlopen(3) (exists on GNU/Linux, OSF, Solaris, SunOS and
36 * others), shl_load(3) (exists on HPUX), LoadLibrary(3) (exists on
37 * Windows, cygwin, OS/2), load_add_on(3) (exists on BeOS), NSAddImage
38 * (exists on MacOS) and can also fall back to dld_link(3) from GNU
39 * libdld or lt_dlpreload from libtool if shared libraries are not
40 * available on the host machine.
42 * An M4 module will usually define an external symbol called
43 * `m4_builtin_table'. This symbol points to a table of `m4_builtin'.
44 * The table is saved as libltdl caller data and each definition therein
45 * is added to the symbol table.
47 * To load a module, call m4_module_load(), which searches for the
48 * module in directories from M4PATH. The search path is initialized
49 * from the environment variable M4PATH, followed by the configuration
50 * time default where the modules shipped with M4 itself are installed.
51 * `m4_module_load' returns NULL on failure, or else an opaque module
52 * handle for the newly mapped vm segment containing the module code.
53 * If the module is not already loaded, m4_module_load() retrieves its
54 * value for the symbol `m4_builtin_table', which is installed using
55 * set_module_builtin_table().
57 * In addition to builtin functions, you can also define static macro
58 * expansions in the `m4_macro_table' symbol. If you define this symbol
59 * in your modules, it should be an array of `m4_macro's, mapping macro
60 * names to the expansion text. Any macros defined in `m4_macro_table'
61 * are installed into the M4 symbol table with set_module_macro_table().
63 * Each time a module is loaded, the module function prototyped as
64 * "M4INIT_HANDLER (<module name>)" is called, if defined. Any value
65 * stored in OBS by this function becomes the expansion of the macro
66 * which called it.
67 **/
69 #define MODULE_SELF_NAME "!myself!"
71 static const char* module_dlerror (void);
73 static void install_builtin_table (m4*, m4_module *);
74 static void install_macro_table (m4*, m4_module *);
76 static int m4__module_interface (lt_dlhandle handle,
77 const char *id_string);
79 static lt_dlinterface_id iface_id = NULL;
81 const char *
82 m4_get_module_name (const m4_module *module)
84 const lt_dlinfo *info;
86 assert (module && module->handle);
88 info = lt_dlgetinfo (module->handle);
90 return info ? info->name : NULL;
93 void *
94 m4_module_import (m4 *context, const char *module_name,
95 const char *symbol_name, m4_obstack *obs)
97 m4_module * module = m4__module_find (module_name);
98 void * symbol_address = NULL;
100 /* Try to load the module if it is not yet available (errors are
101 diagnosed by m4_module_load). */
102 /* FIXME - should this use m4__module_open instead, to avoid
103 polluting the symbol table when importing a function? */
104 if (!module)
105 module = m4_module_load (context, module_name, obs);
107 if (module)
109 symbol_address = lt_dlsym (module->handle, symbol_name);
111 if (!symbol_address)
112 m4_error (context, 0, 0, NULL,
113 _("cannot load symbol `%s' from module `%s'"),
114 symbol_name, module_name);
117 return symbol_address;
120 static void
121 install_builtin_table (m4 *context, m4_module *module)
123 size_t i;
125 assert (context);
126 assert (module);
127 for (i = 0; i < module->builtins_len; i++)
129 m4_symbol_value *value = m4_symbol_value_create ();
130 const char *name = module->builtins[i].builtin.name;
132 m4__set_symbol_value_builtin (value, &module->builtins[i]);
133 if (m4_get_prefix_builtins_opt (context))
134 name = xasprintf ("m4_%s", name);
136 m4_symbol_pushdef (M4SYMTAB, name, strlen (name), value);
138 if (m4_get_prefix_builtins_opt (context))
139 DELETE (name);
141 if (i)
142 m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
143 _("module %s: builtins loaded"),
144 m4_get_module_name (module));
147 static void
148 install_macro_table (m4 *context, m4_module *module)
150 const m4_macro *mp;
152 assert (context);
153 assert (module);
155 mp = (const m4_macro *) lt_dlsym (module->handle, MACRO_SYMBOL);
157 if (mp)
159 for (; mp->name != NULL; mp++)
161 m4_symbol_value *value = m4_symbol_value_create ();
162 size_t len = strlen (mp->value);
164 /* Sanity check that builtins meet the required interface. */
165 assert (mp->min_args <= mp->max_args);
167 m4_set_symbol_value_text (value, xmemdup0 (mp->value, len), len, 0);
168 VALUE_MODULE (value) = module;
169 VALUE_MIN_ARGS (value) = mp->min_args;
170 VALUE_MAX_ARGS (value) = mp->max_args;
172 m4_symbol_pushdef (M4SYMTAB, mp->name, strlen (mp->name), value);
175 m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
176 _("module %s: macros loaded"),
177 m4_get_module_name (module));
181 m4_module *
182 m4_module_load (m4 *context, const char *name, m4_obstack *obs)
184 m4_module *module = m4__module_open (context, name, obs);
186 if (module)
188 const lt_dlinfo *info = lt_dlgetinfo (module->handle);
190 if (info->ref_count == 1)
192 install_builtin_table (context, module);
193 install_macro_table (context, module);
197 return module;
201 static int
202 m4__module_interface (lt_dlhandle handle, const char *id_string)
204 /* Shortcut. If we've already associated our wrapper with this
205 handle, then we've validated the handle in the past, and don't
206 need to waste any time on additional lt_dlsym calls. */
207 m4_module *module = (m4_module *) lt_dlcaller_get_data (iface_id, handle);
208 if (module)
209 return 0;
211 /* A valid m4 module must provide at least one of these symbols. */
212 return !(lt_dlsym (handle, INIT_SYMBOL)
213 || lt_dlsym (handle, BUILTIN_SYMBOL)
214 || lt_dlsym (handle, MACRO_SYMBOL));
218 /* Return successive loaded modules that pass the interface test registered
219 with the interface id. */
220 m4_module *
221 m4_module_next (m4_module *module)
223 lt_dlhandle handle = module ? module->handle : NULL;
224 assert (iface_id);
226 /* Resident modules still show up in the lt_dlhandle_iterate loop
227 after they have been unloaded from m4. */
230 handle = lt_dlhandle_iterate (iface_id, handle);
231 if (!handle)
232 return NULL;
233 module = (m4_module *) lt_dlcaller_get_data (iface_id, handle);
235 while (!module);
236 assert (module->handle == handle);
237 return module;
240 /* Return the first loaded module that passes the registered interface test
241 and is called NAME. */
242 m4_module *
243 m4__module_find (const char *name)
245 lt_dlhandle handle;
246 m4_module *module;
247 assert (iface_id);
249 handle = lt_dlhandle_fetch (iface_id, name);
250 if (!handle)
251 return NULL;
252 module = (m4_module *) lt_dlcaller_get_data (iface_id, handle);
253 if (module)
254 assert (module->handle == handle);
255 return module;
259 /* Initialization. Currently the module search path in path.c is
260 initialized from M4MODPATH. Only absolute path names are accepted to
261 prevent the path search of the dlopen library from finding wrong
262 files. */
263 void
264 m4__module_init (m4 *context)
266 int errors = 0;
268 /* Do this only once! If we already have an iface_id, then the
269 module system has already been initialized. */
270 if (iface_id)
272 m4_error (context, 0, 0, NULL,
273 _("multiple module loader initializations"));
274 return;
277 errors = lt_dlinit ();
279 /* Register with libltdl for a key to store client data against
280 ltdl module handles. */
281 if (!errors)
283 iface_id = lt_dlinterface_register ("m4 libm4", m4__module_interface);
285 if (!iface_id)
287 const char *error_msg = _("libltdl client registration failed");
289 lt_dlseterror (lt_dladderror (error_msg));
291 /* No need to check error statuses from the calls above -- If
292 either fails for some reason, a diagnostic will be set for
293 lt_dlerror() anyway. */
294 ++errors;
298 /* Couldn't initialize the module system; diagnose and exit. */
299 if (errors)
300 m4_error (context, EXIT_FAILURE, 0, NULL,
301 _("failed to initialize module loader: %s"), module_dlerror ());
303 #ifdef DEBUG_MODULES
304 fputs ("Module loader initialized.\n", stderr);
305 #endif /* DEBUG_MODULES */
309 /* Compare two builtins A and B for sorting, as in qsort. */
310 static int
311 compare_builtin_CB (const void *a, const void *b)
313 const m4__builtin *builtin_a = (const m4__builtin *) a;
314 const m4__builtin *builtin_b = (const m4__builtin *) b;
315 int result = strcmp (builtin_a->builtin.name, builtin_b->builtin.name);
316 /* A builtin module should never provide two builtins with the same
317 name. */
318 assert (result || a == b);
319 return result;
322 /* Load a module. NAME can be a absolute file name or, if relative,
323 it is searched for in the module path. The module is unloaded in
324 case of error. */
325 m4_module *
326 m4__module_open (m4 *context, const char *name, m4_obstack *obs)
328 static const char * suffixes[] = { "", ".la", LT_MODULE_EXT, NULL };
329 char * filepath = NULL;
330 lt_dlhandle handle = NULL;
331 lt_dladvise advise = NULL;
332 m4_module * module = NULL;
333 m4_module_init_func * init_func = NULL;
335 assert (context);
336 assert (iface_id); /* need to have called m4__module_init */
338 /* Try opening as a preloaded module initially incase path searching
339 has been disabled by POSIXLY_CORRECT... */
340 if (!lt_dladvise_init (&advise) && !lt_dladvise_preload (&advise))
341 handle = lt_dlopenadvise (name, advise);
342 lt_dladvise_destroy (&advise);
344 /* ...otherwise resort to a path search anyway. */
345 if (!handle)
347 filepath = m4_path_search (context, name, suffixes);
348 if (filepath)
350 handle = lt_dlopenext (filepath);
351 free (filepath);
355 if (handle)
357 const lt_dlinfo *info = lt_dlgetinfo (handle);
359 /* If we have a handle, there must be handle info. */
360 assert (info);
362 #ifdef DEBUG_MODULES
363 if (info->ref_count > 1)
365 xfprintf (stderr, "module %s: now has %d libtool references.",
366 name, info->ref_count);
368 #endif /* DEBUG_MODULES */
370 m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
371 _("module %s: opening file %s"),
372 name ? name : MODULE_SELF_NAME,
373 quotearg_style (locale_quoting_style, info->filename));
375 /* Provide the m4_module corresponding to the lt_dlhandle, if
376 not yet created. */
377 module = (m4_module *) lt_dlcaller_get_data (iface_id, handle);
378 if (!module)
380 void *old;
381 const char *err;
382 const m4_builtin *bp;
384 module = (m4_module *) xzalloc (sizeof *module);
385 module->handle = handle;
387 /* TODO - change module interface to return function pointer
388 that supplies both table and length of table, rather than
389 returning data pointer that must have a sentinel
390 entry? */
391 bp = (m4_builtin *) lt_dlsym (module->handle, BUILTIN_SYMBOL);
392 if (bp)
394 const m4_builtin *tmp;
395 m4__builtin *builtin;
396 for (tmp = bp; tmp->name; tmp++)
397 module->builtins_len++;
398 module->builtins =
399 (m4__builtin *) xnmalloc (module->builtins_len,
400 sizeof *module->builtins);
401 for (builtin = module->builtins; bp->name != NULL;
402 bp++, builtin++)
404 /* Sanity check that builtins meet the required
405 interface. */
406 assert (bp->min_args <= bp->max_args);
407 assert (bp->min_args > 0
408 || (bp->flags & (M4_BUILTIN_BLIND
409 | M4_BUILTIN_SIDE_EFFECT)) == 0);
410 assert (bp->max_args
411 || (bp->flags & M4_BUILTIN_FLATTEN_ARGS) == 0);
412 assert ((bp->flags & ~M4_BUILTIN_FLAGS_MASK) == 0);
414 memcpy (&builtin->builtin, bp, sizeof *bp);
415 builtin->builtin.name = xstrdup (bp->name);
416 builtin->module = module;
419 qsort (module->builtins, module->builtins_len,
420 sizeof *module->builtins, compare_builtin_CB);
422 /* clear out any stale errors, since we have to use
423 lt_dlerror to distinguish between success and
424 failure. */
425 lt_dlerror ();
426 old = lt_dlcaller_set_data (iface_id, handle, module);
427 assert (!old);
428 err = lt_dlerror ();
429 if (err)
430 m4_error (context, EXIT_FAILURE, 0, NULL,
431 _("unable to load module `%s': %s"), name, err);
434 /* Find and run any initializing function in the opened module,
435 each time the module is opened. */
436 init_func = (m4_module_init_func *) lt_dlsym (handle, INIT_SYMBOL);
437 if (init_func)
439 init_func (context, module, obs);
441 m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
442 _("module %s: init hook called"), name);
444 else if (!lt_dlsym (handle, BUILTIN_SYMBOL)
445 && !lt_dlsym (handle, MACRO_SYMBOL))
447 m4_error (context, EXIT_FAILURE, 0, NULL,
448 _("module `%s' has no entry points"), name);
451 m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
452 _("module %s: opened"), name);
454 else
456 /* Couldn't open the module; diagnose and exit. */
457 m4_error (context, EXIT_FAILURE, 0, NULL,
458 _("cannot open module `%s': %s"), name, module_dlerror ());
461 return module;
465 /* FIXME - libtool doesn't expose lt_dlerror strings for translation. */
466 static const char *
467 module_dlerror (void)
469 const char *dlerror = lt_dlerror ();
471 if (!dlerror)
472 dlerror = _("unknown error");
474 return dlerror;