* gdbarch.sh (pointer_to_address): Change to type 'm'.
[binutils-gdb.git] / gas / macro.c
index 23156a1242a42a5185359eaa72c88b75a5d90bda..2c72331f075823bfd034305b187c1b3d18bece3f 100644 (file)
@@ -1,6 +1,6 @@
 /* macro.c - macro support for gas
    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004, 2005 Free Software Foundation, Inc.
+   2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
    Written by Steve and Judy Chamberlain of Cygnus Support,
       sac@cygnus.com
@@ -9,7 +9,7 @@
 
    GAS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GAS is distributed in the hope that it will be useful,
    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
-#include "config.h"
-
-#ifndef __GNUC__
-# if HAVE_ALLOCA_H
-#  include <alloca.h>
-# else
-#  ifdef _AIX
-/* Indented so that pre-ansi C compilers will ignore it, rather than
-   choke on it.  Some versions of AIX require this to be the first
-   thing in the file.  */
- #pragma alloca
-#  else
-#   ifndef alloca /* predefined by HP cc +Olibcalls */
-#    if !defined (__STDC__) && !defined (__hpux)
-extern char *alloca ();
-#    else
-extern void *alloca ();
-#    endif /* __STDC__, __hpux */
-#   endif /* alloca */
-#  endif /* _AIX */
-# endif /* HAVE_ALLOCA_H */
-#endif /* __GNUC__ */
-
-#include <stdio.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#include <strings.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
 #include "as.h"
-#include "libiberty.h"
 #include "safe-ctype.h"
 #include "sb.h"
-#include "hash.h"
 #include "macro.h"
 
-#include "asintl.h"
-
 /* The routines in this file handle macro definition and expansion.
    They are called by gas.  */
 
