m4-patches
[Top][All Lists]
Advanced

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

FYI: 5-gary-macro-formal-parameter-first-cut.patch


From: Gary V. Vaughan
Subject: FYI: 5-gary-macro-formal-parameter-first-cut.patch
Date: Fri, 06 Jun 2003 17:29:17 +0100
User-agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.3) Gecko/20030312

Just applied to HEAD.

Most of this is okay, and it certainly works. But it strikes me that it would be much more elegant to pushdef the values named by the formal parameter list for the duration of the expansion of a macro. In the body of a macro the parameters would be referenced by name (without a leading $) and there would be dynamic scoping since nested macros could reference parameters from their parents.

    define(`foo(bar)', `blah: bar')
    foo(`baz')
    =>blah: baz
    define(`quux(blah)', `quux: blah; foo(`argh')')
    quux(`baz')
    =>quux: baz; baz: argh

Comments?
--
  ())_. Gary V. Vaughan     gary@(oranda.demon.co.uk|gnu.org)
  ( '/  Research Scientist  http://www.oranda.demon.co.uk       ,_())____
  / )=  GNU Hacker          http://www.gnu.org/software/libtool  \'      `&
`(_~)_  Tech' Author        http://sources.redhat.com/autobook   =`---d__/
Index: ChangeLog
from  Gary V. Vaughan  <address@hidden>

        First cut at formal parameters in macros.

        * configure.ac (AC_REPLACE_FUNCS): Add xstrzdup.
        * m4/xstrzdup.c: New file.
        * m4/builtin.c (M4_ARG_SIGNATURE_DEFAULT_SIZE): Start size for
        associative array of parameter names to details.
        (m4_symbol_token): Capture macro names with parameter lists.
        (m4_arg_signature_parse): And build an associative array to hang
        from the symbol structure to map names to details.
        * m4/hash.c (m4_hash_new): Break the m4_hash_new followed by
        m4_hash_resize idiom.  Now that we potentially add a little hash
        table to many of the entries in the symbol table, added an extra
        arg to set the initial size.  Changed all callers.
        (m4_hash_apply): New function that is basically a generalised
        version of...
        * m4/symtab.c (m4_symbol_apply): ...this.  Now deleted.  Adjusted
        all callers to call m4_hash_apply instead.
        (m4_arg_destroy): Recycle memory used by an m4_token_arg.
        (m4_symbol_popdef): Use m4_arg_destroy to help recycle the
        m4_arg_signature association that might be attached to the symbol,
        * m4/hash.h (m4_hash_apply_func): Replacement type for...
        * m4/m4module.h (m4_symtab_apply_func): ...this.  Now deleted.
        (M4_SYNTAX_ASSIGN): Placeholder for assigning default values in
        parameter lists.
        (M4_IS_ASSIGN): Detect characters with M4_SYNTAX_ASSIGN syntax.
        (M4_IS_IDENT): Detect characters that can be safely used in
        parameter names.
        * m4/syntax.c (m4_syntax_init): Add an M4_SYNTAX_ASSIGN character.
        * m4/macro.c: Corrected grammar in some comments.  Use `token'
        rather than `td' for m4_token variables.
        (m4_process_macro): If we find a dollar followed by some
        M4_IS_IDENT characters, replace that with the contents of the argv
        entry with offset stored in the m4_token_arg associated with the
        collected identifier.

Index: configure.ac
===================================================================
RCS file: /cvsroot/m4/m4/configure.ac,v
retrieving revision 1.7
diff -u -p -u -r1.7 configure.ac
--- configure.ac 4 Nov 2002 16:31:04 -0000 1.7
+++ configure.ac 6 Jun 2003 16:06:34 -0000
@@ -176,7 +176,7 @@ AC_CHECK_SIZEOF([long long int])
 ## Library functions required by M4. ##
 ## --------------------------------- ##
 AC_CHECK_FUNCS(bzero calloc mkstemp mktemp strerror tmpfile)
-AC_REPLACE_FUNCS(strtol xmalloc xstrdup)
+AC_REPLACE_FUNCS(strtol xmalloc xstrdup xstrzdup)
 AC_FUNC_ALLOCA
 AC_FUNC_VPRINTF
 
Index: m4/builtin.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/builtin.c,v
retrieving revision 1.15
diff -u -p -u -r1.15 builtin.c
--- m4/builtin.c 5 Jun 2003 16:12:16 -0000 1.15
+++ m4/builtin.c 6 Jun 2003 16:06:34 -0000
@@ -23,11 +23,12 @@
 #include "m4.h"
 #include "m4private.h"
 
-extern FILE *popen ();
-extern int pclose ();
+#define M4_ARG_SIGNATURE_DEFAULT_SIZE 7
+
+static m4_hash *m4_arg_signature_parse (const char *name, const char *param);
 
-
 
+
 /* Find the builtin, which has NAME.  If BP argument is supplied
    then search only in table BP.  */
 const m4_builtin *
@@ -75,13 +76,32 @@ m4_symbol_token (const char *name, m4_da
                 m4_symbol *(*getter) (const char *name),
                 m4_symbol *(*setter) (m4_symbol *, m4_token *))
 {
+  const char *openp  = NULL;
+  const char *params = NULL;
   m4_symbol *symbol;
+  size_t len;
 
   assert (name);
   assert (!token || (TOKEN_TYPE (token) == type));
   assert (getter);
   assert (setter);
 
+  if (!no_gnu_extensions)
+    {
+      /* If name contains an open paren, then parse before that paren
+        as the actual name, and the rest as a formal parameter list.  */
+      len = 0;
+      for (openp = name; *openp && !M4_IS_OPEN (*openp); ++openp)
+       ++len;
+
+      if (*openp)
+       {
+         name   = xstrzdup (name, len);
+         params = 1+ openp;
+       }
+    }
+
+  /* Get a symbol table entry for the name.  */
   symbol = (*getter) (name);
 
   if (symbol)
@@ -106,10 +126,76 @@ m4_symbol_token (const char *name, m4_da
          token = &empty;
        }
 
+      if (params)
+       {
+         /* Make a hash table to map formal parameter names to
+            argv offsets, and store that in the symbol's token.  */
+         TOKEN_ARG_SIGNATURE (token) = m4_arg_signature_parse (name, params);
+       }
+
       (*setter) (symbol, token);
     }
 
+  /* If we split name on open paren, free the copied substring.  */
+  if (params)
+    xfree ((char *) name);
+
   return symbol;
+}
+
+static m4_hash *
+m4_arg_signature_parse (const char *name, const char *params)
+{
+  m4_hash *arg_signature;
+  const char *commap;
+  int index;
+
+  assert (params);
+
+  arg_signature = m4_hash_new (M4_ARG_SIGNATURE_DEFAULT_SIZE,
+                       m4_hash_string_hash, m4_hash_string_cmp);
+
+  for (index = 1; *params && !M4_IS_CLOSE (*params); ++index)
+    {
+      size_t len = 0;
+
+      /* Skip leading whitespace.  */
+      while (M4_IS_SPACE (*params))
+       ++params;
+
+      for (commap = params; *commap && M4_IS_IDENT (*commap); ++commap)
+       ++len;
+
+      /* Skip trailing whitespace.  */
+      while (M4_IS_SPACE (*commap))
+       ++commap;
+
+      if (!M4_IS_COMMA (*commap) && !M4_IS_CLOSE (*commap))
+       M4ERROR ((EXIT_FAILURE, 0,
+                 _("Error: %s: syntax error in parameter list at char `%c'"),
+                 name, *commap));
+
+      /* Skip parameter delimiter.  */
+      if (M4_IS_COMMA (*commap))
+       ++commap;
+
+      if (len)
+       {
+         struct m4_token_arg *arg = XCALLOC (struct m4_token_arg, 1);
+
+         TOKEN_ARG_INDEX (arg) = index;
+
+         m4_hash_insert (arg_signature, xstrzdup (params, len), arg);
+
+         params = commap;
+       }
+    }
+
+  if (!M4_IS_CLOSE (*commap))
+    M4WARN ((warning_status, 0,
+            _("Warning: %s: unterminated parameter list"), name));
+
+  return arg_signature;
 }
 
 void
Index: m4/hash.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/hash.c,v
retrieving revision 1.7
diff -u -p -u -r1.7 hash.c
--- m4/hash.c 28 May 2002 21:46:37 -0000 1.7
+++ m4/hash.c 6 Jun 2003 16:06:34 -0000
@@ -83,21 +83,24 @@ static m4_hash_node *m4_hash_node_free_l
 
 
 
-/* Allocate and return a new, unpopulated but initialised m4_hash,
-   where HASH_FUNC will be used to generate bucket numbers and
-   CMP_FUNC will be called to compare keys.  */
+/* Allocate and return a new, unpopulated but initialised m4_hash with
+   SIZE buckets, where HASH_FUNC will be used to generate bucket numbers
+   and CMP_FUNC will be called to compare keys.  */
 m4_hash *
-m4_hash_new (m4_hash_hash_func *hash_func, m4_hash_cmp_func *cmp_func)
+m4_hash_new (size_t size, m4_hash_hash_func *hash_func, m4_hash_cmp_func 
*cmp_func)
 {
   m4_hash *hash;
 
   assert (hash_func);
   assert (cmp_func);
 
+  if (size == 0)
+    size = M4_HASH_DEFAULT_SIZE;
+
   hash                     = XMALLOC (m4_hash, 1);
-  M4_HASH_SIZE (hash)      = M4_HASH_DEFAULT_SIZE;
+  M4_HASH_SIZE (hash)      = size;
   M4_HASH_LENGTH (hash)            = 0;
-  M4_HASH_BUCKETS (hash)    = XCALLOC (m4_hash_node *, M4_HASH_DEFAULT_SIZE);
+  M4_HASH_BUCKETS (hash)    = XCALLOC (m4_hash_node *, size);
   M4_HASH_HASH_FUNC (hash)  = hash_func;
   M4_HASH_CMP_FUNC (hash)   = cmp_func;
 
@@ -498,6 +501,31 @@ m4_hash_iterator_value (m4_hash_iterator
   assert (place);
 
   return M4_HASH_NODE_VAL (M4_ITERATOR_PLACE (place));
+}
+
+/* The following function is used for the cases where we want to do
+   something to each and every entry in HASH.  This function
+   traverses the hash table, and calls a specified function FUNC for
+   each entry in the table.  FUNC is called with a pointer to the
+   entry key, value, and the passed DATA argument.  */
+int
+m4_hash_apply (m4_hash *hash, m4_hash_apply_func *func, void *data)
+{
+  int result = 0;
+  m4_hash_iterator *place = NULL;
+
+  assert (func);
+
+  while ((place = m4_hash_iterator_next (hash, place)))
+    {
+      result = (*func) (m4_hash_iterator_key (place),
+                       m4_hash_iterator_value (place), data);
+
+      if (result != 0)
+       break;
+    }
+
+  return result;
 }
 
 
Index: m4/hash.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/hash.h,v
retrieving revision 1.6
diff -u -p -u -r1.6 hash.h
--- m4/hash.h 28 May 2002 21:46:37 -0000 1.6
+++ m4/hash.h 6 Jun 2003 16:06:34 -0000
@@ -37,7 +37,7 @@ typedef struct m4_hash m4_hash;
 typedef size_t m4_hash_hash_func (const void *key);
 typedef int    m4_hash_cmp_func  (const void *key, const void *try);
 
-m4_hash *      m4_hash_new     (m4_hash_hash_func *hash_func,
+m4_hash *      m4_hash_new     (size_t size, m4_hash_hash_func *hash_func,
                                 m4_hash_cmp_func *cmp_func);
 void           m4_hash_delete  (m4_hash *hash);
 void           m4_hash_insert  (m4_hash *hash, const void *key, void *value);
@@ -55,11 +55,16 @@ int         m4_hash_string_cmp  (const void *ke
 
 
 typedef struct m4_hash_iterator m4_hash_iterator;
+typedef int m4_hash_apply_func (const void *key, void *value, void *data);
 
 m4_hash_iterator *     m4_hash_iterator_next   (const m4_hash *hash,
                                                 m4_hash_iterator *place);
 const void *           m4_hash_iterator_key    (m4_hash_iterator *place);
 void *                 m4_hash_iterator_value  (m4_hash_iterator *place);
+
+int                    m4_hash_apply           (m4_hash *hash,
+                                                m4_hash_apply_func *func,
+                                                void *data);
 
 END_C_DECLS
 
Index: m4/m4module.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4module.h,v
retrieving revision 1.41
diff -u -p -u -r1.41 m4module.h
--- m4/m4module.h 5 Jun 2003 16:12:16 -0000 1.41
+++ m4/m4module.h 6 Jun 2003 16:06:34 -0000
@@ -37,7 +37,6 @@ typedef struct m4_token               m4_token;
 
 typedef void m4_builtin_func (struct obstack *, int, struct m4_token **);
 typedef void *m4_module_func (const char *);
-typedef int m4_symtab_apply_func (const char *name, m4_symbol *symbol, void 
*data);
 
 typedef struct {
     unsigned char *string;     /* characters of the string */
@@ -84,7 +83,6 @@ extern lt_dlhandle  m4_module_find_by_bu
 extern m4_hash *m4_symtab;
 
 extern void    m4_symtab_init          (void);
-extern int     m4_symtab_apply         (m4_symtab_apply_func *, void *);
 extern void    m4_symtab_remove_module_references (lt_dlhandle);
 extern void    m4_symtab_exit          (void);
 
@@ -360,6 +358,7 @@ extern      int     m4_syntax_code  (char ch);
 #define M4_SYNTAX_DOLLAR       (0x0006) /* not used yet */
 #define M4_SYNTAX_ACTIVE       (0x0007)
 #define M4_SYNTAX_ESCAPE       (0x0008)
+#define M4_SYNTAX_ASSIGN       (0x0009)
 
 /* These are values to be assigned to syntax table entries, but they are
    used as bit masks with M4_IS_ALNUM.*/
@@ -389,8 +388,9 @@ extern      int     m4_syntax_code  (char ch);
 #define M4_IS_COMMA(ch)  ((m4__syntax(ch)&M4_SYNTAX_VALUE) == M4_SYNTAX_COMMA)
 #define M4_IS_DOLLAR(ch) ((m4__syntax(ch)&M4_SYNTAX_VALUE) == M4_SYNTAX_DOLLAR)
 #define M4_IS_ACTIVE(ch) ((m4__syntax(ch)&M4_SYNTAX_VALUE) == M4_SYNTAX_ACTIVE)
-
 #define M4_IS_ESCAPE(ch) ((m4__syntax(ch)&M4_SYNTAX_VALUE) == M4_SYNTAX_ESCAPE)
+#define M4_IS_ASSIGN(ch) ((m4__syntax(ch)&M4_SYNTAX_VALUE) == M4_SYNTAX_ASSIGN)
+
 #define M4_IS_ALPHA(ch)  ((m4__syntax(ch)&M4_SYNTAX_VALUE) == M4_SYNTAX_ALPHA)
 #define M4_IS_NUM(ch)    ((m4__syntax(ch)&M4_SYNTAX_VALUE) == M4_SYNTAX_NUM)
 #define M4_IS_ALNUM(ch)  (((m4__syntax(ch)) & M4_SYNTAX_ALNUM) != 0)
@@ -400,6 +400,7 @@ extern      int     m4_syntax_code  (char ch);
 #define M4_IS_BCOMM(ch)  (m4__syntax(ch) & M4_SYNTAX_BCOMM)
 #define M4_IS_ECOMM(ch)  (m4__syntax(ch) & M4_SYNTAX_ECOMM)
 
+#define M4_IS_IDENT(ch)         (M4_IS_OTHER(ch) || M4_IS_ALNUM(ch))
 
 
 /* --- TOKENISATION AND INPUT --- */
@@ -479,7 +480,7 @@ struct m4_dump_symbol_data
   int size;                    /* size of table */
 };
 
-extern int m4_dump_symbol (const char *name, m4_symbol *symbol, void *data);
+extern int m4_dump_symbol (const void *name, void *symbol, void *data);
 extern void m4_dump_symbols (struct m4_dump_symbol_data *data, int argc, 
m4_token **argv, boolean complain);
 
 
Index: m4/m4private.h
===================================================================
RCS file: /cvsroot/m4/m4/m4/m4private.h,v
retrieving revision 1.17
diff -u -p -u -r1.17 m4private.h
--- m4/m4private.h 5 Jun 2003 16:12:16 -0000 1.17
+++ m4/m4private.h 6 Jun 2003 16:06:34 -0000
@@ -47,6 +47,10 @@ struct m4_token_arg {
   char *       default_val;
 };
 
+#define TOKEN_ARG_INDEX(A)     ((A)->index)
+#define TOKEN_ARG_FLAGS(A)     ((A)->flags)
+#define TOKEN_ARG_DEFAULT(A)   ((A)->default_val)
+
 /* m4_token_arg.flags bit masks:  */
 
 #define TOKEN_ARG_REST_BIT     (1 << 0)
Index: m4/macro.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/macro.c,v
retrieving revision 1.22
diff -u -p -u -r1.22 macro.c
--- m4/macro.c 5 Jun 2003 16:06:00 -0000 1.22
+++ m4/macro.c 6 Jun 2003 16:06:34 -0000
@@ -18,7 +18,7 @@
    02111-1307  USA
 */
 
-/* This file contains the functions, that performs the basic argument
+/* This file contains the functions that perform the basic argument
    parsing and macro expansion.  */
 
 #include "m4.h"
@@ -33,15 +33,15 @@ int m4_expansion_level = 0;
 /* The number of the current call of expand_macro ().  */
 static int macro_call_id = 0;
 
-/* This function read all input, and expands each token, one at a time.  */
+/* This function reads all input, and expands each token, one at a time.  */
 void
 m4_expand_input (void)
 {
-  m4_token_t t;
-  m4_token td;
+  m4_token_t type;
+  m4_token token;
 
-  while ((t = m4_next_token (&td)) != M4_TOKEN_EOF)
-    expand_token ((struct obstack *) NULL, t, &td);
+  while ((type = m4_next_token (&token)) != M4_TOKEN_EOF)
+    expand_token ((struct obstack *) NULL, type, &token);
 }
 
 
@@ -50,12 +50,12 @@ m4_expand_input (void)
    macro definition.  If they have, they are expanded as macros, otherwise
    the text are just copied to the output.  */
 static void
-expand_token (struct obstack *obs, m4_token_t t, m4_token *td)
+expand_token (struct obstack *obs, m4_token_t type, m4_token *token)
 {
   m4_symbol *symbol;
-  char *text = xstrdup (TOKEN_TEXT (td));
+  char *text = xstrdup (TOKEN_TEXT (token));
 
-  switch (t)
+  switch (type)
     {                          /* TOKSW */
     case M4_TOKEN_EOF:
     case M4_TOKEN_MACDEF:
@@ -69,12 +69,12 @@ expand_token (struct obstack *obs, m4_to
 
     case M4_TOKEN_WORD:
       {
-       char *p = text;
+       char *textp = text;
 
-       if (M4_IS_ESCAPE(*p))
-         ++p;
+       if (M4_IS_ESCAPE(*textp))
+         ++textp;
 
-       symbol = m4_symbol_lookup (p);
+       symbol = m4_symbol_lookup (textp);
        if (symbol == NULL
            || SYMBOL_TYPE (symbol) == M4_TOKEN_VOID
            || (SYMBOL_TYPE (symbol) == M4_TOKEN_FUNC
@@ -84,7 +84,7 @@ expand_token (struct obstack *obs, m4_to
            m4_shipout_text (obs, text, strlen (text));
          }
        else
-         expand_macro (p, symbol);
+         expand_macro (textp, symbol);
       }
       break;
 
@@ -101,15 +101,15 @@ expand_token (struct obstack *obs, m4_to
 /* This function parses one argument to a macro call.  It expects the first
    left parenthesis, or the separating comma to have been read by the
    caller.  It skips leading whitespace, and reads and expands tokens,
-   until it finds a comma or an right parenthesis at the same level of
-   parentheses.  It returns a flag indicating whether the argument read are
-   the last for the active macro call.  The argument are build on the
+   until it finds a comma or a right parenthesis at the same level of
+   parentheses.  It returns a flag indicating whether the argument read is
+   the last for the active macro call.  The arguments are build on the
    obstack OBS, indirectly through expand_token ().     */
 static boolean
 expand_argument (struct obstack *obs, m4_token *argp)
 {
-  m4_token_t t;
-  m4_token td;
+  m4_token_t type;
+  m4_token token;
   char *text;
   int paren_level = 0;
   const char *current_file = m4_current_file;
@@ -120,16 +120,16 @@ expand_argument (struct obstack *obs, m4
   /* Skip leading white space.  */
   do
     {
-      t = m4_next_token (&td);
+      type = m4_next_token (&token);
     }
-  while (t == M4_TOKEN_SPACE);
+  while (type == M4_TOKEN_SPACE);
 
   while (1)
     {
-      switch (t)
+      switch (type)
        {                       /* TOKSW */
        case M4_TOKEN_SIMPLE:
-         text = TOKEN_TEXT (&td);
+         text = TOKEN_TEXT (&token);
          if ((M4_IS_COMMA (*text) || M4_IS_CLOSE (*text)) && paren_level == 0)
            {
 
@@ -142,14 +142,14 @@ expand_argument (struct obstack *obs, m4
                  TOKEN_TYPE (argp) = M4_TOKEN_TEXT;
                  TOKEN_TEXT (argp) = text;
                }
-             return (boolean) (M4_IS_COMMA (*TOKEN_TEXT (&td)));
+             return (boolean) (M4_IS_COMMA (*TOKEN_TEXT (&token)));
            }
 
          if (M4_IS_OPEN (*text))
            paren_level++;
          else if (M4_IS_CLOSE (*text))
            paren_level--;
-         expand_token (obs, t, &td);
+         expand_token (obs, type, &token);
          break;
 
        case M4_TOKEN_EOF:
@@ -160,12 +160,12 @@ expand_argument (struct obstack *obs, m4
        case M4_TOKEN_WORD:
        case M4_TOKEN_SPACE:
        case M4_TOKEN_STRING:
-         expand_token (obs, t, &td);
+         expand_token (obs, type, &token);
          break;
 
        case M4_TOKEN_MACDEF:
          if (obstack_object_size (obs) == 0)
-           m4_token_copy (argp, &td);
+           m4_token_copy (argp, &token);
          break;
 
        default:
@@ -174,46 +174,47 @@ expand_argument (struct obstack *obs, m4
          abort ();
        }
 
-      t = m4_next_token (&td);
+      type = m4_next_token (&token);
     }
 }
 
-/* Collect all the arguments to a call of the macro SYM.  The arguments are
-   stored on the obstack ARGUMENTS and a table of pointers to the arguments
-   on the obstack ARGPTR.  */
+/* Collect all the arguments to a call of the macro SYMBOL (called NAME).
+   The arguments are stored on the obstack ARGUMENTS and a table of pointers
+   to the arguments on the obstack ARGPTR.  */
 static void
 collect_arguments (const char *name, m4_symbol *symbol,
                   struct obstack *argptr, struct obstack *arguments)
 {
   int ch;                      /* lookahead for ( */
-  m4_token td;
-  m4_token *tdp;
+  m4_token token;
+  m4_token *tokenp;
   boolean more_args;
   boolean groks_macro_args;
 
   groks_macro_args = BIT_TEST (SYMBOL_FLAGS (symbol), TOKEN_MACRO_ARGS_BIT);
 
-  TOKEN_TYPE (&td) = M4_TOKEN_TEXT;
-  TOKEN_TEXT (&td) = (char *) name;
-  tdp = (m4_token *) obstack_copy (arguments, (void *) &td, sizeof (td));
-  obstack_grow (argptr, (void *) &tdp, sizeof (tdp));
+  TOKEN_TYPE (&token) = M4_TOKEN_TEXT;
+  TOKEN_TEXT (&token) = (char *) name;
+  tokenp = (m4_token *) obstack_copy (arguments, (void *) &token,
+                                     sizeof (token));
+  obstack_grow (argptr, (void *) &tokenp, sizeof (tokenp));
 
   ch = m4_peek_input ();
   if (M4_IS_OPEN(ch))
     {
-      m4_next_token (&td);             /* gobble parenthesis */
+      m4_next_token (&token);          /* gobble parenthesis */
       do
        {
-         more_args = expand_argument (arguments, &td);
+         more_args = expand_argument (arguments, &token);
 
-         if (!groks_macro_args && TOKEN_TYPE (&td) == M4_TOKEN_FUNC)
+         if (!groks_macro_args && TOKEN_TYPE (&token) == M4_TOKEN_FUNC)
            {
-             TOKEN_TYPE (&td) = M4_TOKEN_TEXT;
-             TOKEN_TEXT (&td) = "";
+             TOKEN_TYPE (&token) = M4_TOKEN_TEXT;
+             TOKEN_TEXT (&token) = "";
            }
-         tdp = (m4_token *)
-           obstack_copy (arguments, (void *) &td, sizeof (td));
-         obstack_grow (argptr, (void *) &tdp, sizeof (tdp));
+         tokenp = (m4_token *)
+           obstack_copy (arguments, (void *) &token, sizeof (token));
+         obstack_grow (argptr, (void *) &tokenp, sizeof (tokenp));
        }
       while (more_args);
     }
@@ -222,11 +223,11 @@ collect_arguments (const char *name, m4_
 
 
 /* The actual call of a macro is handled by m4_call_macro ().
-   m4_call_macro () is passed a symbol SYM, whose type is used to
+   m4_call_macro () is passed a SYMBOL, whose type is used to
    call either a builtin function, or the user macro expansion
-   function expand_predefine () (lives in builtin.c).  There are ARGC
-   arguments to the call, stored in the ARGV table.  The expansion is
-   left on the obstack EXPANSION.  Macro tracing is also handled here.  */
+   function m4_process_macro ().  There are ARGC arguments to
+   the call, stored in the ARGV table.  The expansion is left on
+   the obstack EXPANSION.  Macro tracing is also handled here.  */
 void
 m4_call_macro (m4_symbol *symbol, int argc, m4_token **argv,
               struct obstack *expansion)
@@ -358,7 +359,50 @@ m4_process_macro (struct obstack *obs, m
          break;
 
        default:
-         obstack_1grow (obs, '$');
+         if (no_gnu_extensions || !SYMBOL_ARG_SIGNATURE (symbol))
+           {
+             obstack_1grow (obs, '$');
+           }
+         else
+           {
+             size_t       len  = 0;
+             const char * endp;
+             const char * key;
+
+             for (endp = ++text; *endp && M4_IS_IDENT (*endp); ++endp)
+               ++len;
+             key = xstrzdup (text, len);
+
+             if (*endp)
+               {
+                 struct m4_token_arg **arg
+                   = (struct m4_token_arg **)
+                     m4_hash_lookup (SYMBOL_ARG_SIGNATURE (symbol), key);
+
+                 if (arg)
+                   {
+                     i = TOKEN_ARG_INDEX (*arg);
+
+                     if (i < argc)
+                       m4_shipout_string (obs, M4ARG (i), 0, FALSE);
+                     else
+                       M4ERROR ((EXIT_FAILURE, 0, "\
+INTERNAL ERROR: %s: out of range reference `%d' from argument %s",
+                             M4ARG (0), i, key));
+                   }
+               }
+             else
+               {
+                 M4ERROR ((warning_status, 0,
+                         _("Error: %s: unterminated parameter reference: %s"),
+                           M4ARG (0), key));
+               }
+
+             text = *endp ? 1+ endp : endp;
+
+             xfree ((char *) key);
+             break;
+           }
          break;
        }
     }
Index: m4/symtab.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/symtab.c,v
retrieving revision 1.30
diff -u -p -u -r1.30 symtab.c
--- m4/symtab.c 5 Jun 2003 16:12:16 -0000 1.30
+++ m4/symtab.c 6 Jun 2003 16:06:34 -0000
@@ -28,7 +28,7 @@
    symbol is represented by `struct m4_symbol', which is stored in the hash
    table keyed by the symbol name.  As a special case, to facilitate the
    "pushdef" and "popdef" builtins, the value stored against each key is a
-   stack of `struct m4_symbol'. All the value entries for a symbol name are
+   stack of `struct m4_token'. All the value entries for a symbol name are
    simply ordered on the stack by age.  The most recently pushed definition
    will then always be the first found.
 
@@ -42,8 +42,12 @@
    of fluff in these functions to make sure that such symbols (with empty
    value stacks) are invisible to the users of this module.  */
 
-static int     m4_symbol_destroy       (const char *name, m4_symbol *symbol,
-                                        void *data);
+#define M4_SYMTAB_DEFAULT_SIZE 2047
+
+static int     m4_symbol_destroy       (const void *name, void *symbol,
+                                        void *symtab);
+static int     m4_arg_destroy          (const void *ignored, void *arg,
+                                        void *also_ignored);
 
 /* Pointer to symbol table.  */
 m4_hash *m4_symtab = 0;
@@ -58,35 +62,8 @@ m4_hash *m4_symtab = 0;
 void
 m4_symtab_init (void)
 {
-  m4_symtab = m4_hash_new (m4_hash_string_hash, m4_hash_string_cmp);
-  m4_hash_resize (m4_symtab, 2047);
-}
-
-/* The following function is used for the cases where we want to do
-   something to each and every symbol in the table.  This function
-   traverses the symbol table, and calls a specified function FUNC for
-   each symbol in the table.  FUNC is called with a pointer to the
-   symbol, and the DATA argument.  */
-int
-m4_symtab_apply (m4_symtab_apply_func *func, void *data)
-{
-  int result = 0;
-  m4_hash_iterator *place = 0;
-
-  assert (func);
-
-  while ((place = m4_hash_iterator_next (m4_symtab, place)))
-    {
-      const char *name = (const char *) m4_hash_iterator_key (place);
-      m4_symbol *symbol = (m4_symbol *) m4_hash_iterator_value (place);
-
-      result = (*func) (name, symbol, data);
-
-      if (result != 0)
-       break;
-    }
-
-  return result;
+  m4_symtab = m4_hash_new (M4_SYMTAB_DEFAULT_SIZE,
+                          m4_hash_string_hash, m4_hash_string_cmp);
 }
 
 
@@ -136,9 +113,9 @@ m4_symtab_remove_module_references (lt_d
 void
 m4_symtab_exit (void)
 {
-  m4_symtab_apply (m4_symbol_destroy, NULL);
-  m4_hash_delete  (m4_symtab);
-  m4_hash_exit    ();
+  m4_hash_apply  (m4_symtab, m4_symbol_destroy, m4_symtab);
+  m4_hash_delete (m4_symtab);
+  m4_hash_exit   ();
 }
 
 /* This callback is used exclusively by m4_symtab_exit(), to cleanup
@@ -146,13 +123,13 @@ m4_symtab_exit (void)
    on every symbol so that m4_symbol_popdef() doesn't try to preserve
    the table entry.  */
 static int
-m4_symbol_destroy (const char *name, m4_symbol *symbol, void *data)
+m4_symbol_destroy (const void *name, void *symbol, void *symtab)
 {
-  char *key = xstrdup (name);
+  char *key = xstrdup ((char *) name);
 
-  SYMBOL_TRACED (symbol) = FALSE;
+  SYMBOL_TRACED ((m4_symbol *) symbol) = FALSE;
 
-  while (key && m4_hash_lookup (m4_symtab, key))
+  while (key && m4_hash_lookup ((m4_hash *) symtab, key))
     m4_symbol_popdef (key);
 
   XFREE (key);
@@ -240,6 +217,12 @@ m4_symbol_popdef (const char *name)
     {
       SYMBOL_TOKEN (*psymbol) = TOKEN_NEXT (stale);
 
+      if (TOKEN_ARG_SIGNATURE (stale))
+       {
+         m4_hash_apply (TOKEN_ARG_SIGNATURE (stale),
+                        m4_arg_destroy, NULL);
+         m4_hash_delete (TOKEN_ARG_SIGNATURE (stale));
+       }
       if (TOKEN_TYPE (stale) == M4_TOKEN_TEXT)
        XFREE (TOKEN_TEXT (stale));
       XFREE (stale);
@@ -264,6 +247,19 @@ m4_symbol_delete (const char *name)
     m4_symbol_popdef (name);
 }
 
+/* Callback used by m4_symbol_popdef () to release the memory used
+   by values in the arg_signature hash.  */
+static int
+m4_arg_destroy (const void *ignored, void *arg, void *also_ignored)
+{
+  struct m4_token_arg *token_arg = (struct m4_token_arg *) arg;
+
+  if (TOKEN_ARG_DEFAULT (token_arg))
+    XFREE (TOKEN_ARG_DEFAULT (token_arg));
+  xfree (arg);
+
+  return 0;
+}
 
 
 /* Set the type and value of a symbol according to the passed
@@ -320,7 +316,7 @@ m4_symbol_macro (m4_symbol *symbol, m4_t
 
 #ifdef DEBUG_SYM
 
-static int symtab_print_list (const char *name, m4_symbol *symbol, void 
*ignored);
+static int symtab_print_list (const void *name, void *symbol, void *ignored);
 static void symtab_dump (void);
 
 static void
@@ -397,16 +393,16 @@ symtab_debug (void)
       else
        (void) m4_symbol_define (text);
     }
-  m4_symtab_apply (symtab_print_list, 0);
+  m4_hash_apply (m4_symtab, symtab_print_list, NULL);
 }
 
 static int
-symtab_print_list (const char *name, m4_symbol *symbol, void *ignored)
+symtab_print_list (const void *name, void *symbol, void *ignored)
 {
   printf ("\tname %s, addr %#x, flags: %d %s\n",
-         name, (unsigned) symbol,
-         SYMBOL_FLAGS (symbol),
-         SYMBOL_TRACED (symbol) ? " traced" : "<none>");
+         (char *) name, (unsigned) symbol,
+         SYMBOL_FLAGS ((m4_symbol *) symbol),
+         SYMBOL_TRACED ((m4_symbol *) symbol) ? " traced" : "<none>");
   return 0;
 }
 
Index: m4/syntax.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/syntax.c,v
retrieving revision 1.1
diff -u -p -u -r1.1 syntax.c
--- m4/syntax.c 29 May 2002 18:06:42 -0000 1.1
+++ m4/syntax.c 6 Jun 2003 16:06:34 -0000
@@ -35,9 +35,10 @@
    M4_SYNTAX_CLOSE     Close list of macro arguments
    M4_SYNTAX_COMMA     Separates macro arguments
    M4_SYNTAX_DOLLAR    *Indicates macro argument in user macros
-   M4_SYNTAX_ACTIVE    This caracter is a macro name by itself
-
+   M4_SYNTAX_ACTIVE    This character is a macro name by itself
    M4_SYNTAX_ESCAPE    Use this character to prefix all macro names
+   M4_SYNTAX_ASSIGN    Used to assign defaults in parameter lists
+
    M4_SYNTAX_ALPHA     Alphabetic characters (can start macro names)
    M4_SYNTAX_NUM       Numeric characters
    M4_SYNTAX_ALNUM     Alphanumeric characters (can form macro names)
@@ -116,6 +117,8 @@ m4_syntax_init (void)
        set_syntax_internal (M4_SYNTAX_CLOSE, ch);
       else if (ch == ',')
        set_syntax_internal (M4_SYNTAX_COMMA, ch);
+      else if (ch == '=')
+       set_syntax_internal (M4_SYNTAX_ASSIGN, ch);
       else if (isspace (ch))
        set_syntax_internal (M4_SYNTAX_SPACE, ch);
       else if (isalpha (ch) || ch == '_')
@@ -156,6 +159,7 @@ m4_syntax_code (char ch)
     case '(': code = M4_SYNTAX_OPEN;   break;
     case ')': code = M4_SYNTAX_CLOSE;  break;
     case ',': code = M4_SYNTAX_COMMA;  break;
+    case '=': code = M4_SYNTAX_ASSIGN; break;
     case '@': code = M4_SYNTAX_ESCAPE; break;
 #if 0                          /* not yet used */
     case '$': code = M4_SYNTAX_DOLLAR; break;
Index: m4/system-h.in
===================================================================
RCS file: /cvsroot/m4/m4/m4/system-h.in,v
retrieving revision 1.1
diff -u -p -u -r1.1 system-h.in
--- m4/system-h.in 6 Sep 2001 20:13:12 -0000 1.1
+++ m4/system-h.in 6 Jun 2003 16:06:34 -0000
@@ -178,6 +178,7 @@ extern void *xrealloc (void *p, size_t n
 extern void *xfree    (void *stale);
 
 extern char *xstrdup  (const char *string);
+extern char *xstrzdup (const char *string, size_t len);
 
 END_C_DECLS
 
Index: m4/utility.c
===================================================================
RCS file: /cvsroot/m4/m4/m4/utility.c,v
retrieving revision 1.22
diff -u -p -u -r1.22 utility.c
--- m4/utility.c 30 May 2003 15:13:32 -0000 1.22
+++ m4/utility.c 6 Jun 2003 16:06:34 -0000
@@ -132,7 +132,7 @@ m4_skip_space (const char *arg)
 }
 
 /* The function m4_numeric_arg () converts ARG to an int pointed to by
-   VALUEP. If the conversion fails, print error message for macro MACRO.
+   VALUEP. If the conversion fails, print error message for macro.
    Return TRUE iff conversion succeeds.  */
 boolean
 m4_numeric_arg (int argc, m4_token **argv, int arg, int *valuep)
@@ -222,16 +222,16 @@ dumpdef_cmp (const void *s1, const void 
 /* The function dump_symbol () is for use by "dumpdef".  It builds up a
    table of all defined symbol names.  */
 int
-m4_dump_symbol (const char *name, m4_symbol *symbol, void *data)
+m4_dump_symbol (const void *name, void *symbol, void *data)
 {
-  if (SYMBOL_TYPE (symbol) != M4_TOKEN_VOID)
+  if (SYMBOL_TYPE ((m4_symbol *) symbol) != M4_TOKEN_VOID)
     {
       struct m4_dump_symbol_data *symbol_data
        = (struct m4_dump_symbol_data *) data;
 
       obstack_blank (symbol_data->obs, sizeof (const char *));
       symbol_data->base = (const char **) obstack_base (symbol_data->obs);
-      symbol_data->base[symbol_data->size++] = name;
+      symbol_data->base[symbol_data->size++] = (const char *) name;
     }
 
   return 0;
@@ -248,7 +248,7 @@ m4_dump_symbols (struct m4_dump_symbol_d
 
   if (argc == 1)
     {
-      m4_symtab_apply (m4_dump_symbol, data);
+      m4_hash_apply (m4_symtab, m4_dump_symbol, data);
     }
   else
     {
Index: modules/m4.c
===================================================================
RCS file: /cvsroot/m4/m4/modules/m4.c,v
retrieving revision 1.34
diff -u -p -u -r1.34 m4.c
--- modules/m4.c 5 Jun 2003 16:12:16 -0000 1.34
+++ modules/m4.c 6 Jun 2003 16:06:35 -0000
@@ -94,7 +94,7 @@ typedef unsigned long int unumber;
 
 static void    include         (int argc, m4_token **argv,
                                 boolean silent);
-static int     set_trace       (const char *name, m4_symbol *symbol,
+static int     set_trace       (const void *ignored, void *symbol,
                                 void *data);
 static const char *ntoa                (number value, int radix);
 static void    numb_obstack    (struct obstack *obs, const number value,
@@ -581,9 +581,9 @@ M4BUILTIN_HANDLER (m4wrap)
    tracing of a macro.  It disables tracing if DATA is NULL, otherwise it
    enable tracing.  */
 static int
-set_trace (const char *name, m4_symbol *symbol, void *data)
+set_trace (const void *ignored, void *symbol, void *data)
 {
-  SYMBOL_TRACED (symbol) = (boolean) (data != NULL);
+  SYMBOL_TRACED ((m4_symbol *) symbol) = (boolean) (data != NULL);
   return 0;
 }
 
@@ -592,7 +592,7 @@ M4BUILTIN_HANDLER (traceon)
   int i;
 
   if (argc == 1)
-    m4_symtab_apply (set_trace, (char *) obs);
+    m4_hash_apply (m4_symtab, set_trace, (void *) obs);
   else
     for (i = 1; i < argc; i++)
       {
@@ -612,7 +612,7 @@ M4BUILTIN_HANDLER (traceoff)
   int i;
 
   if (argc == 1)
-    m4_symtab_apply (set_trace, NULL);
+    m4_hash_apply (m4_symtab, set_trace, NULL);
   else
     for (i = 1; i < argc; i++)
       {

reply via email to

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