[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: RFC: enhancement to builtin
From: |
Eric Blake |
Subject: |
Re: RFC: enhancement to builtin |
Date: |
Fri, 27 Oct 2006 17:02:47 +0000 (UTC) |
User-agent: |
Loom/3.14 (http://gmane.org/) |
Eric Blake <ebb9 <at> byu.net> writes:
>
>
> Here's a proposal for enhancing the 'builtin' macro to make it possible to
> recover a builtin macro, even if all references to it have been undefined.
> Hopefully, the proposed documentation in the patch will give some more
> details on how this could be useful. Any objections to installing this?
I interpreted silence as consent, and installed this:
2006-10-27 Eric Blake <address@hidden>
* m4/macro.c (expand_argument): Fix missing initialization.
* m4/m4private.h (struct m4_symbol_value): Store entire
m4_builtin, not just the func.
(m4_get_symbol_value_func): Update.
(m4_get_symbol_value_builtin, m4_set_symbol_value_builtin): New
fast accessors.
* m4/m4module.h (m4_get_symbol_value_builtin)
(m4_get_symbol_builtin): New prototypes.
(m4_set_symbol_value_func): Delete, replace with...
(m4_set_symbol_value_builtin): New function.
(m4_builtin_find_by_name): Change signature.
* m4/symtab.c (m4_symbol_value_print): Simplify.
(m4_get_symbol_value_func): Update.
(m4_get_symbol_value_builtin): New function.
(m4_set_symbol_value_func): Delete, replace with...
(m4_set_symbol_value_builtin): New function.
(dump_symbol_CB) [DEBUG_SYM]: Simplify.
* m4/builtin.c (m4_builtin_find_by_name): Change signature.
* m4/input.c (struct m4_input_block): Remove unused trace member.
(m4_push_builtin, builtin_print, init_builtin_token): Update
callers.
* m4/module.c (install_builtin_table): Likewise.
* src/freeze.c (reload_frozen_state): Likewise.
* modules/gnu.c (builtin): Make it possible to retrieve a builtin
token, even after the builtin has been undefined.
* doc/m4.texinfo (Builtin): Document new capability.
* NEWS: Likewise.
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.30
diff -u -r1.30 NEWS
--- NEWS 26 Oct 2006 23:19:12 -0000 1.30
+++ NEWS 27 Oct 2006 16:57:18 -0000
@@ -35,6 +35,13 @@
- FIXME: This feature can cause core dumps when renaming multiple
symbols to the same name.
+* The `builtin' macro now has a special form, where if the first argument
+ is exactly the special token representing defn(`builtin'), the expansion
+ is the special token representing the builtin named in the second
+ argument. This allows regenerating a macro with a more efficient
+ mapping directly to a builtin function, rather than through textual
+ indirection through further expansions of `builtin'.
+
* New `-r'/`--regexp-syntax' command-line option changes the default
regular expression syntax used by M4. Without this option, M4 continues
to use EMACS style expressions. A new section in the info docs
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.73
diff -u -r1.73 m4.texinfo
--- doc/m4.texinfo 25 Oct 2006 23:19:19 -0000 1.73
+++ doc/m4.texinfo 27 Oct 2006 16:57:19 -0000
@@ -2231,10 +2231,17 @@
Builtin macros can be called indirectly with @code{builtin}:
@deffn {Builtin (gnu)} builtin (@var{name}, @address@hidden)
address@hidden {Builtin (gnu)} builtin (@code{defn(`builtin')}, @var{name1})
Results in a call to the builtin @var{name}, which is passed the
rest of the arguments @var{args}. If @var{name} does not name a
builtin, a warning message is printed, and the expansion is void.
+As a special case, if @var{name} is exactly the special token
+representing the @code{builtin} macro, as obtained by @code{defn}
+(@pxref{Defn}), then @var{args} must consist of a single @var{name1},
+and the expansion is the special token representing the builtin macro
+named by @var{name1}.
+
The macro @code{builtin} is recognized only with parameters.
@end deffn
@@ -2311,6 +2318,65 @@
@result{}0
@end example
+Normally, once a builtin macro is undefined, the only way to retrieve
+its functionality is by defining a new macro that expands to
address@hidden under the hood. But this extra layer of expansion is
+slightly inefficient, not to mention the fact that it is not robust to
+changes in the current quoting scheme due to @code{changequote}
+(@pxref{Changequote}). On the other hand, defining a macro to the
+special token produced by @code{defn} (@pxref{Defn}) is very efficient,
+and avoids the need for quoting within the macro definition; but
address@hidden only works if the desired macro is already defined by some
+other name. So @code{builtin} provides a special case where it is
+possible to retrieve the same special token representing a builtin as
+what @code{defn} would provide, were the desired macro still defined.
+This feature is activated by passing @code{defn(`builtin')} as the first
+argument to builtin. Normally, passing a special token representing a
+macro as @var{name} results in a warning and an empty expansion, but in
+this case, if the second argument @var{name1} names a valid builtin,
+there is no warning and the expansion is the appropriate special
+token. In fact, with just the @code{builtin} macro accessible, it is
+possible to reconstitute the entire startup state of @code{m4}.
+
+In the example below, compare the number of macro invocations performed
+by @code{defn1} and @code{defn2}, and the differences once quoting is
+changed.
+
address@hidden
+$ @kbd{m4 -d}
+undefine(`defn')
address@hidden
+define(`foo', `bar')
address@hidden
+define(`defn1', `builtin(`defn', $@@)')
address@hidden
+define(`defn2', builtin(builtin(`defn', `builtin'), `defn'))
address@hidden
+dumpdef(`defn1', `defn2')
address@hidden:@tabchar{}`builtin(`defn', $@@)'
address@hidden:@tabchar{}<defn>
address@hidden
+traceon
address@hidden
+defn1(`foo')
address@hidden: -1- defn1(`foo') -> `builtin(`defn', `foo')'
address@hidden: -1- builtin(`defn', `foo') -> ``bar''
address@hidden
+defn2(`foo')
address@hidden: -1- defn2(`foo') -> ``bar''
address@hidden
+traceoff
address@hidden: -1- traceoff -> `'
address@hidden
+changequote(`[', `]')
address@hidden
+defn1([foo])
address@hidden:stdin:11: Warning: builtin: undefined builtin ``defn''
address@hidden
+defn2([foo])
address@hidden
address@hidden example
+
@node M4symbols
@section Getting the defined macro names
Index: m4/builtin.c
===================================================================
RCS file: /sources/m4/m4/m4/builtin.c,v
retrieving revision 1.25
diff -u -r1.25 builtin.c
--- m4/builtin.c 27 Oct 2005 16:04:03 -0000 1.25
+++ m4/builtin.c 27 Oct 2006 16:57:19 -0000
@@ -1,5 +1,6 @@
/* GNU m4 -- A simple macro processor
- Copyright (C) 1989-1994, 1999, 2000, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1999, 2000, 2005,
+ 2006 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
@@ -22,9 +23,11 @@
#include "m4private.h"
-/* Find the builtin which has NAME. If HANDLE argument is supplied
- then search only in HANDLE's builtin table. */
-const m4_builtin *
+/* Find the builtin which has NAME. If HANDLE is not NULL, then
+ search only in HANDLE's builtin table. The result is a malloc'd
+ symbol value, suitable for use in the symbol table or for an
+ argument to m4_push_builtin. */
+m4_symbol_value *
m4_builtin_find_by_name (lt_dlhandle handle, const char *name)
{
lt_dlhandle cur = handle ? handle : m4__module_next (0);
@@ -32,18 +35,27 @@
do
{
const m4_builtin *builtin =
- (const m4_builtin *) lt_dlsym (cur, BUILTIN_SYMBOL);
+ (m4_builtin *) lt_dlsym (cur, BUILTIN_SYMBOL);
if (builtin)
{
for (; builtin->name != NULL; builtin++)
if (!strcmp (builtin->name, name))
- return builtin;
+ {
+ m4_symbol_value *token = xzalloc (sizeof *token);
+
+ m4_set_symbol_value_builtin (token, builtin);
+ VALUE_HANDLE (token) = cur;
+ VALUE_FLAGS (token) = builtin->flags;
+ VALUE_MIN_ARGS (token) = builtin->min_args;
+ VALUE_MAX_ARGS (token) = builtin->max_args;
+ return token;
+ }
}
}
while (!handle && (cur = m4__module_next (cur)));
- return 0;
+ return NULL;
}
/* Find the builtin which has FUNC. If HANDLE argument is supplied
Index: m4/input.c
===================================================================
RCS file: /sources/m4/m4/m4/input.c,v
retrieving revision 1.55
diff -u -r1.55 input.c
--- m4/input.c 25 Oct 2006 23:19:19 -0000 1.55
+++ m4/input.c 27 Oct 2006 16:57:19 -0000
@@ -162,7 +162,7 @@
u_f;
struct
{
- m4_builtin_func *func; /* pointer to builtin's function. */
+ const m4_builtin *builtin; /* pointer to builtin's function. */
lt_dlhandle handle; /* originating module. */
int flags; /* flags associated with the builtin. */
m4_hash *arg_signature; /* argument signature for builtin. */
@@ -389,12 +389,9 @@
static void
builtin_print (m4_input_block *me, m4 *context, m4_obstack *obs)
{
- const m4_builtin *bp;
- const char *text;
+ const m4_builtin *bp = me->u.u_b.builtin;
+ const char *text = bp->name;
- bp = m4_builtin_find_by_func (NULL, me->u.u_b.func);
- assert (bp);
- text = bp->name;
obstack_1grow (obs, '<');
obstack_grow (obs, text, strlen (text));
obstack_1grow (obs, '>');
@@ -431,9 +428,9 @@
i->file = m4_get_current_file (context);
i->line = m4_get_current_line (context);
- i->u.u_b.func = m4_get_symbol_value_func (token);
+ i->u.u_b.builtin = m4_get_symbol_value_builtin (token);
i->u.u_b.handle = VALUE_HANDLE (token);
- i->u.u_b.arg_signature= VALUE_ARG_SIGNATURE (token);
+ i->u.u_b.arg_signature = VALUE_ARG_SIGNATURE (token);
i->u.u_b.min_args = VALUE_MIN_ARGS (token);
i->u.u_b.max_args = VALUE_MAX_ARGS (token);
i->u.u_b.flags = VALUE_FLAGS (token);
@@ -746,7 +743,7 @@
block = block->u.u_c.current;
assert (block->funcs->read_func == builtin_read && ! block->u.u_b.read);
- m4_set_symbol_value_func (token, block->u.u_b.func);
+ m4_set_symbol_value_builtin (token, block->u.u_b.builtin);
VALUE_HANDLE (token) = block->u.u_b.handle;
VALUE_FLAGS (token) = block->u.u_b.flags;
VALUE_ARG_SIGNATURE (token) = block->u.u_b.arg_signature;
Index: m4/m4module.h
===================================================================
RCS file: /sources/m4/m4/m4/m4module.h,v
retrieving revision 1.98
diff -u -r1.98 m4module.h
--- m4/m4module.h 27 Oct 2006 04:03:28 -0000 1.98
+++ m4/m4module.h 27 Oct 2006 16:57:19 -0000
@@ -243,6 +243,8 @@
(m4_get_symbol_value_text (m4_get_symbol_value (symbol)))
#define m4_get_symbol_func(symbol) \
(m4_get_symbol_value_func (m4_get_symbol_value (symbol)))
+#define m4_get_symbol_builtin(symbol) \
+ (m4_get_symbol_value_builtin (m4_get_symbol_value (symbol)))
#define m4_get_symbol_placeholder(symbol) \
(m4_get_symbol_value_placeholder (m4_get_symbol_value (symbol)))
#define m4_symbol_groks_macro(symbol) \
@@ -258,20 +260,21 @@
extern bool m4_is_symbol_value_void (m4_symbol_value *);
extern const char *m4_get_symbol_value_text (m4_symbol_value *);
extern m4_builtin_func *m4_get_symbol_value_func (m4_symbol_value *);
-extern const char *m4_get_symbol_value_placeholder (m4_symbol_value *);
+extern const m4_builtin *m4_get_symbol_value_builtin (m4_symbol_value *);
+extern const char *m4_get_symbol_value_placeholder
(m4_symbol_value *);
extern void m4_set_symbol_value_text (m4_symbol_value *,
- const char *);
-extern void m4_set_symbol_value_func (m4_symbol_value *,
- m4_builtin_func *);
-extern void m4_set_symbol_value_placeholder (m4_symbol_value *,
- const char *);
+ const char *);
+extern void m4_set_symbol_value_builtin (m4_symbol_value *,
+ const m4_builtin *);
+extern void m4_set_symbol_value_placeholder (m4_symbol_value *,
+ const char *);
/* --- BUILTIN MANAGEMENT --- */
-extern const m4_builtin *m4_builtin_find_by_name (lt_dlhandle, const char *);
-extern const m4_builtin *m4_builtin_find_by_func (lt_dlhandle,
+extern m4_symbol_value *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/m4private.h
===================================================================
RCS file: /sources/m4/m4/m4/m4private.h,v
retrieving revision 1.68
diff -u -r1.68 m4private.h
--- m4/m4private.h 27 Oct 2006 04:03:28 -0000 1.68
+++ m4/m4private.h 27 Oct 2006 16:57:19 -0000
@@ -181,7 +181,7 @@
m4__symbol_type type;
union {
const char * text; /* Valid when type is TEXT, PLACEHOLDER. */
- m4_builtin_func * func; /* Valid when type is FUNC. */
+ const m4_builtin * builtin; /* Valid when type is FUNC. */
} u;
};
@@ -217,16 +217,18 @@
# define m4_is_symbol_value_placeholder(V) \
((V)->type == M4_SYMBOL_PLACEHOLDER)
# define m4_get_symbol_value_text(V) ((V)->u.text)
-# define m4_get_symbol_value_func(V) ((V)->u.func)
+# define m4_get_symbol_value_func(V) ((V)->u.builtin->func)
+# define m4_get_symbol_value_builtin(V) ((V)->u.builtin)
# define m4_get_symbol_value_placeholder(V) \
((V)->u.text)
+# define m4_get_symbol_value_module(V) (VALUE_HANDLE (V))
# define m4_symbol_value_groks_macro(V) (BIT_TEST ((V)->flags,
\
VALUE_MACRO_ARGS_BIT))
# define m4_set_symbol_value_text(V, T) \
((V)->type = M4_SYMBOL_TEXT, (V)->u.text = (T))
-# define m4_set_symbol_value_func(V, F) \
- ((V)->type = M4_SYMBOL_FUNC, (V)->u.func = (F))
+# define m4_set_symbol_value_builtin(V, B) \
+ ((V)->type = M4_SYMBOL_FUNC, (V)->u.builtin = (B))
# define m4_set_symbol_value_placeholder(V, T)
\
((V)->type = M4_SYMBOL_PLACEHOLDER, (V)->u.text = (T))
#endif
Index: m4/macro.c
===================================================================
RCS file: /sources/m4/m4/m4/macro.c,v
retrieving revision 1.61
diff -u -r1.61 macro.c
--- m4/macro.c 27 Oct 2006 04:03:28 -0000 1.61
+++ m4/macro.c 27 Oct 2006 16:57:19 -0000
@@ -182,6 +182,7 @@
if (argp->type == M4_SYMBOL_VOID)
{
+ VALUE_HANDLE (argp) = NULL;
m4_set_symbol_value_text (argp, text);
}
return type == M4_TOKEN_COMMA;
@@ -358,6 +359,7 @@
if (!groks_macro_args && m4_is_symbol_value_func (&token))
{
+ VALUE_HANDLE (&token) = NULL;
m4_set_symbol_value_text (&token, "");
}
tokenp = (m4_symbol_value *) obstack_copy (arguments, &token,
Index: m4/module.c
===================================================================
RCS file: /sources/m4/m4/m4/module.c,v
retrieving revision 1.47
diff -u -r1.47 module.c
--- m4/module.c 16 Oct 2006 22:12:07 -0000 1.47
+++ m4/module.c 27 Oct 2006 16:57:19 -0000
@@ -138,7 +138,7 @@
assert (context);
assert (handle);
- bp = (const m4_builtin *) lt_dlsym (handle, BUILTIN_SYMBOL);
+ bp = (m4_builtin *) lt_dlsym (handle, BUILTIN_SYMBOL);
if (bp)
{
for (; bp->name != NULL; bp++)
@@ -153,7 +153,7 @@
| M4_BUILTIN_SIDE_EFFECT)) == 0);
assert ((bp->flags & ~M4_BUILTIN_FLAGS_MASK) == 0);
- m4_set_symbol_value_func (value, bp->func);
+ m4_set_symbol_value_builtin (value, bp);
VALUE_HANDLE (value) = handle;
VALUE_FLAGS (value) = bp->flags;
VALUE_MIN_ARGS (value) = bp->min_args;
Index: m4/symtab.c
===================================================================
RCS file: /sources/m4/m4/m4/symtab.c,v
retrieving revision 1.66
diff -u -r1.66 symtab.c
--- m4/symtab.c 27 Oct 2006 04:03:28 -0000 1.66
+++ m4/symtab.c 27 Oct 2006 16:57:19 -0000
@@ -480,9 +480,7 @@
}
else if (m4_is_symbol_value_func (value))
{
- const m4_builtin *bp;
- bp = m4_builtin_find_by_func (NULL, m4_get_symbol_value_func (value));
- assert (bp);
+ const m4_builtin *bp = m4_get_symbol_value_builtin (value);
text = bp->name;
lquote = "<";
rquote = ">";
@@ -641,7 +639,15 @@
m4_get_symbol_value_func (m4_symbol_value *value)
{
assert (value && value->type == M4_SYMBOL_FUNC);
- return value->u.func;
+ return value->u.builtin->func;
+}
+
+#undef m4_get_symbol_value_builtin
+const m4_builtin *
+m4_get_symbol_value_builtin (m4_symbol_value *value)
+{
+ assert (value && value->type == M4_SYMBOL_FUNC);
+ return value->u.builtin;
}
#undef m4_get_symbol_value_placeholder
@@ -652,6 +658,14 @@
return value->u.text;
}
+#undef m4_get_symbol_value_module
+lt_dlhandle
+m4_get_symbol_value_module (m4_symbol_value *value)
+{
+ assert (value);
+ return VALUE_HANDLE (value);
+}
+
#undef m4_set_symbol_value_text
void
m4_set_symbol_value_text (m4_symbol_value *value, const char *text)
@@ -663,15 +677,15 @@
value->u.text = text;
}
-#undef m4_set_symbol_value_func
+#undef m4_set_symbol_value_builtin
void
-m4_set_symbol_value_func (m4_symbol_value *value, m4_builtin_func *func)
+m4_set_symbol_value_builtin (m4_symbol_value *value, const m4_builtin *builtin)
{
assert (value);
- assert (func);
+ assert (builtin);
value->type = M4_SYMBOL_FUNC;
- value->u.func = func;
+ value->u.builtin = builtin;
}
#undef m4_set_symbol_value_placeholder
@@ -685,7 +699,6 @@
value->u.text = text;
}
-
#ifdef DEBUG_SYM
@@ -712,26 +725,16 @@
if (!value)
fputs ("<!UNDEFINED!>", stderr);
+ else if (m4_is_symbol_value_void (value))
+ fputs ("<!VOID!>", stderr);
else
- switch (value->type)
- {
- case M4_SYMBOL_TEXT:
- fputs (m4_get_symbol_text (symbol), stderr);
- break;
-
- case M4_SYMBOL_FUNC:
- bp = m4_builtin_find_by_func (handle, m4_get_symbol_func (symbol));
- fprintf (stderr, "<%s>",
- bp ? bp->name : "!ERROR!");
- break;
- case M4_SYMBOL_PLACEHOLDER:
- fprintf (stderr, "<placeholder for %s>",
- m4_get_symbol_placeholder (symbol));
- break;
- case M4_SYMBOL_VOID:
- fputs ("<!VOID!>", stderr);
- break;
- }
+ {
+ m4_obstack obs;
+ obstack_init (&obs);
+ m4_symbol_value_print (value, &obs, false, NULL, NULL, 0, true);
+ fprintf (stderr, "%s", obstack_finish (&obs));
+ obstack_free (&obs, NULL);
+ }
fputc ('\n', stderr);
return NULL;
}
Index: modules/gnu.c
===================================================================
RCS file: /sources/m4/m4/modules/gnu.c,v
retrieving revision 1.65
diff -u -r1.65 gnu.c
--- modules/gnu.c 21 Oct 2006 22:15:52 -0000 1.65
+++ modules/gnu.c 27 Oct 2006 16:57:19 -0000
@@ -323,32 +323,68 @@
/* The builtin "builtin" allows calls to builtin macros, even if their
definition has been overridden or shadowed. It is thus possible to
- redefine builtins, and still access their original definition. */
+ redefine builtins, and still access their original definition. A
+ special form allows one to retrieve the special token that defn
+ would normally return, even if that builtin is not currently
+ defined and hence can't be passed to defn. */
/**
* builtin(MACRO, [...])
+ * builtin(defn(`builtin'), MACRO)
**/
M4BUILTIN_HANDLER (builtin)
{
+ const char *name;
+ m4_symbol_value *value;
+
if (! m4_is_symbol_value_text (argv[1]))
- m4_warn (context, 0, _("%s: invalid macro name ignored"), M4ARG (0));
+ {
+ if (m4_is_symbol_value_func (argv[1])
+ && m4_get_symbol_value_func (argv[1]) == builtin_builtin)
+ {
+ if (m4_bad_argc (context, argc, argv, 2, 2, false))
+ return;
+ if (! m4_is_symbol_value_text (argv[2]))
+ {
+ m4_warn (context, 0, _("%s: invalid macro name ignored"),
+ M4ARG (0));
+ return;
+ }
+ name = M4ARG (2);
+ value = m4_builtin_find_by_name (NULL, name);
+ if (value == NULL)
+ m4_warn (context, 0, _("%s: undefined builtin `%s'"), M4ARG (0),
+ name);
+ else
+ {
+ m4_push_builtin (context, value);
+ free (value);
+ }
+ }
+ else
+ m4_warn (context, 0, _("%s: invalid macro name ignored"), M4ARG (0));
+ }
else
{
- const char *name = M4ARG (1);
- const m4_builtin *bp = m4_builtin_find_by_name (NULL, name);
-
- if (bp == NULL)
+ name = M4ARG (1);
+ value = m4_builtin_find_by_name (NULL, name);
+ if (value == NULL)
m4_warn (context, 0, _("%s: undefined builtin `%s'"), M4ARG (0), name);
- else if (!m4_bad_argc (context, argc - 1, argv + 1,
- bp->min_args, bp->max_args,
- (bp->flags & M4_BUILTIN_SIDE_EFFECT) != 0))
+ else
{
- int i;
- if ((bp->flags & M4_BUILTIN_GROKS_MACRO) == 0)
- for (i = 2; i < argc; i++)
- if (! m4_is_symbol_value_text (argv[i]))
- m4_set_symbol_value_text (argv[i], "");
- bp->func (context, obs, argc - 1, argv + 1);
+ const m4_builtin *bp = m4_get_symbol_value_builtin (value);
+ if (!m4_bad_argc (context, argc - 1, argv + 1,
+ bp->min_args, bp->max_args,
+ (bp->flags & M4_BUILTIN_SIDE_EFFECT) != 0))
+ {
+ int i;
+ if ((bp->flags & M4_BUILTIN_GROKS_MACRO) == 0)
+ for (i = 2; i < argc; i++)
+ if (! m4_is_symbol_value_text (argv[i]))
+ m4_set_symbol_value_text (argv[i], "");
+ bp->func (context, obs, argc - 1, argv + 1);
+ }
+ free (value);
}
}
}
Index: src/freeze.c
===================================================================
RCS file: /sources/m4/m4/src/freeze.c,v
retrieving revision 1.53
diff -u -r1.53 freeze.c
--- src/freeze.c 27 Oct 2006 04:03:28 -0000 1.53
+++ src/freeze.c 27 Oct 2006 16:57:19 -0000
@@ -531,26 +531,18 @@
/* Enter a macro having a builtin function as a definition. */
{
- const m4_builtin *bp;
lt_dlhandle handle = 0;
- m4_symbol_value *token = xzalloc (sizeof *token);
+ m4_symbol_value *token;
if (number[2] > 0)
handle = m4__module_find (string[2]);
+ token = m4_builtin_find_by_name (handle, string[1]);
- bp = m4_builtin_find_by_name (handle, string[1]);
- VALUE_HANDLE (token) = handle;
-
- if (bp)
- {
- m4_set_symbol_value_func (token, bp->func);
- VALUE_FLAGS (token) = bp->flags;
- VALUE_MIN_ARGS (token) = bp->min_args;
- VALUE_MAX_ARGS (token) = bp->max_args;
- }
- else
+ if (token == NULL)
{
+ token = xzalloc (sizeof *token);
m4_set_symbol_value_placeholder (token, xstrdup (string[1]));
+ VALUE_HANDLE (token) = handle;
VALUE_MIN_ARGS (token) = 0;
VALUE_MAX_ARGS (token) = -1;
}