@@ -303,18 +267,14 @@ getstring (int idx, sb *in, sb *acc)
 {
   while (idx < in->len
         && (in->ptr[idx] == '"'
-            || in->ptr[idx] == '('
             || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
             || (in->ptr[idx] == '\'' && macro_alternate)))
     {
       if (in->ptr[idx] == '<')
        {
          int nest = 0;
-         char start_char = '>';
-         char end_char = '>';
-
          idx++;
-         while ((in->ptr[idx] != end_char || nest)
+         while ((in->ptr[idx] != '>' || nest)
                 && idx < in->len)
            {
              if (in->ptr[idx] == '!')
@@ -324,37 +284,15 @@ getstring (int idx, sb *in, sb *acc)
                }
              else
                {
-                 if (in->ptr[idx] == end_char)
+                 if (in->ptr[idx] == '>')
                    nest--;
-                 if (in->ptr[idx] == start_char)
+                 if (in->ptr[idx] == '<')
                    nest++;
                  sb_add_char (acc, in->ptr[idx++]);
                }
            }
          idx++;
        }
-      else if (in->ptr[idx] == '(')
-       {
-         int nest = 0;
-         char c;
-
-         do
-           {
-             c = in->ptr[idx];
-
-             if (c == '!')
-               c = in->ptr[++idx];
-             else if (c == ')')
-               nest--;
-             else if (c == '(')
-               nest++;
-
-             sb_add_char (acc, c);
-             idx++;
-           }
-         while ((c != ')' || nest)
-                && idx < in->len);
-       }
       else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
        {
          char tchar = in->ptr[idx];
@@ -438,17 +376,15 @@ get_any_string (int idx, sb *in, sb *out)
          sb_add_string (out, buf);
        }
       else if (in->ptr[idx] == '"'
-              || in->ptr[idx] == '('
               || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
               || (macro_alternate && in->ptr[idx] == '\''))
        {
-         if (macro_alternate && ! macro_strip_at)
+         if (macro_alternate && ! macro_strip_at && in->ptr[idx] != '<')
            {
              /* Keep the quotes.  */
-             sb_add_char (out, '\"');
-
+             sb_add_char (out, '"');
              idx = getstring (idx, in, out);
-             sb_add_char (out, '\"');
+             sb_add_char (out, '"');
            }
          else
            {
@@ -457,27 +393,57 @@ get_any_string (int idx, sb *in, sb *out)
        }
       else
        {
+         char *br_buf = xmalloc(1);
+         char *in_br = br_buf;
+
+         *in_br = '\0';
          while (idx < in->len
-                && in->ptr[idx] != ' '
-                && in->ptr[idx] != '\t'
+                && (*in_br
+                    || (in->ptr[idx] != ' '
+                        && in->ptr[idx] != '\t'))
                 && in->ptr[idx] != ','
                 && (in->ptr[idx] != '<'
                     || (! macro_alternate && ! macro_mri)))
            {
-             if (in->ptr[idx] == '"'
-                 || in->ptr[idx] == '\'')
-               {
-                 char tchar = in->ptr[idx];
+             char tchar = in->ptr[idx];
 
+             switch (tchar)
+               {
+               case '"':
+               case '\'':
                  sb_add_char (out, in->ptr[idx++]);
                  while (idx < in->len
                         && in->ptr[idx] != tchar)
                    sb_add_char (out, in->ptr[idx++]);
                  if (idx == in->len)
                    return idx;
+                 break;
+               case '(':
+               case '[':
+                 if (in_br > br_buf)
+                   --in_br;
+                 else
+                   {
+                     br_buf = xmalloc(strlen(in_br) + 2);
+                     strcpy(br_buf + 1, in_br);
+                     free(in_br);
+                     in_br = br_buf;
+                   }
+                 *in_br = tchar;
+                 break;
+               case ')':
+                 if (*in_br == '(')
+                   ++in_br;
+                 break;
+               case ']':
+                 if (*in_br == '[')
+                   ++in_br;
+                 break;
                }
-             sb_add_char (out, in->ptr[idx++]);
+             sb_add_char (out, tchar);
+             ++idx;
            }
+         free(br_buf);
        }
     }
 
@@ -710,7 +676,7 @@ define_macro (int idx, sb *in, sb *label,
   if (hash_find (macro_hash, macro->name))
     error = _("Macro `%s' was already defined");
   if (!error)
-    error = hash_jam (macro_hash, macro->name, (PTR) macro);
+    error = hash_jam (macro_hash, macro->name, (void *) macro);
 
   if (namep != NULL)
     *namep = macro->name;
@@ -1002,11 +968,11 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
   while (loclist != NULL)
     {
       formal_entry *f;
+      const char *name;
 
       f = loclist->next;
-      /* Setting the value to NULL effectively deletes the entry.  We
-         avoid calling hash_delete because it doesn't reclaim memory.  */
-      hash_jam (formal_hash, sb_terminate (&loclist->name), NULL);
+      name = sb_terminate (&loclist->name);
+      hash_delete (formal_hash, name, f == NULL);
       del_formal (loclist);
       loclist = f;
     }
@@ -1023,7 +989,6 @@ macro_expand (int idx, sb *in, macro_entry *m, sb *out)
   sb t;
   formal_entry *ptr;
   formal_entry *f;
-  int is_positional = 0;
   int is_keyword = 0;
   int narg = 0;
   const char *err = NULL;
@@ -1114,8 +1079,6 @@ macro_expand (int idx, sb *in, macro_entry *m, sb *out)
        }
       else
        {
-         /* This is a positional arg.  */
-         is_positional = 1;
          if (is_keyword)
            {
              err = _("can't mix positional and keyword arguments");
@@ -1307,7 +1270,9 @@ delete_macro (const char *name)
     copy[i] = TOLOWER (name[i]);
   copy[i] = '\0';
 
-  /* Since hash_delete doesn't free memory, just clear out the entry.  */
+  /* We can only ask hash_delete to free memory if we are deleting
+     macros in reverse order to their definition.
+     So just clear out the entry.  */
   if ((macro = hash_find (macro_hash, copy)) != NULL)
     {
       hash_jam (macro_hash, copy, NULL);
@@ -1362,8 +1327,14 @@ expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *))
     }
   else
     {
+      bfd_boolean in_quotes = FALSE;
+
       if (irpc && in->ptr[idx] == '"')
-       ++idx;
+       {
+         in_quotes = TRUE;
+         ++idx;
+       }
+
       while (idx < in->len)
        {
          if (!irpc)
@@ -1374,6 +1345,9 @@ expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *))
                {
                  int nxt;
 
+                 if (irpc)
+                   in_quotes = ! in_quotes;
+         
                  nxt = sb_skip_white (idx + 1, in);
                  if (nxt >= in->len)
                    {
@@ -1385,12 +1359,13 @@ expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *))
              sb_add_char (&f.actual, in->ptr[idx]);
              ++idx;
            }
+
          err = macro_expand_body (&sub, out, &f, h, 0);
          if (err != NULL)
            break;
          if (!irpc)
            idx = sb_skip_comma (idx, in);
-         else
+         else if (! in_quotes)
            idx = sb_skip_white (idx, in);
        }
     }