m4-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RFC: enhancement to builtin


From: Eric Blake
Subject: RFC: enhancement to builtin
Date: Sun, 15 Oct 2006 19:44:14 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Thunderbird/1.5.0.7 Mnenhy/0.7.4.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

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?

2006-10-15  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.

- --
Life is short - so eat dessert first!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.1 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFFMuPu84KuGfSFAYARAhILAJ9V1C4teufjmFJ7+HFRyBtMnaTa2gCff5yi
uAxsbkrL0l17SEtQC6KiPMc=
=S84Z
-----END PGP SIGNATURE-----
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.27
diff -u -p -r1.27 NEWS
--- NEWS        12 Oct 2006 02:44:26 -0000      1.27
+++ NEWS        16 Oct 2006 01:41:02 -0000
@@ -35,6 +35,13 @@ promoted to 2.0.
   - 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.65
diff -u -p -r1.65 m4.texinfo
--- doc/m4.texinfo      14 Oct 2006 14:16:23 -0000      1.65
+++ doc/m4.texinfo      16 Oct 2006 01:41:04 -0000
@@ -2151,10 +2151,17 @@ indir(`divert', defn(`foo'))
 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
 
@@ -2231,6 +2238,65 @@ indir(`index')
 @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 -p -r1.25 builtin.c
--- m4/builtin.c        27 Oct 2005 16:04:03 -0000      1.25
+++ m4/builtin.c        16 Oct 2006 01:41:04 -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 @@ m4_builtin_find_by_name (lt_dlhandle han
   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.54
diff -u -p -r1.54 input.c
--- m4/input.c  14 Oct 2006 15:23:08 -0000      1.54
+++ m4/input.c  16 Oct 2006 01:41:04 -0000
@@ -155,13 +155,12 @@ struct m4_input_block
       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.  */
          unsigned int min_args;  /* argv minima for the builtin. */
          unsigned int max_args;  /* argv maxima for the builtin. */
-         bool traced;            /* true iff builtin is traced. */
          bool read;              /* true iff block has been read. */
        }
       u_b;
@@ -402,12 +401,9 @@ builtin_unget (m4_input_block *me, int c
 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, '>');
@@ -442,9 +438,9 @@ m4_push_builtin (m4_symbol_value *token)
                                        sizeof (m4_input_block));
   i->funcs = &builtin_funcs;
 
-  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);
@@ -692,7 +688,7 @@ init_builtin_token (m4 *context, m4_symb
       abort ();
     }
 
-  m4_set_symbol_value_func (token, isp->u.u_b.func);
+  m4_set_symbol_value_builtin (token, isp->u.u_b.builtin);
   VALUE_HANDLE (token)         = isp->u.u_b.handle;
   VALUE_FLAGS (token)          = isp->u.u_b.flags;
   VALUE_ARG_SIGNATURE (token)  = isp->u.u_b.arg_signature;
Index: m4/m4module.h
===================================================================
RCS file: /sources/m4/m4/m4/m4module.h,v
retrieving revision 1.95
diff -u -p -r1.95 m4module.h
--- m4/m4module.h       13 Oct 2006 16:46:47 -0000      1.95
+++ m4/m4module.h       16 Oct 2006 01:41:04 -0000
@@ -243,6 +243,8 @@ extern bool m4_symbol_value_groks_macro     
        (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)                                  \
@@ -254,22 +256,23 @@ extern void               m4_symbol_value_copy      (m4_
                                                   m4_symbol_value *);
 extern bool            m4_is_symbol_value_text   (m4_symbol_value *);
 extern bool            m4_is_symbol_value_func   (m4_symbol_value *);
-extern bool            m4_is_symbol_value_placeholder  (m4_symbol_value *);
+extern bool            m4_is_symbol_value_placeholder  (m4_symbol_value *);
 extern bool            m4_is_symbol_value_void   (m4_symbol_value *);
 extern char           *m4_get_symbol_value_text  (m4_symbol_value *);
 extern m4_builtin_func *m4_get_symbol_value_func  (m4_symbol_value *);
-extern char           *m4_get_symbol_value_placeholder  (m4_symbol_value *);
+extern const m4_builtin *m4_get_symbol_value_builtin   (m4_symbol_value *);
+extern char           *m4_get_symbol_value_placeholder (m4_symbol_value *);
 extern void            m4_set_symbol_value_text  (m4_symbol_value *, char *);
-extern void            m4_set_symbol_value_func  (m4_symbol_value *,
-                                                  m4_builtin_func *);
-extern void            m4_set_symbol_value_placeholder  (m4_symbol_value *,
-                                                         char *);
+extern void            m4_set_symbol_value_builtin     (m4_symbol_value *,
+                                                        const m4_builtin *);
+extern void            m4_set_symbol_value_placeholder (m4_symbol_value *,
+                                                        char *);
 
 
 
 /* --- BUILTIN MANAGEMENT --- */
 
-extern const m4_builtin *m4_builtin_find_by_name (lt_dlhandle, const char *);
+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.67
diff -u -p -r1.67 m4private.h
--- m4/m4private.h      13 Oct 2006 16:46:47 -0000      1.67
+++ m4/m4private.h      16 Oct 2006 01:41:04 -0000
@@ -181,7 +181,7 @@ struct m4_symbol_value {
   m4__symbol_type      type;
   union {
     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 @@ struct m4_symbol_value {
 #  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.59
diff -u -p -r1.59 macro.c
--- m4/macro.c  12 Oct 2006 21:14:50 -0000      1.59
+++ m4/macro.c  16 Oct 2006 01:41:04 -0000
@@ -167,6 +167,7 @@ expand_argument (m4 *context, m4_obstack
 
              if (argp->type == M4_SYMBOL_VOID)
                {
+                 VALUE_HANDLE (argp) = NULL;
                  m4_set_symbol_value_text (argp, text);
                }
              return type == M4_TOKEN_COMMA;
@@ -328,6 +329,7 @@ collect_arguments (m4 *context, const ch
 
          if (!groks_macro_args && m4_is_symbol_value_func (&token))
            {
+             VALUE_HANDLE (&token) = NULL;
              m4_set_symbol_value_text (&token, "");
            }
          tokenp = (m4_symbol_value *)
Index: m4/module.c
===================================================================
RCS file: /sources/m4/m4/m4/module.c,v
retrieving revision 1.46
diff -u -p -r1.46 module.c
--- m4/module.c 27 Sep 2006 12:24:53 -0000      1.46
+++ m4/module.c 16 Oct 2006 01:41:05 -0000
@@ -138,7 +138,7 @@ install_builtin_table (m4 *context, lt_d
   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 @@ install_builtin_table (m4 *context, lt_d
                                   | 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.64
diff -u -p -r1.64 symtab.c
--- m4/symtab.c 13 Oct 2006 16:46:47 -0000      1.64
+++ m4/symtab.c 16 Oct 2006 01:41:05 -0000
@@ -480,9 +480,7 @@ m4_symbol_value_print (m4_symbol_value *
     }
   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_builtin_func *
 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 @@ m4_get_symbol_value_placeholder (m4_symb
   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, char *text)
@@ -663,15 +677,15 @@ m4_set_symbol_value_text (m4_symbol_valu
   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 @@ m4_set_symbol_value_placeholder (m4_symb
   value->u.text = text;
 }
 
-
 
 #ifdef DEBUG_SYM
 
@@ -712,26 +725,16 @@ dump_symbol_CB (m4_symbol_table *symtab,
 
   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.64
diff -u -p -r1.64 gnu.c
--- modules/gnu.c       13 Oct 2006 16:46:47 -0000      1.64
+++ modules/gnu.c       16 Oct 2006 01:41:05 -0000
@@ -322,32 +322,68 @@ M4BUILTIN_HANDLER (__program__)
 
 /* 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 (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.52
diff -u -p -r1.52 freeze.c
--- src/freeze.c        4 Oct 2006 03:57:01 -0000       1.52
+++ src/freeze.c        16 Oct 2006 01:41:05 -0000
@@ -533,26 +533,18 @@ ill-formed frozen file, version 2 direct
 
          /* 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;
              }

reply via email to

[Prev in Thread] Current Thread [Next in Thread]