summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary V. Vaughan <gary@gnu.org>2013-09-20 16:01:31 +0700
committerGary V. Vaughan <gary@gnu.org>2013-09-20 21:41:58 +0700
commitb466ccc6137f2255220c87f74baf86a67884a3d8 (patch)
tree208fdb52d5f50d07b06ba612920055519599b44f
parentaeb92bcb25e253b55650961f341640f93ec3b54e (diff)
downloadm4-b466ccc6137f2255220c87f74baf86a67884a3d8.tar.gz
modules: allow only a single function access point.
Exporting non-function symbols barely works on Windows, so change the module loading API to use a single function access point which is then responsible for calling back to install symbols and macros. * m4/m4module.h, m4/m4module.c (m4_install_builtins) (m4_install_macros): New APIs for saving builtins and macros into the module struct. * m4/m4module.c (install_macro_table, install_builtin_table): Adjust accordingly. (m4__module_open): Simplify accordingly. * m4/m4private.h (BUILTIN_SYMBOL, MACRO_SYMBOL): Remove. * modules/gnu.c, modules/import.c, modules/m4.c, modules/modtest.c, modules/mpeval.c, modules/shadow.c, modules/time.c, modules/traditional.c (m4_builtin_table, m4_macro_table): Make static, and remove LTX symbol mangling macros. (M4INIT_HANDLER): Call m4_install_builtins and/or m4_install_macros. * tests/options.at: Now that init_func is always called, adjust expected debug output. Signed-off-by: Gary V. Vaughan <gary@gnu.org>
-rw-r--r--m4/m4module.h3
-rw-r--r--m4/m4private.h3
-rw-r--r--m4/module.c151
-rw-r--r--modules/gnu.c16
-rw-r--r--modules/import.c8
-rw-r--r--modules/m4.c8
-rw-r--r--modules/modtest.c10
-rw-r--r--modules/mpeval.c16
-rw-r--r--modules/shadow.c19
-rw-r--r--modules/stdlib.c14
-rw-r--r--modules/time.c13
-rw-r--r--modules/traditional.c10
-rw-r--r--tests/options.at2
13 files changed, 147 insertions, 126 deletions
diff --git a/m4/m4module.h b/m4/m4module.h
index a6bd5139..92710a7e 100644
--- a/m4/m4module.h
+++ b/m4/m4module.h
@@ -237,6 +237,9 @@ extern m4_module * m4_module_load (m4 *, const char *, m4_obstack *);
extern void * m4_module_import (m4 *, const char *, const char *,
m4_obstack *);
+extern void m4_install_builtins (m4*, m4_module *, const m4_builtin*);
+extern void m4_install_macros (m4*, m4_module *, const m4_macro*);
+
extern const char * m4_get_module_name (const m4_module *);
extern m4_module * m4_module_next (m4_module *);
diff --git a/m4/m4private.h b/m4/m4private.h
index 29f2bfe9..35957223 100644
--- a/m4/m4private.h
+++ b/m4/m4private.h
@@ -173,8 +173,6 @@ extern void m4__builtin_print (m4_obstack *, const m4__builtin *, bool,
/* --- MODULE MANAGEMENT --- */
-#define BUILTIN_SYMBOL "m4_builtin_table"
-#define MACRO_SYMBOL "m4_macro_table"
#define INIT_SYMBOL "m4_init_module"
/* Representation of a loaded m4 module. */
@@ -182,6 +180,7 @@ struct m4_module
{
lt_dlhandle handle; /* All ltdl module information. */
m4__builtin *builtins; /* Sorted array of builtins. */
+ m4_macro *macros; /* Unsorted array of macros. */
size_t builtins_len; /* Number of builtins. */
};
diff --git a/m4/module.c b/m4/module.c
index ebedcffe..a2215f0e 100644
--- a/m4/module.c
+++ b/m4/module.c
@@ -39,10 +39,17 @@
* libdld or lt_dlpreload from libtool if shared libraries are not
* available on the host machine.
*
- * An M4 module will usually define an external symbol called
- * `m4_builtin_table'. This symbol points to a table of `m4_builtin'.
- * The table is saved as libltdl caller data and each definition therein
- * is added to the symbol table.
+ * An M4 module will usually define an external symbol named after the
+ * basename of the loadable module:
+ *
+ * void
+ * mymod_LTX_m4_init_module (m4 *context, m4_module *module,
+ * m4_obstack *obs)
+ *
+ * The function is only called the first time the module is included
+ * and generally uses either `m4_install_builtins' or
+ * `m4_install_macros' (or both!) to register whatever builtins and
+ * macros are provided by the module.
*
* To load a module, call m4_module_load(), which searches for the
* module in directories from M4PATH. The search path is initialized
@@ -50,20 +57,10 @@
* time default where the modules shipped with M4 itself are installed.
* `m4_module_load' returns NULL on failure, or else an opaque module
* handle for the newly mapped vm segment containing the module code.
- * If the module is not already loaded, m4_module_load() retrieves its
- * value for the symbol `m4_builtin_table', which is installed using
- * set_module_builtin_table().
- *
- * In addition to builtin functions, you can also define static macro
- * expansions in the `m4_macro_table' symbol. If you define this symbol
- * in your modules, it should be an array of `m4_macro's, mapping macro
- * names to the expansion text. Any macros defined in `m4_macro_table'
- * are installed into the M4 symbol table with set_module_macro_table().
- *
- * Each time a module is loaded, the module function prototyped as
- * "M4INIT_HANDLER (<module name>)" is called, if defined. Any value
- * stored in OBS by this function becomes the expansion of the macro
- * which called it.
+ * If the module is not already loaded, m4_module_load() the builtins
+ * and macros registered by `mymod_LTX_m4_init_module' are installed
+ * into the symbol table using `install_builtin_table' and `install_
+ * macro_table' respectively.
**/
#define MODULE_SELF_NAME "!myself!"
@@ -73,8 +70,9 @@ static const char* module_dlerror (void);
static void install_builtin_table (m4*, m4_module *);
static void install_macro_table (m4*, m4_module *);
-static int m4__module_interface (lt_dlhandle handle,
- const char *id_string);
+static int compare_builtin_CB (const void *a, const void *b);
+static int m4__module_interface (lt_dlhandle handle,
+ const char *id_string);
static lt_dlinterface_id iface_id = NULL;
@@ -117,6 +115,36 @@ m4_module_import (m4 *context, const char *module_name,
return symbol_address;
}
+void
+m4_install_builtins (m4 *context, m4_module *module, const m4_builtin *bp)
+{
+ assert (context);
+ assert (module);
+ assert (bp);
+
+ const m4_builtin *tmp;
+ m4__builtin *builtin;
+ for (tmp = bp; tmp->name; tmp++)
+ module->builtins_len++;
+ module->builtins = (m4__builtin *) xnmalloc (module->builtins_len,
+ sizeof *module->builtins);
+ for (builtin = module->builtins; bp->name != NULL; bp++, builtin++)
+ {
+ /* Sanity check that builtins meet the required interface. */
+ assert (bp->min_args <= bp->max_args);
+ assert (bp->min_args > 0 ||
+ (bp->flags & (M4_BUILTIN_BLIND|M4_BUILTIN_SIDE_EFFECT)) == 0);
+ assert (bp->max_args ||
+ (bp->flags & M4_BUILTIN_FLATTEN_ARGS) == 0);
+ assert ((bp->flags & ~M4_BUILTIN_FLAGS_MASK) == 0);
+ memcpy (&builtin->builtin, bp, sizeof *bp);
+ builtin->builtin.name = xstrdup (bp->name);
+ builtin->module = module;
+ }
+ qsort (module->builtins, module->builtins_len,
+ sizeof *module->builtins, compare_builtin_CB);
+}
+
static void
install_builtin_table (m4 *context, m4_module *module)
{
@@ -144,6 +172,16 @@ install_builtin_table (m4 *context, m4_module *module)
m4_get_module_name (module));
}
+void
+m4_install_macros (m4 *context, m4_module *module, const m4_macro *mp)
+{
+ assert (context);
+ assert (module);
+ assert (mp);
+
+ module->macros = (m4_macro *) mp;
+}
+
static void
install_macro_table (m4 *context, m4_module *module)
{
@@ -152,7 +190,7 @@ install_macro_table (m4 *context, m4_module *module)
assert (context);
assert (module);
- mp = (const m4_macro *) lt_dlsym (module->handle, MACRO_SYMBOL);
+ mp = module->macros;
if (mp)
{
@@ -174,7 +212,7 @@ install_macro_table (m4 *context, m4_module *module)
m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
_("module %s: macros loaded"),
- m4_get_module_name (module));
+ m4_get_module_name (module));
}
}
@@ -209,9 +247,7 @@ m4__module_interface (lt_dlhandle handle, const char *id_string)
return 0;
/* A valid m4 module must provide at least one of these symbols. */
- return !(lt_dlsym (handle, INIT_SYMBOL)
- || lt_dlsym (handle, BUILTIN_SYMBOL)
- || lt_dlsym (handle, MACRO_SYMBOL));
+ return !(lt_dlsym (handle, INIT_SYMBOL));
}
@@ -379,46 +415,10 @@ m4__module_open (m4 *context, const char *name, m4_obstack *obs)
{
void *old;
const char *err;
- const m4_builtin *bp;
module = (m4_module *) xzalloc (sizeof *module);
module->handle = handle;
- /* TODO - change module interface to return function pointer
- that supplies both table and length of table, rather than
- returning data pointer that must have a sentinel
- entry? */
- bp = (m4_builtin *) lt_dlsym (module->handle, BUILTIN_SYMBOL);
- if (bp)
- {
- const m4_builtin *tmp;
- m4__builtin *builtin;
- for (tmp = bp; tmp->name; tmp++)
- module->builtins_len++;
- module->builtins =
- (m4__builtin *) xnmalloc (module->builtins_len,
- sizeof *module->builtins);
- for (builtin = module->builtins; bp->name != NULL;
- bp++, builtin++)
- {
- /* Sanity check that builtins meet the required
- interface. */
- assert (bp->min_args <= bp->max_args);
- assert (bp->min_args > 0
- || (bp->flags & (M4_BUILTIN_BLIND
- | M4_BUILTIN_SIDE_EFFECT)) == 0);
- assert (bp->max_args
- || (bp->flags & M4_BUILTIN_FLATTEN_ARGS) == 0);
- assert ((bp->flags & ~M4_BUILTIN_FLAGS_MASK) == 0);
-
- memcpy (&builtin->builtin, bp, sizeof *bp);
- builtin->builtin.name = xstrdup (bp->name);
- builtin->module = module;
- }
- }
- qsort (module->builtins, module->builtins_len,
- sizeof *module->builtins, compare_builtin_CB);
-
/* clear out any stale errors, since we have to use
lt_dlerror to distinguish between success and
failure. */
@@ -429,23 +429,22 @@ m4__module_open (m4 *context, const char *name, m4_obstack *obs)
if (err)
m4_error (context, EXIT_FAILURE, 0, NULL,
_("unable to load module `%s': %s"), name, err);
- }
- /* Find and run any initializing function in the opened module,
- each time the module is opened. */
- init_func = (m4_module_init_func *) lt_dlsym (handle, INIT_SYMBOL);
- if (init_func)
- {
- init_func (context, module, obs);
+ /* Find and run any initializing function in the opened module,
+ the first time the module is opened. */
+ init_func = (m4_module_init_func *) lt_dlsym (handle, INIT_SYMBOL);
+ if (init_func)
+ {
+ init_func (context, module, obs);
- m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
- _("module %s: init hook called"), name);
- }
- else if (!lt_dlsym (handle, BUILTIN_SYMBOL)
- && !lt_dlsym (handle, MACRO_SYMBOL))
- {
- m4_error (context, EXIT_FAILURE, 0, NULL,
- _("module `%s' has no entry points"), name);
+ m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
+ _("module %s: init hook called"), name);
+ }
+ else
+ {
+ m4_error (context, EXIT_FAILURE, 0, NULL,
+ _("module `%s' has no entry point"), name);
+ }
}
m4_debug_message (context, M4_DEBUG_TRACE_MODULE,
diff --git a/modules/gnu.c b/modules/gnu.c
index ae3024f7..5c9b0eed 100644
--- a/modules/gnu.c
+++ b/modules/gnu.c
@@ -32,11 +32,6 @@
#include "spawn-pipe.h"
#include "wait-process.h"
-/* Rename exported symbols for dlpreload()ing. */
-#define m4_builtin_table gnu_LTX_m4_builtin_table
-#define m4_macro_table gnu_LTX_m4_macro_table
-
-
/* Maintain each of the builtins implemented in this modules along
with their details in a single table for easy maintenance.
@@ -70,7 +65,7 @@
/* Generate a table for mapping m4 symbol names to handler functions. */
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
{
#define BUILTIN(handler, macros, blind, side, min, max) \
M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -83,7 +78,7 @@ const m4_builtin m4_builtin_table[] =
/* A table for mapping m4 symbol names to simple expansion text. */
-const m4_macro m4_macro_table[] =
+static const m4_macro m4_macro_table[] =
{
/* name text min max */
#if UNIX
@@ -102,6 +97,13 @@ const m4_macro m4_macro_table[] =
};
+M4INIT_HANDLER (gnu)
+{
+ m4_install_builtins (context, module, m4_builtin_table);
+ m4_install_macros (context, module, m4_macro_table);
+}
+
+
/* Regular expressions. Reuse re_registers among multiple
re_pattern_buffer allocations to reduce malloc usage. */
diff --git a/modules/import.c b/modules/import.c
index ebce6e45..679a50d5 100644
--- a/modules/import.c
+++ b/modules/import.c
@@ -41,7 +41,7 @@
builtin_functions
#undef BUILTIN
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
{
#define BUILTIN(handler, macros, blind, side, min, max) \
M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -53,6 +53,12 @@ const m4_builtin m4_builtin_table[] =
};
+M4INIT_HANDLER (import)
+{
+ m4_install_builtins (context, module, m4_builtin_table);
+}
+
+
typedef bool export_test_func (const char *);
typedef bool no_such_func (const char *);
diff --git a/modules/m4.c b/modules/m4.c
index f9449fe0..ecae4c3a 100644
--- a/modules/m4.c
+++ b/modules/m4.c
@@ -39,8 +39,6 @@
#include <modules/m4.h>
/* Rename exported symbols for dlpreload()ing. */
-#define m4_builtin_table m4_LTX_m4_builtin_table
-
#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
@@ -127,6 +125,12 @@ const m4_builtin m4_builtin_table[] =
};
+M4INIT_HANDLER (m4)
+{
+ m4_install_builtins (context, module, m4_builtin_table);
+}
+
+
/* The rest of this file is code for builtins and expansion of user
defined macros. All the functions for builtins have a prototype as:
diff --git a/modules/modtest.c b/modules/modtest.c
index 385049b4..75450f7e 100644
--- a/modules/modtest.c
+++ b/modules/modtest.c
@@ -29,9 +29,6 @@
#endif
/* Rename exported symbols for dlpreload()ing. */
-#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
extern bool export_test (const char *foo);
@@ -44,7 +41,7 @@ extern bool export_test (const char *foo);
builtin_functions
#undef BUILTIN
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
{
#define BUILTIN(handler, macros, blind, side, min, max) \
M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -55,7 +52,7 @@ const m4_builtin m4_builtin_table[] =
{ NULL, NULL, 0, 0, 0 },
};
-const m4_macro m4_macro_table[] =
+static const m4_macro m4_macro_table[] =
{
/* name text min max */
{ "__test__", "`modtest'", 0, 0 },
@@ -73,6 +70,9 @@ M4INIT_HANDLER (modtest)
{
const char *s = "Test module loaded.\n";
+ m4_install_builtins (context, module, m4_builtin_table);
+ m4_install_macros (context, module, m4_macro_table);
+
/* Don't depend on OBS so that the traces are the same when used
directly, or via a frozen file. */
fputs (s, stderr);
diff --git a/modules/mpeval.c b/modules/mpeval.c
index 7928a281..49afd765 100644
--- a/modules/mpeval.c
+++ b/modules/mpeval.c
@@ -32,11 +32,6 @@
# include <gmp.h>
#endif
-/* Rename exported symbols for dlpreload()ing. */
-#define m4_builtin_table mpeval_LTX_m4_builtin_table
-#define m4_macro_table mpeval_LTX_m4_macro_table
-
-
/* Maintain each of the builtins implemented in this modules along
with their details in a single table for easy maintenance.
@@ -106,7 +101,7 @@
/* Generate a table for mapping m4 symbol names to handler functions. */
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
{
#define BUILTIN(handler, macros, blind, side, min, max) \
M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -119,7 +114,7 @@ const m4_builtin m4_builtin_table[] =
/* A table for mapping m4 symbol names to simple expansion text. */
-const m4_macro m4_macro_table[] =
+static const m4_macro m4_macro_table[] =
{
/* name text min max */
{ "__mpeval__", "", 0, 0 },
@@ -127,6 +122,13 @@ const m4_macro m4_macro_table[] =
};
+M4INIT_HANDLER (mpeval)
+{
+ m4_install_builtins (context, module, m4_builtin_table);
+ m4_install_macros (context, module, m4_macro_table);
+}
+
+
/* GMP defines mpq_t as a 1-element array of struct. Therefore, `mpq_t'
is not compatible with `const mpq_t'. */
typedef mpq_t number;
diff --git a/modules/shadow.c b/modules/shadow.c
index 529425c4..53829937 100644
--- a/modules/shadow.c
+++ b/modules/shadow.c
@@ -28,10 +28,6 @@
# include "m4private.h"
#endif
-/* Rename exported symbols for dlpreload()ing. */
-#define m4_builtin_table shadow_LTX_m4_builtin_table
-#define m4_macro_table shadow_LTX_m4_macro_table
-
/* function macros blind side minargs maxargs */
#define builtin_functions \
BUILTIN (shadow, false, false, false, 0, -1 ) \
@@ -42,7 +38,7 @@
builtin_functions
#undef BUILTIN
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
{
#define BUILTIN(handler, macros, blind, side, min, max) \
M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -53,7 +49,7 @@ const m4_builtin m4_builtin_table[] =
{ NULL, NULL, 0, 0, 0 },
};
-const m4_macro m4_macro_table[] =
+static const m4_macro m4_macro_table[] =
{
/* name text min max */
{ "__test__", "`shadow'", 0, 0 },
@@ -64,16 +60,13 @@ const m4_macro m4_macro_table[] =
M4INIT_HANDLER (shadow)
{
- static bool loaded = false;
-
const char *s = "Shadow module loaded.";
- /* Only display the message on first load. */
- if (obs && !loaded)
- {
- loaded = true;
+ if (obs)
obstack_grow (obs, s, strlen (s));
- }
+
+ m4_install_builtins (context, module, m4_builtin_table);
+ m4_install_macros (context, module, m4_macro_table);
}
diff --git a/modules/stdlib.c b/modules/stdlib.c
index d8f839cf..b01326df 100644
--- a/modules/stdlib.c
+++ b/modules/stdlib.c
@@ -36,12 +36,9 @@
# include "m4private.h"
#endif
-/* Rename exported symbols for dlpreload()ing. */
-#define m4_builtin_table stdlib_LTX_m4_builtin_table
-
/* function macros blind side minargs maxargs */
#define builtin_functions \
- BUILTIN (getcwd, false, false, false, 0, 0 ) \
+ BUILTIN (getcwd, false, false, false, 0, 0 ) \
BUILTIN (getenv, false, true, false, 1, 1 ) \
BUILTIN (getlogin, false, false, false, 0, 0 ) \
BUILTIN (getpid, false, false, false, 0, 0 ) \
@@ -61,7 +58,7 @@
builtin_functions
#undef BUILTIN
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
{
#define BUILTIN(handler, macros, blind, side, min, max) \
M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -71,6 +68,13 @@ const m4_builtin m4_builtin_table[] =
{ NULL, NULL, 0, 0, 0 },
};
+
+
+M4INIT_HANDLER (stdlib)
+{
+ m4_install_builtins (context, module, m4_builtin_table);
+}
+
/**
* getcwd()
diff --git a/modules/time.c b/modules/time.c
index 573d14df..39db75fe 100644
--- a/modules/time.c
+++ b/modules/time.c
@@ -34,9 +34,6 @@
# include "m4private.h"
#endif
-/* Rename exported symbols for dlpreload()ing. */
-#define m4_builtin_table time_LTX_m4_builtin_table
-
/* function macros blind side minargs maxargs */
#define builtin_functions \
BUILTIN (currenttime, false, false, false, 0, 0 ) \
@@ -61,7 +58,7 @@
# endif
#undef BUILTIN
-const m4_builtin m4_builtin_table[] =
+static const m4_builtin m4_builtin_table[] =
{
#define BUILTIN(handler, macros, blind, side, min, max) \
M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max)
@@ -77,6 +74,14 @@ const m4_builtin m4_builtin_table[] =
{ NULL, NULL, 0, 0, 0 },
};
+
+
+M4INIT_HANDLER (time)
+{
+ m4_install_builtins (context, module, m4_builtin_table);
+}
+
+
/**
* currenttime()
diff --git a/modules/traditional.c b/modules/traditional.c
index cb9a32bd..88a4966b 100644
--- a/modules/traditional.c
+++ b/modules/traditional.c
@@ -28,11 +28,8 @@
# include "m4private.h"
#endif
-/* Rename exported symbols for dlpreload()ing. */
-#define m4_macro_table traditional_LTX_m4_macro_table
-
/* A table for mapping m4 symbol names to simple expansion text. */
-const m4_macro m4_macro_table[] =
+static const m4_macro m4_macro_table[] =
{
/* name text min max */
#if UNIX
@@ -47,3 +44,8 @@ const m4_macro m4_macro_table[] =
{ "__traditional__", "", 0, 0 },
{ NULL, NULL, 0, 0 },
};
+
+M4INIT_HANDLER (traditional)
+{
+ m4_install_macros (context, module, m4_macro_table);
+}
diff --git a/tests/options.at b/tests/options.at
index 5848fa80..8503f8fc 100644
--- a/tests/options.at
+++ b/tests/options.at
@@ -423,9 +423,11 @@ dnl Test all flags.
AT_CHECK_M4([-dV in], [0], [[3
0
]], [[m4debug: module m4: opening file
+m4debug: module m4: init hook called
m4debug: module m4: opened
m4debug: module m4: builtins loaded
m4debug: module gnu: opening file
+m4debug: module gnu: init hook called
m4debug: module gnu: opened
m4debug: module gnu: builtins loaded
m4debug: module gnu: macros loaded