m4-discuss
[Top][All Lists]
Advanced

[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;
              }








reply via email to

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