[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
FYI: 38-gary-inter-module-symbol-importing.patch
From: |
Gary V. Vaughan |
Subject: |
FYI: 38-gary-inter-module-symbol-importing.patch |
Date: |
Tue, 12 Aug 2003 16:35:24 +0100 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5b) Gecko/20030804 |
Applied to HEAD.
--
())_. Gary V. Vaughan gary@(oranda.demon.co.uk|gnu.org)
( '/ Research Scientist http://www.oranda.demon.co.uk ,_())____
/ )= GNU Hacker http://www.gnu.org/software/libtool \' `&
`(_~)_ Tech' Author http://sources.redhat.com/autobook =`---d__/
Index: ChangeLog
from Gary V. Vaughan <address@hidden>
Libltdl already has an excellent mechanism for accessing C symbols
in modules. Lets use that! Remove all the exporting cruft and
just use lt_dlsym in conjunction with a few conventions to
simplify module writers' jobs. Also removed the table address
caching code and otherwise simplified the module loader quite a
bit. To access exported symbols in other modules, first the
exporting module must name the symbols <modname>_LTX_<symname>,
and the importing module must define a function type called
<symname>_func. The importer then adds
M4_MODULE_IMPORT(<modname>, <symname>) at the top of any function
that wishes to call out to the exported functions. Care must be
taken that <symname> is non-NULL in the importing module incase
M4_MODULE_IMPORT fails, but otherwise it can be called as if the
definition was in the importers source. Study
`modules/{gnu.c,m4.{c,h}' for a model example. At the moment,
m4_module_import will attempt to automatically load a module
required for symbol access if it is not loaded already.
* TODO: Removed the items fixed in this delta.
* m4/ltdl.c (lt_dlhandle_find): New function to find a handle by
module name.
* m4/ltdl.h (lt_dlhandle_find): Declare it.
* m4/module.c (m4_module_unload): Use it.
* src/freeze.c (reload_frozen_state): Ditto.
* m4/m4module.h (m4_export): Deleted. Removed all references.
(M4_MODULE_IMPORT): New user convenience macro for importing
arbitrary symbols from other modules.
* m4/module.c (m4_module_import): New function to service
M4_MODULE_IMPORT macro.
(module_data): Removed. Looking up the tables on demand with
lt_dlsym, rather than caching their addresses here simplifies the
code substantially.
(m4_get_module_builtin_table, m4_get_module_macro_table):
Removed. Changed all callers.
(set_module_macro_table, set_module_builtin_table): Renamed to
install_macro_table and install_builtin_table respectively, and
simplified now that the cache is no more.
* modules/gnu.c (builtin_symbols): Use this new mechanism to
import m4_dump_symbols from the m4 module.
(builtin_esyscmd): Likewise for m4_set_sysval and
m4_sysval_flush.
* modules/m4.c (m4_export_table): Removed. Functions are
addressed with the new mechanism which doesn't need this.
(m4_set_sysval): New exported accessor function to prevent
problems with variable access on inferior architectures.
* modules/m4.h (m4_sysval_flush_func, m4_set_sysval_func)
(m4_dump_symbols_func): Typedefs required by M4_MODULE_IMPORT so
that we can have some type safety.
* modules/modtest.c (export_test): C level exported function for
testing the new import mechanism.
* modules/import.c: New file for the import end of the test.
* modules/Makefile.am (pkglibexec_LTLIBRARIES): Added import.la.
* tests/modules.at: New test cases for intermodule symbol
importing.
Index: TODO
===================================================================
RCS file: /cvsroot/m4/m4/TODO,v
retrieving revision 1.12
diff -u -p -u -r1.12 TODO
--- TODO 29 Jul 2003 15:57:33 -0000 1.12
+++ TODO 12 Aug 2003 15:32:23 -0000
@@ -108,20 +108,6 @@ for any of these ideas or if you have ot
asked to load a frozen file that requires versions of modules with
interface versions unsupported by the current release.
- + Some liberties are take with preloaded modules using one another's
- symbols. This only works (portably) because the modules that do it
- (m4.so and gnu.so) are both statically linked into the core. Need to
- investigate how this can be supported for any module, on platforms that
- don't support backlinking. Maybe exporting symbol name/address pairs
- into a table maintained by libm4, and only using module symbols through
- that table in other modules.
-
- + On a related note, modules should be able to declare that they require
- other modules to be loaded before they can work -- and the module loader
- should take care of that. Should such required modules be fully loaded
- into the symbol table? Or merely loaded into memory so that the C level
- code is callable?
-
+ Setting of the module search path within m4 scripts:
append(__modulepath__, `/some/modules/live/here')
Index: m4/builtin.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/builtin.c,v
retrieving revision 1.20
diff -u -p -u -r1.20 builtin.c
--- m4/builtin.c 17 Jun 2003 15:17:45 -0000 1.20
+++ m4/builtin.c 12 Aug 2003 15:32:24 -0000
@@ -23,44 +23,50 @@
#include "m4.h"
#include "m4private.h"
-/* Find the builtin, which has NAME. If BP argument is supplied
- then search only in table BP. */
+/* Find the builtin which has NAME. If HANDLE argument is supplied
+ then search only in HANDLE's builtin table. */
const m4_builtin *
-m4_builtin_find_by_name (const m4_builtin *bp, const char *name)
+m4_builtin_find_by_name (lt_dlhandle handle, const char *name)
{
- lt_dlhandle handle = NULL;
+ lt_dlhandle cur = handle ? handle : lt_dlhandle_next (0);
- while ((handle = lt_dlhandle_next (handle)))
+ do
{
- m4_builtin *builtin = m4_get_module_builtin_table (handle);
+ const m4_builtin *builtin =
+ (const m4_builtin *) lt_dlsym (cur, BUILTIN_SYMBOL);
- if (builtin && (bp == NULL || bp == builtin))
+ if (builtin)
{
for (; builtin->name != NULL; builtin++)
- if (strcmp (builtin->name, name) == 0)
+ if (!strcmp (builtin->name, name))
return builtin;
}
}
+ while (!handle && (cur = lt_dlhandle_next (cur)));
- return NULL;
+ return 0;
}
+/* Find the builtin which has FUNC. If HANDLE argument is supplied
+ then search only in HANDLE's builtin table. */
const m4_builtin *
-m4_builtin_find_by_func (const m4_builtin *bp, m4_builtin_func *func)
+m4_builtin_find_by_func (lt_dlhandle handle, m4_builtin_func *func)
{
- lt_dlhandle handle = NULL;
+ lt_dlhandle cur = handle ? handle : lt_dlhandle_next (0);
- while ((handle = lt_dlhandle_next (handle)))
+ do
{
- m4_builtin *builtin = m4_get_module_builtin_table (handle);
+ const m4_builtin *builtin =
+ (const m4_builtin *) lt_dlsym (cur, BUILTIN_SYMBOL);
- if (builtin && (bp == NULL || bp == builtin))
+ if (builtin)
{
for (; builtin->name != NULL; builtin++)
if (builtin->func == func)
return builtin;
}
}
+ while (!handle && (cur = lt_dlhandle_next (cur)));
- return NULL;
+ return 0;
}
Index: m4/ltdl.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/ltdl.c,v
retrieving revision 1.13
diff -u -p -u -r1.13 ltdl.c
--- m4/ltdl.c 30 May 2003 15:13:32 -0000 1.13
+++ m4/ltdl.c 12 Aug 2003 15:32:24 -0000
@@ -4135,6 +4135,22 @@ lt_dlhandle_next (place)
return place ? place->next : handles;
}
+lt_dlhandle
+lt_dlhandle_find (module_name)
+ const char *module_name;
+{
+ lt_dlhandle cur = handles;
+
+ if (cur)
+ do
+ {
+ if (cur->info.name && strcmp (cur->info.name, module_name) == 0)
+ break;
+ } while (cur = cur->next);
+
+ return cur;
+}
+
int
lt_dlforeach (func, data)
int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
Index: m4/ltdl.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/ltdl.h,v
retrieving revision 1.5
diff -u -p -u -r1.5 ltdl.h
--- m4/ltdl.h 13 Aug 2001 23:37:44 -0000 1.5
+++ m4/ltdl.h 12 Aug 2003 15:32:24 -0000
@@ -243,6 +243,8 @@ typedef struct {
extern const lt_dlinfo *lt_dlgetinfo LT_PARAMS((lt_dlhandle handle));
extern lt_dlhandle lt_dlhandle_next LT_PARAMS((lt_dlhandle place));
+extern lt_dlhandle lt_dlhandle_find LT_PARAMS((
+ const char *module_name));
extern int lt_dlforeach LT_PARAMS((
int (*func) (lt_dlhandle handle, lt_ptr data),
lt_ptr data));
Index: m4/m4module.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4module.h,v
retrieving revision 1.64
diff -u -p -u -r1.64 m4module.h
--- m4/m4module.h 7 Aug 2003 14:42:48 -0000 1.64
+++ m4/m4module.h 12 Aug 2003 15:32:24 -0000
@@ -29,26 +29,31 @@ BEGIN_C_DECLS
-/* Various declarations. */
+/* --- MODULE AUTHOR DECLARATIONS --- */
typedef struct m4 m4;
-typedef struct obstack m4_obstack;
+typedef struct m4_builtin m4_builtin;
+typedef struct m4_macro m4_macro;
typedef struct m4_symbol_value m4_symbol_value;
+
+typedef struct obstack m4_obstack;
+typedef lt_dlsymlist m4_export;
+
typedef void m4_builtin_func (m4 *, m4_obstack *, int, m4_symbol_value **);
-typedef struct {
+struct m4_builtin
+{
const char * name;
m4_builtin_func * func;
boolean groks_macro_args, blind_if_no_args;
int min_args, max_args;
-} m4_builtin;
+};
-typedef struct {
+struct m4_macro
+{
const char *name;
const char *value;
-} m4_macro;
-
-typedef lt_dlsymlist m4_export;
+};
#define M4BUILTIN(name) \
@@ -71,6 +76,10 @@ typedef lt_dlsymlist m4_export;
void CONC(name, CONC(_LTX_, m4_finish_module)) \
(m4 *context, lt_dlhandle handle, m4_obstack *obs)
+#define M4_MODULE_IMPORT(M, S) \
+ CONC(S, _func) *S = (CONC(S, _func) *) \
+ m4_module_import (context, STR(M), STR(S), obs)
+
#define M4ARG(i) (argc > (i) ? m4_get_symbol_value_text (argv[i]) : "")
extern boolean m4_bad_argc (m4 *, int, m4_symbol_value **,
@@ -143,12 +152,12 @@ m4_context_opt_bit_table
typedef void m4_module_init_func (m4 *, lt_dlhandle, m4_obstack*);
typedef void m4_module_finish_func (m4 *, lt_dlhandle, m4_obstack*);
-extern lt_dlhandle m4_module_load (m4 *, const char*, m4_obstack*);
-extern void m4_module_unload (m4 *, const char*, m4_obstack*);
+extern lt_dlhandle m4_module_load (m4 *, const char*, m4_obstack*);
+extern void m4_module_unload (m4 *, const char*, m4_obstack*);
+extern void * m4_module_import (m4 *, const char*, const char*,
+ m4_obstack*);
-extern const char *m4_get_module_name (lt_dlhandle);
-extern m4_builtin *m4_get_module_builtin_table (lt_dlhandle);
-extern m4_macro *m4_get_module_macro_table (lt_dlhandle);
+extern const char * m4_get_module_name (lt_dlhandle);
@@ -207,10 +216,9 @@ extern void m4_set_symbol_value_func (
/* --- BUILTIN MANAGEMENT --- */
-extern const m4_builtin *m4_builtin_find_by_name (
- const m4_builtin *, const char *);
-extern const m4_builtin *m4_builtin_find_by_func (
- const m4_builtin *, m4_builtin_func *);
+extern const m4_builtin *m4_builtin_find_by_name (lt_dlhandle, const char *);
+extern const m4_builtin *m4_builtin_find_by_func (lt_dlhandle,
+ m4_builtin_func *);
Index: m4/module.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/module.c,v
retrieving revision 1.26
diff -u -p -u -r1.26 module.c
--- m4/module.c 23 Jul 2003 16:20:50 -0000 1.26
+++ m4/module.c 12 Aug 2003 15:32:24 -0000
@@ -79,19 +79,14 @@
#define MODULE_SELF_NAME "!myself!"
-typedef struct {
- m4_builtin *builtin_table;
- m4_macro *macro_table;
-} module_data;
-
static const char* module_dlerror (void);
static int module_remove (m4 *context, lt_dlhandle handle,
m4_obstack *obs);
static void module_close (m4 *context, lt_dlhandle handle,
m4_obstack *obs);
-static void set_module_macro_table (m4*, lt_dlhandle, const m4_macro*);
-static void set_module_builtin_table (m4*, lt_dlhandle, const m4_builtin*);
+static const m4_builtin * install_builtin_table (m4*, lt_dlhandle);
+static const m4_macro * install_macro_table (m4*, lt_dlhandle);
static lt_dlcaller_id caller_id = 0;
@@ -107,93 +102,112 @@ m4_get_module_name (lt_dlhandle handle)
return info ? info->name : 0;
}
-m4_builtin *
-m4_get_module_builtin_table (lt_dlhandle handle)
+void *
+m4_module_import (m4 *context, const char *module_name,
+ const char *symbol_name, m4_obstack *obs)
{
- module_data *data;
+ lt_dlhandle handle = lt_dlhandle_find (module_name);
+ lt_ptr symbol_address = 0;
- assert (handle);
+ /* Try to load the module if it is not yet available (errors are
+ diagnosed by m4_module_load). */
+ if (!handle)
+ handle = m4_module_load (context, module_name, obs);
- data = lt_dlcaller_get_data (caller_id, handle);
+ if (handle)
+ {
+ symbol_address = lt_dlsym (handle, symbol_name);
- return data ? data->builtin_table : 0;
+ if (!symbol_address)
+ M4ERROR ((m4_get_warning_status_opt (context), 0,
+ _("Warning: cannot load symbol `%s' from module `%s'"),
+ symbol_name, module_name));
+ }
+
+ return (void *) symbol_address;
}
-static void
-set_module_builtin_table (m4 *context, lt_dlhandle handle,
- const m4_builtin *table)
+static const m4_builtin *
+install_builtin_table (m4 *context, lt_dlhandle handle)
{
const m4_builtin *bp;
assert (context);
assert (handle);
- assert (table);
- for (bp = table; bp->name != NULL; bp++)
+ bp = (const m4_builtin *) lt_dlsym (handle, BUILTIN_SYMBOL);
+ if (bp)
{
- m4_symbol_value *value = m4_symbol_value_create ();
- char * name;
-
- m4_set_symbol_value_func (value, bp->func);
- VALUE_HANDLE (value) = handle;
- VALUE_MIN_ARGS (value) = bp->min_args;
- VALUE_MAX_ARGS (value) = bp->max_args;
-
- if (bp->groks_macro_args)
- BIT_SET (VALUE_FLAGS (value), VALUE_MACRO_ARGS_BIT);
- if (bp->blind_if_no_args)
- BIT_SET (VALUE_FLAGS (value), VALUE_BLIND_ARGS_BIT);
-
- if (m4_get_prefix_builtins_opt (context))
+ for (; bp->name != NULL; bp++)
{
- static const char prefix[] = "m4_";
- size_t len = strlen (prefix) + strlen (bp->name);
+ m4_symbol_value *value = m4_symbol_value_create ();
+ char * name;
- name = (char *) xmalloc (1+ len);
- snprintf (name, 1+ len, "%s%s", prefix, bp->name);
- }
- else
- name = (char *) bp->name;
+ m4_set_symbol_value_func (value, bp->func);
+ VALUE_HANDLE (value) = handle;
+ VALUE_MIN_ARGS (value) = bp->min_args;
+ VALUE_MAX_ARGS (value) = bp->max_args;
+
+ if (bp->groks_macro_args)
+ BIT_SET (VALUE_FLAGS (value), VALUE_MACRO_ARGS_BIT);
+ if (bp->blind_if_no_args)
+ BIT_SET (VALUE_FLAGS (value), VALUE_BLIND_ARGS_BIT);
+ if (m4_get_prefix_builtins_opt (context))
+ {
+ static const char prefix[] = "m4_";
+ size_t len = strlen (prefix) + strlen (bp->name);
- m4_symbol_pushdef (M4SYMTAB, name, value);
+ name = (char *) xmalloc (1+ len);
+ snprintf (name, 1+ len, "%s%s", prefix, bp->name);
+ }
+ else
+ name = (char *) bp->name;
- if (m4_get_prefix_builtins_opt (context))
- xfree (name);
- }
-}
+ m4_symbol_pushdef (M4SYMTAB, name, value);
-m4_macro *
-m4_get_module_macro_table (lt_dlhandle handle)
-{
- module_data *data;
-
- assert (handle);
+ if (m4_get_prefix_builtins_opt (context))
+ xfree (name);
+ }
- data = lt_dlcaller_get_data (caller_id, handle);
+#ifdef DEBUG_MODULES
+ M4_DEBUG_MESSAGE1("module %s: builtins loaded",
+ m4_get_module_name (handle));
+#endif /* DEBUG_MODULES */
+ }
- return data ? data->macro_table : 0;
+ return bp;
}
-static void
-set_module_macro_table (m4 *context, lt_dlhandle handle,
- const m4_macro *table)
+static const m4_macro *
+install_macro_table (m4 *context, lt_dlhandle handle)
{
const m4_macro *mp;
assert (context);
assert (handle);
- assert (table);
- for (mp = table; mp->name != NULL; mp++)
+ mp = (const m4_macro *) lt_dlsym (handle, MACRO_SYMBOL);
+
+ if (mp)
{
- m4_symbol_value *value = m4_symbol_value_create ();
+ for (; mp->name != NULL; mp++)
+ {
+ m4_symbol_value *value = m4_symbol_value_create ();
+
+ m4_set_symbol_value_text (value, xstrdup (mp->value));
+ VALUE_HANDLE (value) = handle;
- m4_set_symbol_value_text (value, xstrdup (mp->value));
- VALUE_HANDLE (value) = handle;
+ m4_symbol_pushdef (M4SYMTAB, mp->name, value);
+ }
- m4_symbol_pushdef (M4SYMTAB, mp->name, value);
+#ifdef DEBUG_MODULES
+ M4_DEBUG_MESSAGE1("module %s: macros loaded",
+ m4_get_module_name (handle));
+#endif /* DEBUG_MODULES */
}
+
+ return mp;
}
lt_dlhandle
@@ -201,46 +215,26 @@ m4_module_load (m4 *context, const char
{
const lt_dlhandle handle = m4__module_open (context, name, obs);
- /* If name is not set we are getting a reflective handle, but we
- might need to display an error message later so we set an appropriate
- value here. */
- if (!name)
- name = MODULE_SELF_NAME;
-
if (handle)
{
const lt_dlinfo *info = lt_dlgetinfo (handle);
if (!info)
{
+ /* If name is not set we are getting a reflective handle, but we
+ need to display an error message so we set an appropriate
+ value here. */
+ if (!name)
+ name = MODULE_SELF_NAME;
+
M4ERROR ((m4_get_warning_status_opt (context), 0,
_("Warning: cannot load module `%s': %s"),
name, module_dlerror ()));
}
else if (info->ref_count == 1)
{
- const m4_builtin *builtin_table
- = m4_get_module_builtin_table (handle);
- const m4_macro *macro_table
- = m4_get_module_macro_table (handle);
-
- /* Install the macro functions. */
- if (builtin_table)
- {
- set_module_builtin_table (context, handle, builtin_table);
-#ifdef DEBUG_MODULES
- M4_DEBUG_MESSAGE1("module %s: builtins loaded", name);
-#endif /* DEBUG_MODULES */
- }
-
- /* Install the user macros. */
- if (macro_table)
- {
- set_module_macro_table (context, handle, macro_table);
-#ifdef DEBUG_MODULES
- M4_DEBUG_MESSAGE1("module %s: macros loaded", name);
-#endif /* DEBUG_MODULES */
- }
+ install_builtin_table (context, handle);
+ install_macro_table (context, handle);
}
}
@@ -254,12 +248,10 @@ m4_module_unload (m4 *context, const cha
lt_dlhandle handle = 0;
int errors = 0;
- /* Scan the list for the first module with a matching name. */
- while ((handle = lt_dlhandle_next (handle)))
- {
- if (name && (strcmp (name, m4_get_module_name (handle)) == 0))
- break;
- }
+ assert (context);
+
+ if (name)
+ handle = lt_dlhandle_find (name);
if (!handle)
{
@@ -358,22 +350,22 @@ lt_dlhandle
m4__module_open (m4 *context, const char *name, m4_obstack *obs)
{
lt_dlhandle handle = lt_dlopenext (name);
- m4_module_init_func *init_func = 0;
- m4_builtin *builtin_table = 0;
- m4_macro *macro_table = 0;
+ m4_module_init_func * init_func = 0;
+
+ assert (context);
+ assert (caller_id);
if (handle)
{
-#ifdef DEBUG_MODULES
const lt_dlinfo *info = lt_dlgetinfo (handle);
- M4_DEBUG_MESSAGE2("module %s: opening at %s", name, info->filename);
-#endif
- /* Find the builtin table in the opened module. */
- builtin_table = (m4_builtin *) lt_dlsym (handle, BUILTIN_SYMBOL);
+ /* If we have a handle, there must be handle info. */
+ assert (info);
- /* Find the macro table in the opened module. */
- macro_table = (m4_macro *) lt_dlsym (handle, MACRO_SYMBOL);
+#ifdef DEBUG_MODULES
+ M4_DEBUG_MESSAGE2("module %s: opening at %s",
+ name ? name : MODULE_SELF_NAME, info->filename);
+#endif
/* Find and run any initialising function in the opened module,
each time the module is opened. */
@@ -386,6 +378,20 @@ m4__module_open (m4 *context, const char
M4_DEBUG_MESSAGE1("module %s: init hook called", name);
#endif /* DEBUG_MODULES */
}
+
+ if (!init_func
+ && !lt_dlsym (handle, FINISH_SYMBOL)
+ && !lt_dlsym (handle, BUILTIN_SYMBOL)
+ && !lt_dlsym (handle, MACRO_SYMBOL))
+ {
+ M4ERROR ((EXIT_FAILURE, 0,
+ _("module `%s' has no entry points"),
+ name));
+ }
+
+#ifdef DEBUG_MODULES
+ M4_DEBUG_MESSAGE1("module %s: opened", name);
+#endif /* DEBUG_MODULES */
}
else
{
@@ -395,48 +401,6 @@ m4__module_open (m4 *context, const char
name, module_dlerror ()));
}
- if (!builtin_table && !macro_table && !init_func)
- {
- /* Since we don't use it here, only check for the finish hook
- if we were about to diagnose a module with no entry points. */
- if (!lt_dlsym (handle, FINISH_SYMBOL))
- M4ERROR ((EXIT_FAILURE, 0,
- _("module `%s' has no entry points"),
- name));
- }
-
- /* If the module was correctly opened and has the necessary
- symbols, then store some client data for the new module
- on the first open only. */
- if (handle)
- {
- const lt_dlinfo *info = lt_dlgetinfo (handle);
-
- if (info && (info->ref_count == 1))
- {
- module_data *data = XMALLOC (module_data, 1);
- module_data *stale = 0;
-
- data->builtin_table = builtin_table;
- data->macro_table = macro_table;
-
- stale = lt_dlcaller_set_data (caller_id, handle, data);
-
- if (stale)
- {
- xfree (stale);
-
- M4ERROR ((m4_get_warning_status_opt (context), 0,
- _("Warning: overiding stale caller data in module
`%s'"),
- name));
- }
-
-#ifdef DEBUG_MODULES
- M4_DEBUG_MESSAGE1("module %s: opened", name);
-#endif /* DEBUG_MODULES */
- }
- }
-
return handle;
}
@@ -451,15 +415,6 @@ m4__module_exit (m4 *context)
lt_dlhandle pending = handle;
const lt_dlinfo *info = lt_dlgetinfo (pending);
- /* We are *really* shutting down here, so freeing the module
- data is required. */
- if (info)
- {
- module_data *stale
- = lt_dlcaller_set_data (caller_id, handle, 0);
- XFREE (stale);
- }
-
/* If we are about to unload the final reference, move on to the
next handle before we unload the current one. */
if (info->ref_count <= 1)
@@ -519,17 +474,6 @@ module_close (m4 *context, lt_dlhandle h
if (!lt_dlisresident (handle))
{
- const lt_dlinfo *info = lt_dlgetinfo (handle);
-
- /* When we are about to unload the module for the final
- time, be sure to release any client data memory. */
- if (info && (info->ref_count == 1))
- {
- module_data *stale
- = lt_dlcaller_set_data (caller_id, handle, 0);
- XFREE (stale);
- }
-
errors = lt_dlclose (handle);
if (!errors)
{
Index: m4/path.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/path.c,v
retrieving revision 1.5
diff -u -p -u -r1.5 path.c
--- m4/path.c 29 Jul 2003 15:57:34 -0000 1.5
+++ m4/path.c 12 Aug 2003 15:32:26 -0000
@@ -169,7 +169,7 @@ m4_path_search (m4 *context, const char
#ifdef DEBUG_INCL
static void
-include_dump (void)
+include_dump (m4 *context)
{
m4__search_path *incl;
Index: m4/symtab.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/symtab.c,v
retrieving revision 1.42
diff -u -p -u -r1.42 symtab.c
--- m4/symtab.c 24 Jul 2003 14:21:02 -0000 1.42
+++ m4/symtab.c 12 Aug 2003 15:32:26 -0000
@@ -524,8 +524,7 @@ static void *dump_symbol_CB (m4_symbol_t
break;
case M4_SYMBOL_FUNC:
- bp = m4_builtin_find_by_func (m4_get_module_builtin_table (handle),
- m4_get_symbol_func (symbol));
+ bp = m4_builtin_find_by_func (handle, m4_get_symbol_func (symbol));
fprintf (stderr, "<%s>",
bp ? bp->name : "!ERROR!");
break;
Index: modules/Makefile.am
===================================================================
RCS file: /cvsroot/m4/m4/modules/Makefile.am,v
retrieving revision 1.20
diff -u -p -u -r1.20 Makefile.am
--- modules/Makefile.am 24 Jul 2003 14:21:03 -0000 1.20
+++ modules/Makefile.am 12 Aug 2003 15:32:26 -0000
@@ -36,7 +36,7 @@ AM_LDFLAGS = -no-undefined
pkgmodinc_HEADERS = m4.h
pkglibexec_LTLIBRARIES = gnu.la load.la m4.la \
traditional.la perl.la \
- modtest.la shadow.la stdlib.la time.la
+ modtest.la shadow.la import.la stdlib.la time.la
if USE_GMP
pkglibexec_LTLIBRARIES += mpeval.la
@@ -63,6 +63,9 @@ traditional_la_LDFLAGS = -module
modtest_la_SOURCES = modtest.c
modtest_la_LDFLAGS = -module
+
+import_la_SOURCES = import.c
+import_la_LDFLAGS = -module
perl_la_SOURCES = perl.c
perl_la_CFLAGS = `perl -MExtUtils::Embed -e ccopts`
Index: modules/gnu.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/gnu.c,v
retrieving revision 1.29
diff -u -p -u -r1.29 gnu.c
--- modules/gnu.c 24 Jul 2003 14:21:03 -0000 1.29
+++ modules/gnu.c 12 Aug 2003 15:32:26 -0000
@@ -90,7 +90,7 @@ int errno;
/* Generate prototypes for each builtin handler function. */
-#define BUILTIN(handler, macros, blind, min, max) M4BUILTIN(handler)
+#define BUILTIN(handler, macros, blind, min, max) M4BUILTIN(handler)
builtin_functions
#undef BUILTIN
@@ -452,29 +452,30 @@ M4BUILTIN_HANDLER (epatsubst)
/* Implementation of "symbols". It builds up a table of pointers to
symbols, sorts it and ships out the symbol names. */
-/* TODO: Import this through the m4_export list of m4 module. */
-extern void m4_dump_symbols (m4 *context, m4_dump_symbol_data *data, int argc,
- m4_symbol_value **argv, boolean complain);
-
/**
* symbols([...])
**/
M4BUILTIN_HANDLER (symbols)
{
- m4_dump_symbol_data data;
- m4_obstack data_obs;
-
- obstack_init (&data_obs);
- data.obs = &data_obs;
- m4_dump_symbols (context, &data, argc, argv, FALSE);
+ M4_MODULE_IMPORT (m4, m4_dump_symbols);
- for (; data.size > 0; --data.size, data.base++)
+ if (m4_dump_symbols)
{
- m4_shipout_string (context, obs, data.base[0], 0, TRUE);
- if (data.size > 1)
- obstack_1grow (obs, ',');
+ m4_dump_symbol_data data;
+ m4_obstack data_obs;
+
+ obstack_init (&data_obs);
+ data.obs = &data_obs;
+ m4_dump_symbols (context, &data, argc, argv, FALSE);
+
+ for (; data.size > 0; --data.size, data.base++)
+ {
+ m4_shipout_string (context, obs, data.base[0], 0, TRUE);
+ if (data.size > 1)
+ obstack_1grow (obs, ',');
+ }
+ obstack_free (&data_obs, NULL);
}
- obstack_free (&data_obs, NULL);
}
@@ -506,28 +507,30 @@ M4BUILTIN_HANDLER (syncoutput)
* esyscmd(SHELL-COMMAND)
**/
-/* TODO: Import these through the m4_export list of m4 module. */
-extern int m4_sysval;
-extern void m4_sysval_flush (m4 *);
-
M4BUILTIN_HANDLER (esyscmd)
{
- FILE *pin;
- int ch;
+ M4_MODULE_IMPORT (m4, m4_set_sysval);
+ M4_MODULE_IMPORT (m4, m4_sysval_flush);
- m4_sysval_flush (context);
- pin = popen (M4ARG (1), "r");
- if (pin == NULL)
- {
- M4ERROR ((m4_get_warning_status_opt (context), errno,
- _("Cannot open pipe to command `%s'"), M4ARG (1)));
- m4_sysval = 0xff << 8;
- }
- else
+ if (m4_set_sysval && m4_sysval_flush)
{
- while ((ch = getc (pin)) != EOF)
- obstack_1grow (obs, (char) ch);
- m4_sysval = pclose (pin);
+ FILE *pin;
+ int ch;
+
+ m4_sysval_flush (context);
+ pin = popen (M4ARG (1), "r");
+ if (pin == NULL)
+ {
+ M4ERROR ((m4_get_warning_status_opt (context), errno,
+ _("Cannot open pipe to command `%s'"), M4ARG (1)));
+ m4_set_sysval (0xff << 8);
+ }
+ else
+ {
+ while ((ch = getc (pin)) != EOF)
+ obstack_1grow (obs, (char) ch);
+ m4_set_sysval (pclose (pin));
+ }
}
}
Index: modules/import.c
===================================================================
RCS file: modules/import.c
diff -N modules/import.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ modules/import.c 12 Aug 2003 15:32:26 -0000
@@ -0,0 +1,102 @@
+/* GNU m4 -- A simple macro processor
+ Copyright 2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA
+*/
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <m4module.h>
+
+#include <assert.h>
+
+#define m4_builtin_table import_LTX_m4_builtin_table
+
+/* function macros blind minargs maxargs */
+#define builtin_functions \
+ BUILTIN (import, FALSE, FALSE, 1, 2) \
+ BUILTIN (symbol_fail, FALSE, FALSE, 1, 2) \
+ BUILTIN (module_fail, FALSE, FALSE, 1, 2)
+
+#define BUILTIN(handler, macros, blind, min, max) M4BUILTIN(handler)
+ builtin_functions
+#undef BUILTIN
+
+m4_builtin m4_builtin_table[] =
+{
+#define BUILTIN(handler, macros, blind, min, max) \
+ { STR(handler), CONC(builtin_, handler), macros, blind, min, max },
+
+ builtin_functions
+#undef BUILTIN
+
+ { 0, 0, FALSE, FALSE, 0, 0 },
+};
+
+
+
+typedef boolean export_test_func (const char *);
+typedef boolean no_such_func (const char *);
+
+/**
+ * import()
+ **/
+M4BUILTIN_HANDLER (import)
+{
+ M4_MODULE_IMPORT (modtest, export_test);
+
+ const char *s = "`import'::`import' called.";
+
+ assert (obs != 0);
+ obstack_grow (obs, s, strlen(s));
+
+ if (export_test && export_test (M4ARG (1)))
+ fprintf (stderr, "TRUE\n");
+}
+
+/**
+ * symbol_fail()
+ **/
+M4BUILTIN_HANDLER (symbol_fail)
+{
+ M4_MODULE_IMPORT (modtest, no_such);
+
+ const char *s = "`import'::`symbol_fail' called.";
+
+ assert (obs != 0);
+ obstack_grow (obs, s, strlen(s));
+
+ if (no_such && no_such (M4ARG (1)))
+ fprintf (stderr, "TRUE\n");
+}
+
+/**
+ * module_fail()
+ **/
+M4BUILTIN_HANDLER (module_fail)
+{
+ M4_MODULE_IMPORT (no_such, no_such);
+
+ const char *s = "`import'::`module_fail' called.";
+
+ assert (obs != 0);
+ obstack_grow (obs, s, strlen(s));
+
+ if (no_such && no_such (M4ARG (1)))
+ fprintf (stderr, "TRUE\n");
+}
Index: modules/m4.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/m4.c,v
retrieving revision 1.51
diff -u -p -u -r1.51 m4.c
--- modules/m4.c 24 Jul 2003 14:21:03 -0000 1.51
+++ modules/m4.c 12 Aug 2003 15:32:26 -0000
@@ -1,5 +1,5 @@
/* GNU m4 -- A simple macro processor
- Copyright 2000 Free Software Foundation, Inc.
+ Copyright 2000, 2002, 2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -49,20 +49,9 @@ extern int errno;
#define m4_export_table m4_LTX_m4_export_table
#define m4_builtin_table m4_LTX_m4_builtin_table
-/* Exit code from last "syscmd" command. */
-int m4_sysval = 0;
-
-void m4_sysval_flush (m4 *context);
-void m4_dump_symbols (m4 *context, m4_dump_symbol_data *data, int argc,
- m4_symbol_value **argv, boolean complain);
-
-m4_export m4_export_table[] = {
- { "m4_sysval", &m4_sysval },
- { "m4_sysval_flush", &m4_sysval_flush },
- { "m4_dump_symbols", &m4_dump_symbols },
-
- { NULL, NULL }
-};
+#define m4_set_sysval m4_LTX_m4_set_sysval
+#define m4_sysval_flush m4_LTX_m4_sysval_flush
+#define m4_dump_symbols m4_LTX_m4_dump_symbols
/* Maintain each of the builtins implemented in this modules along
with their details in a single table for easy maintenance.
@@ -422,6 +411,15 @@ M4BUILTIN_HANDLER (defn)
/* This section contains macros to handle the builtins "syscmd"
and "sysval". */
+
+/* Exit code from last "syscmd" command. */
+int m4_sysval = 0;
+
+void
+m4_set_sysval (int value)
+{
+ m4_sysval = value;
+}
void
m4_sysval_flush (m4 *context)
Index: modules/m4.h
===================================================================
RCS file: /cvsroot/m4/m4/modules/m4.h,v
retrieving revision 1.1
diff -u -p -u -r1.1 m4.h
--- modules/m4.h 24 Jul 2003 14:21:03 -0000 1.1
+++ modules/m4.h 12 Aug 2003 15:32:26 -0000
@@ -33,6 +33,14 @@ typedef struct
int size; /* size of table */
} m4_dump_symbol_data;
+
+/* Types used to cast imported symbols to, so we get type checking
+ across the interface boundary. */
+typedef void m4_sysval_flush_func (m4 *context);
+typedef void m4_set_sysval_func (int value);
+typedef void m4_dump_symbols_func (m4 *context, m4_dump_symbol_data *data,
+ int argc, m4_symbol_value **argv, boolean complain);
+
END_C_DECLS
#endif /* !MODULES_M4_H */
Index: modules/modtest.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/modtest.c,v
retrieving revision 1.7
diff -u -p -u -r1.7 modtest.c
--- modules/modtest.c 12 Oct 2001 19:57:29 -0000 1.7
+++ modules/modtest.c 12 Aug 2003 15:32:26 -0000
@@ -1,5 +1,5 @@
/* GNU m4 -- A simple macro processor
- Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,6 +28,9 @@
#define m4_builtin_table modtest_LTX_m4_builtin_table
#define m4_macro_table modtest_LTX_m4_macro_table
+#define export_test modtest_LTX_export_test
+
+
/* function macros blind minargs maxargs */
#define builtin_functions \
BUILTIN (test, FALSE, FALSE, 1, 1)
@@ -91,4 +94,16 @@ M4BUILTIN_HANDLER (test)
assert (obs != 0);
obstack_grow (obs, s, strlen(s));
+}
+
+
+/**
+ * export_test()
+ **/
+boolean
+export_test (const char *foo)
+{
+ if (foo)
+ fprintf (stderr, "%s\n", foo);
+ return (boolean) (foo != 0);
}
Index: src/freeze.c
===================================================================
RCS file: /cvsroot/m4/m4/src/freeze.c,v
retrieving revision 1.33
diff -u -p -u -r1.33 freeze.c
--- src/freeze.c 17 Jul 2003 19:57:06 -0000 1.33
+++ src/freeze.c 12 Aug 2003 15:32:26 -0000
@@ -162,9 +162,8 @@ dump_symbol_CB (m4_symbol_table *symtab,
}
else if (m4_is_symbol_func (symbol))
{
- const m4_builtin *bp = m4_builtin_find_by_func
- (m4_get_module_builtin_table (SYMBOL_HANDLE (symbol)),
- m4_get_symbol_func (symbol));
+ const m4_builtin *bp = m4_builtin_find_by_func (SYMBOL_HANDLE (symbol),
+ m4_get_symbol_func (symbol));
if (bp == NULL)
return "INTERNAL ERROR: Builtin not found in builtin table!";
@@ -456,23 +455,13 @@ reload_frozen_state (m4 *context, const
/* Enter a macro having a builtin function as a definition. */
{
- lt_dlhandle handle = 0;
- m4_builtin *bt = NULL;
+ lt_dlhandle handle = 0;
if (number[2] > 0)
- {
- while ((handle = lt_dlhandle_next (handle)))
- if (strcmp (m4_get_module_name (handle), string[2]) == 0)
- break;
-
- if (handle)
- {
- bt = m4_get_module_builtin_table (handle);
- }
- }
+ handle = lt_dlhandle_find (string[2]);
- if (bt)
- bp = m4_builtin_find_by_name (bt, string[1]);
+ if (handle)
+ bp = m4_builtin_find_by_name (handle, string[1]);
if (bp)
{
@@ -666,9 +655,7 @@ reload_frozen_state (m4 *context, const
lt_dlhandle handle = 0;
if (number[2] > 0)
- while ((handle = lt_dlhandle_next (handle)))
- if (strcmp (m4_get_module_name (handle), string[2]) == 0)
- break;
+ handle = lt_dlhandle_find (string[2]);
m4_set_symbol_value_text (token, xstrdup (string[1]));
VALUE_HANDLE (token) = handle;
Index: tests/modules.at
===================================================================
RCS file: /cvsroot/m4/m4/tests/modules.at,v
retrieving revision 1.6
diff -u -p -u -r1.6 modules.at
--- tests/modules.at 11 Oct 2001 21:09:16 -0000 1.6
+++ tests/modules.at 12 Aug 2003 15:32:26 -0000
@@ -333,6 +333,52 @@ AT_CHECK_M4([-m load input.m4], 0, expou
AT_CLEANUP
+
+## ----------------------- ##
+## module symbol importing ##
+## ----------------------- ##
+
+# Importing a symbol from a not yet loaded module
+
+AT_SETUP([modules: importing])
+
+AT_DATA([[input.m4]],
+[[import
+load(`import')
+import
+unload(`modtest')
+import
+symbol_fail
+module_fail
+]])
+
+AT_DATA([[expout]],
+[[import
+
+import::import called.
+
+import::import called.
+import::symbol_fail called.
+]])
+
+AT_DATA([[experr]],
+[[Test module loaded.
+
+TRUE
+Test module unloaded.
+Test module loaded.
+
+TRUE
+m4: input.m4: 6: Warning: cannot load symbol `no_such' from module `modtest'
+m4: input.m4: 7: cannot open module `no_such': no_such.so: cannot open shared
object file: No such file or directory
+]])
+
+AT_CHECK_M4([-m load input.m4], 1, expout, experr)
+
+AT_CLEANUP
+
+
+
## -------------------- ##
## trace module symbols ##
## -------------------- ##
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- FYI: 38-gary-inter-module-symbol-importing.patch,
Gary V. Vaughan <=