2005-04-19 H.J. Lu <hongjiu.lu@intel.com>
[deliverable/binutils-gdb.git] / gas / macro.c
index 2aeb157388ee8d9bfbffc2de0dd411fc7e946524..081940446153fa72f3ae9c526eacc7bde6c1364c 100644 (file)
@@ -1,5 +1,6 @@
-/* macro.c - macro support for gas and gasp
-   Copyright (C) 1994, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+/* macro.c - macro support for gas
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+   2004, 2005 Free Software Foundation, Inc.
 
    Written by Steve and Judy Chamberlain of Cygnus Support,
       sac@cygnus.com
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to the Free
    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA. */
+   02111-1307, USA.  */
 
 #include "config.h"
 
-/* AIX requires this to be the first thing in the file.  */
-#ifdef __GNUC__
-# ifndef alloca
-#  ifdef __STDC__
-extern void *alloca ();
-#  else
-extern char *alloca ();
-#  endif
-# endif
-#else
+#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 */
@@ -48,7 +43,7 @@ extern void *alloca ();
 #   endif /* alloca */
 #  endif /* _AIX */
 # endif /* HAVE_ALLOCA_H */
-#endif
+#endif /* __GNUC__ */
 
 #include <stdio.h>
 #ifdef HAVE_STRING_H
@@ -56,11 +51,12 @@ extern void *alloca ();
 #else
 #include <strings.h>
 #endif
-#include <ctype.h>
 #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"
@@ -68,56 +64,20 @@ extern void *alloca ();
 #include "asintl.h"
 
 /* The routines in this file handle macro definition and expansion.
-   They are called by both gasp and gas.  */
-
-/* Structures used to store macros. 
-
-   Each macro knows its name and included text.  It gets built with a
-   list of formal arguments, and also keeps a hash table which points
-   into the list to speed up formal search.  Each formal knows its
-   name and its default value.  Each time the macro is expanded, the
-   formals get the actual values attatched to them. */
-
-/* describe the formal arguments to a macro */
-
-typedef struct formal_struct
-  {
-    struct formal_struct *next;        /* next formal in list */
-    sb name;                   /* name of the formal */
-    sb def;                    /* the default value */
-    sb actual;                 /* the actual argument (changed on each expansion) */
-    int index;                 /* the index of the formal 0..formal_count-1 */
-  }
-formal_entry;
-
-/* Other values found in the index field of a formal_entry.  */
-#define QUAL_INDEX (-1)
-#define NARG_INDEX (-2)
-#define LOCAL_INDEX (-3)
-
-/* describe the macro. */
-
-typedef struct macro_struct
-  {
-    sb sub;                    /* substitution text. */
-    int formal_count;          /* number of formal args. */
-    formal_entry *formals;     /* pointer to list of formal_structs */
-    struct hash_control *formal_hash; /* hash table of formals. */
-  }
-macro_entry;
+   They are called by gas.  */
 
 /* Internal functions.  */
 
-static int get_token PARAMS ((int, sb *, sb *));
-static int getstring PARAMS ((int, sb *, sb *));
-static int get_any_string PARAMS ((int, sb *, sb *, int, int));
-static int do_formals PARAMS ((macro_entry *, int, sb *));
-static int get_apost_token PARAMS ((int, sb *, sb *, int));
-static int sub_actual
-  PARAMS ((int, sb *, sb *, struct hash_control *, int, sb *, int));
+static int get_token (int, sb *, sb *);
+static int getstring (int, sb *, sb *);
+static int get_any_string (int, sb *, sb *, int, int);
+static int do_formals (macro_entry *, int, sb *);
+static int get_apost_token (int, sb *, sb *, int);
+static int sub_actual (int, sb *, sb *, struct hash_control *, int, sb *, int);
 static const char *macro_expand_body
-  PARAMS ((sb *, sb *, formal_entry *, struct hash_control *, int, int));
-static const char *macro_expand PARAMS ((int, sb *, macro_entry *, sb *, int));
+  (sb *, sb *, formal_entry *, struct hash_control *, int);
+static const char *macro_expand (int, sb *, macro_entry *, sb *);
+static void free_macro(macro_entry *);
 
 #define ISWHITE(x) ((x) == ' ' || (x) == '\t')
 
@@ -134,13 +94,13 @@ static const char *macro_expand PARAMS ((int, sb *, macro_entry *, sb *, int));
 
 /* The macro hash table.  */
 
-static struct hash_control *macro_hash;
+struct hash_control *macro_hash;
 
 /* Whether any macros have been defined.  */
 
 int macro_defined;
 
-/* Whether we are in GASP alternate mode.  */
+/* Whether we are in alternate syntax mode.  */
 
 static int macro_alternate;
 
@@ -154,7 +114,7 @@ static int macro_strip_at;
 
 /* Function to use to parse an expression.  */
 
-static int (*macro_expr) PARAMS ((const char *, int, sb *, int *));
+static int (*macro_expr) (const char *, int, sb *, int *);
 
 /* Number of macro expansions that have been done.  */
 
@@ -163,11 +123,8 @@ static int macro_number;
 /* Initialize macro processing.  */
 
 void
-macro_init (alternate, mri, strip_at, expr)
-     int alternate;
-     int mri;
-     int strip_at;
-     int (*expr) PARAMS ((const char *, int, sb *, int *));
+macro_init (int alternate, int mri, int strip_at,
+           int (*expr) (const char *, int, sb *, int *))
 {
   macro_hash = hash_new ();
   macro_defined = 0;
@@ -177,11 +134,18 @@ macro_init (alternate, mri, strip_at, expr)
   macro_expr = expr;
 }
 
+/* Switch in and out of alternate mode on the fly.  */
+
+void
+macro_set_alternate (int alternate)
+{
+  macro_alternate = alternate;
+}
+
 /* Switch in and out of MRI mode on the fly.  */
 
 void
-macro_mri_mode (mri)
-     int mri;
+macro_mri_mode (int mri)
 {
   macro_mri = mri;
 }
@@ -189,78 +153,116 @@ macro_mri_mode (mri)
 /* Read input lines till we get to a TO string.
    Increase nesting depth if we get a FROM string.
    Put the results into sb at PTR.
+   FROM may be NULL (or will be ignored) if TO is "ENDR".
    Add a new input line to an sb using GET_LINE.
    Return 1 on success, 0 on unexpected EOF.  */
 
 int
-buffer_and_nest (from, to, ptr, get_line)
-     const char *from;
-     const char *to;
-     sb *ptr;
-     int (*get_line) PARAMS ((sb *));
+buffer_and_nest (const char *from, const char *to, sb *ptr,
+                int (*get_line) (sb *))
 {
-  int from_len = strlen (from);
+  int from_len;
   int to_len = strlen (to);
   int depth = 1;
   int line_start = ptr->len;
 
   int more = get_line (ptr);
 
+  if (to_len == 4 && strcasecmp(to, "ENDR") == 0)
+    {
+      from = NULL;
+      from_len = 0;
+    }
+  else
+    from_len = strlen (from);
+
   while (more)
     {
-      /* Try and find the first pseudo op on the line */
+      /* Try and find the first pseudo op on the line */
       int i = line_start;
 
-      if (! macro_alternate && ! macro_mri)
+      if (! NO_PSEUDO_DOT && ! flag_m68k_mri)
        {
          /* With normal syntax we can suck what we want till we get
             to the dot.  With the alternate, labels have to start in
-            the first column, since we cant tell what's a label and
-            whats a pseudoop */
+            the first column, since we can't tell what's a label and
+            whats a pseudoop */
 
-         /* Skip leading whitespace */
-         while (i < ptr->len && ISWHITE (ptr->ptr[i]))
-           i++;
-
-         /* Skip over a label */
-         while (i < ptr->len
-                && (isalnum ((unsigned char) ptr->ptr[i])
-                    || ptr->ptr[i] == '_'
-                    || ptr->ptr[i] == '$'))
-           i++;
+         if (! LABELS_WITHOUT_COLONS)
+           {
+             /* Skip leading whitespace.  */
+             while (i < ptr->len && ISWHITE (ptr->ptr[i]))
+               i++;
+           }
 
-         /* And a colon */
-         if (i < ptr->len
-             && ptr->ptr[i] == ':')
-           i++;
+         for (;;)
+           {
+             /* Skip over a label, if any.  */
+             if (i >= ptr->len || ! is_name_beginner (ptr->ptr[i]))
+               break;
+             i++;
+             while (i < ptr->len && is_part_of_name (ptr->ptr[i]))
+               i++;
+             if (i < ptr->len && is_name_ender (ptr->ptr[i]))
+               i++;
+             if (LABELS_WITHOUT_COLONS)
+               break;
+             /* Skip whitespace.  */
+             while (i < ptr->len && ISWHITE (ptr->ptr[i]))
+               i++;
+             /* Check for the colon.  */
+             if (i >= ptr->len || ptr->ptr[i] != ':')
+               {
+                 i = line_start;
+                 break;
+               }
+             i++;
+             line_start = i;
+           }
 
        }
-      /* Skip trailing whitespace */
+      /* Skip trailing whitespace */
       while (i < ptr->len && ISWHITE (ptr->ptr[i]))
        i++;
 
       if (i < ptr->len && (ptr->ptr[i] == '.'
-                          || macro_alternate
+                          || NO_PSEUDO_DOT
                           || macro_mri))
        {
-         if (ptr->ptr[i] == '.')
-             i++;
-         if (strncasecmp (ptr->ptr + i, from, from_len) == 0)
+         if (! flag_m68k_mri && ptr->ptr[i] == '.')
+           i++;
+         if (from == NULL
+            && strncasecmp (ptr->ptr + i, "IRPC", from_len = 4) != 0
+            && strncasecmp (ptr->ptr + i, "IRP", from_len = 3) != 0
+            && strncasecmp (ptr->ptr + i, "IREPC", from_len = 5) != 0
+            && strncasecmp (ptr->ptr + i, "IREP", from_len = 4) != 0
+            && strncasecmp (ptr->ptr + i, "REPT", from_len = 4) != 0
+            && strncasecmp (ptr->ptr + i, "REP", from_len = 3) != 0)
+           from_len = 0;
+         if ((from != NULL
+              ? strncasecmp (ptr->ptr + i, from, from_len) == 0
+              : from_len > 0)
+             && (ptr->len == (i + from_len)
+                 || ! (is_part_of_name (ptr->ptr[i + from_len])
+                       || is_name_ender (ptr->ptr[i + from_len]))))
            depth++;
-         if (strncasecmp (ptr->ptr + i, to, to_len) == 0)
+         if (strncasecmp (ptr->ptr + i, to, to_len) == 0
+             && (ptr->len == (i + to_len)
+                 || ! (is_part_of_name (ptr->ptr[i + to_len])
+                       || is_name_ender (ptr->ptr[i + to_len]))))
            {
              depth--;
              if (depth == 0)
                {
-                 /* Reset the string to not include the ending rune */
+                 /* Reset the string to not include the ending rune */
                  ptr->len = line_start;
                  break;
                }
            }
        }
 
-      /* Add a CR to the end and keep running */
-      sb_add_char (ptr, '\n');
+      /* Add the original end-of-line char to the end and keep running.  */
+      sb_add_char (ptr, more);
       line_start = ptr->len;
       more = get_line (ptr);
     }
@@ -272,26 +274,24 @@ buffer_and_nest (from, to, ptr, get_line)
 /* Pick up a token.  */
 
 static int
-get_token (idx, in, name)
-     int idx;
-     sb *in;
-     sb *name;
+get_token (int idx, sb *in, sb *name)
 {
   if (idx < in->len
-      && (isalpha ((unsigned char) in->ptr[idx])
-         || in->ptr[idx] == '_'
-         || in->ptr[idx] == '$'))
+      && is_name_beginner (in->ptr[idx]))
     {
       sb_add_char (name, in->ptr[idx++]);
       while (idx < in->len
-            && (isalnum ((unsigned char) in->ptr[idx])
-                || in->ptr[idx] == '_'
-                || in->ptr[idx] == '$'))
+            && is_part_of_name (in->ptr[idx]))
+       {
+         sb_add_char (name, in->ptr[idx++]);
+       }
+      if (idx < in->len
+            && is_name_ender (in->ptr[idx]))
        {
          sb_add_char (name, in->ptr[idx++]);
        }
     }
-  /* Ignore trailing & */
+  /* Ignore trailing & */
   if (macro_alternate && idx < in->len && in->ptr[idx] == '&')
     idx++;
   return idx;
@@ -300,15 +300,12 @@ get_token (idx, in, name)
 /* Pick up a string.  */
 
 static int
-getstring (idx, in, acc)
-     int idx;
-     sb *in;
-     sb *acc;
+getstring (int idx, sb *in, sb *acc)
 {
   idx = sb_skip_white (idx, in);
 
   while (idx < in->len
-        && (in->ptr[idx] == '"' 
+        && (in->ptr[idx] == '"'
             || (in->ptr[idx] == '<' && (macro_alternate || macro_mri))
             || (in->ptr[idx] == '\'' && macro_alternate)))
     {
@@ -321,7 +318,7 @@ getstring (idx, in, acc)
            {
              if (in->ptr[idx] == '!')
                {
-                 idx++  ;
+                 idx++;
                  sb_add_char (acc, in->ptr[idx++]);
                }
              else
@@ -338,29 +335,47 @@ getstring (idx, in, acc)
       else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
        {
          char tchar = in->ptr[idx];
+         int escaped = 0;
+
          idx++;
+
          while (idx < in->len)
            {
+             if (in->ptr[idx - 1] == '\\')
+               escaped ^= 1;
+             else
+               escaped = 0;
+
              if (macro_alternate && in->ptr[idx] == '!')
                {
-                 idx++  ;
-                 sb_add_char (acc, in->ptr[idx++]);
+                 idx ++;
+
+                 sb_add_char (acc, in->ptr[idx]);
+
+                 idx ++;
+               }
+             else if (escaped && in->ptr[idx] == tchar)
+               {
+                 sb_add_char (acc, tchar);
+                 idx ++;
                }
              else
                {
                  if (in->ptr[idx] == tchar)
                    {
-                     idx++;
+                     idx ++;
+
                      if (idx >= in->len || in->ptr[idx] != tchar)
                        break;
                    }
+
                  sb_add_char (acc, in->ptr[idx]);
-                 idx++;
+                 idx ++;
                }
            }
        }
     }
-  
+
   return idx;
 }
 
@@ -373,19 +388,14 @@ getstring (idx, in, acc)
 */
 
 static int
-get_any_string (idx, in, out, expand, pretend_quoted)
-     int idx;
-     sb *in;
-     sb *out;
-     int expand;
-     int pretend_quoted;
+get_any_string (int idx, sb *in, sb *out, int expand, int pretend_quoted)
 {
   sb_reset (out);
   idx = sb_skip_white (idx, in);
 
   if (idx < in->len)
     {
-      if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx]))
+      if (in->len > idx + 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
        {
          while (!ISSEP (in->ptr[idx]))
            sb_add_char (out, in->ptr[idx++]);
@@ -396,12 +406,13 @@ get_any_string (idx, in, out, expand, pretend_quoted)
        {
          int val;
          char buf[20];
-         /* Turns the next expression into a string */
+         /* Turns the next expression into a string.  */
+         /* xgettext: no-c-format */
          idx = (*macro_expr) (_("% operator needs absolute expression"),
                               idx + 1,
                               in,
                               &val);
-         sprintf(buf, "%d", val);
+         sprintf (buf, "%d", val);
          sb_add_string (out, buf);
        }
       else if (in->ptr[idx] == '"'
@@ -412,39 +423,39 @@ get_any_string (idx, in, out, expand, pretend_quoted)
              && ! macro_strip_at
              && expand)
            {
-             /* Keep the quotes */
-             sb_add_char (out,  '\"');
+             /* Keep the quotes */
+             sb_add_char (out, '\"');
 
              idx = getstring (idx, in, out);
-             sb_add_char (out,  '\"');
+             sb_add_char (out, '\"');
            }
          else
            {
              idx = getstring (idx, in, out);
            }
        }
-      else 
+      else
        {
-         while (idx < in->len 
+         while (idx < in->len
                 && (in->ptr[idx] == '"'
                     || in->ptr[idx] == '\''
-                    || pretend_quoted 
+                    || pretend_quoted
                     || (in->ptr[idx] != ' '
                         && in->ptr[idx] != '\t'
                         && in->ptr[idx] != ','
                         && (in->ptr[idx] != '<'
                             || (! macro_alternate && ! macro_mri)))))
            {
-             if (in->ptr[idx] == '"' 
+             if (in->ptr[idx] == '"'
                  || in->ptr[idx] == '\'')
                {
                  char tchar = in->ptr[idx];
                  sb_add_char (out, in->ptr[idx++]);
                  while (idx < in->len
                         && in->ptr[idx] != tchar)
-                   sb_add_char (out, in->ptr[idx++]);              
+                   sb_add_char (out, in->ptr[idx++]);
                  if (idx == in->len)
-                   return idx;       
+                   return idx;
                }
              sb_add_char (out, in->ptr[idx++]);
            }
@@ -457,18 +468,15 @@ get_any_string (idx, in, out, expand, pretend_quoted)
 /* Pick up the formal parameters of a macro definition.  */
 
 static int
-do_formals (macro, idx, in)
-     macro_entry *macro;
-     int idx;
-     sb *in;
+do_formals (macro_entry *macro, int idx, sb *in)
 {
   formal_entry **p = &macro->formals;
 
-  macro->formal_count = 0;
-  macro->formal_hash = hash_new ();
+  idx = sb_skip_white (idx, in);
   while (idx < in->len)
     {
       formal_entry *formal;
+      int cidx;
 
       formal = (formal_entry *) xmalloc (sizeof (formal_entry));
 
@@ -476,27 +484,33 @@ do_formals (macro, idx, in)
       sb_new (&formal->def);
       sb_new (&formal->actual);
 
-      idx = sb_skip_white (idx, in);
       idx = get_token (idx, in, &formal->name);
       if (formal->name.len == 0)
-       break;
+       {
+         if (macro->formal_count)
+           --idx;
+         break;
+       }
       idx = sb_skip_white (idx, in);
-      if (formal->name.len)
+      /* This is a formal.  */
+      if (idx < in->len && in->ptr[idx] == '=')
        {
-         /* This is a formal */
-         if (idx < in->len && in->ptr[idx] == '=')
-           {
-             /* Got a default */
-             idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
-           }
+         /* Got a default.  */
+         idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
+         idx = sb_skip_white (idx, in);
        }
 
-      /* Add to macro's hash table */
+      /* Add to macro's hash table */
       hash_jam (macro->formal_hash, sb_terminate (&formal->name), formal);
 
-      formal->index = macro->formal_count;
+      formal->index = macro->formal_count++;
+      cidx = idx;
       idx = sb_skip_comma (idx, in);
-      macro->formal_count++;
+      if (idx != cidx && idx >= in->len)
+       {
+         idx = cidx;
+         break;
+       }
       *p = formal;
       p = &formal->next;
       *p = NULL;
@@ -524,7 +538,7 @@ do_formals (macro, idx, in)
 
       sb_add_string (&formal->name, name);
 
-      /* Add to macro's hash table */
+      /* Add to macro's hash table */
       hash_jam (macro->formal_hash, name, formal);
 
       formal->index = NARG_INDEX;
@@ -540,12 +554,8 @@ do_formals (macro, idx, in)
    the macro which was defined.  */
 
 const char *
-define_macro (idx, in, label, get_line, namep)
-     int idx;
-     sb *in;
-     sb *label;
-     int (*get_line) PARAMS ((sb *));
-     const char **namep;
+define_macro (int idx, sb *in, sb *label,
+             int (*get_line) (sb *), const char **namep)
 {
   macro_entry *macro;
   sb name;
@@ -557,6 +567,7 @@ define_macro (idx, in, label, get_line, namep)
 
   macro->formal_count = 0;
   macro->formals = 0;
+  macro->formal_hash = hash_new ();
 
   idx = sb_skip_white (idx, in);
   if (! buffer_and_nest ("MACRO", "ENDM", &macro->sub, get_line))
@@ -566,29 +577,41 @@ define_macro (idx, in, label, get_line, namep)
       sb_add_sb (&name, label);
       if (idx < in->len && in->ptr[idx] == '(')
        {
-         /* It's the label: MACRO (formals,...)  sort */
+         /* It's the label: MACRO (formals,...)  sort  */
          idx = do_formals (macro, idx + 1, in);
-         if (in->ptr[idx] != ')')
+         if (idx >= in->len || in->ptr[idx] != ')')
            return _("missing ) after formals");
+         idx = sb_skip_white (idx + 1, in);
        }
       else
        {
-         /* It's the label: MACRO formals,...  sort */
+         /* It's the label: MACRO formals,...  sort  */
          idx = do_formals (macro, idx, in);
        }
     }
   else
     {
+      int cidx;
+
       idx = get_token (idx, in, &name);
-      idx = sb_skip_comma (idx, in);
-      idx = do_formals (macro, idx, in);
+      if (name.len == 0)
+       return _("Missing macro name");
+      cidx = sb_skip_white (idx, in);
+      idx = sb_skip_comma (cidx, in);
+      if (idx == cidx || idx < in->len)
+       idx = do_formals (macro, idx, in);
+      else
+       idx = cidx;
     }
+  if (idx < in->len)
+    return _("Bad macro parameter list");
 
-  /* and stick it in the macro hash table */
+  /* And stick it in the macro hash table.  */
   for (idx = 0; idx < name.len; idx++)
-    if (isupper ((unsigned char) name.ptr[idx]))
-      name.ptr[idx] = tolower (name.ptr[idx]);
+    name.ptr[idx] = TOLOWER (name.ptr[idx]);
   namestr = sb_terminate (&name);
+  if (hash_find (macro_hash, namestr))
+    return _("Macro with this name was already defined");
   hash_jam (macro_hash, namestr, (PTR) macro);
 
   macro_defined = 1;
@@ -602,11 +625,7 @@ define_macro (idx, in, label, get_line, namep)
 /* Scan a token, and then skip KIND.  */
 
 static int
-get_apost_token (idx, in, name, kind)
-     int idx;
-     sb *in;
-     sb *name;
-     int kind;
+get_apost_token (int idx, sb *in, sb *name, int kind)
 {
   idx = get_token (idx, in, name);
   if (idx < in->len
@@ -620,14 +639,8 @@ get_apost_token (idx, in, name, kind)
 /* Substitute the actual value for a formal parameter.  */
 
 static int
-sub_actual (start, in, t, formal_hash, kind, out, copyifnotthere)
-     int start;
-     sb *in;
-     sb *t;
-     struct hash_control *formal_hash;
-     int kind;
-     sb *out;
-     int copyifnotthere;
+sub_actual (int start, sb *in, sb *t, struct hash_control *formal_hash,
+           int kind, sb *out, int copyifnotthere)
 {
   int src;
   formal_entry *ptr;
@@ -656,12 +669,13 @@ sub_actual (start, in, t, formal_hash, kind, out, copyifnotthere)
     {
       /* Doing this permits people to use & in macro bodies.  */
       sb_add_char (out, '&');
+      sb_add_sb (out, t);
     }
   else if (copyifnotthere)
     {
       sb_add_sb (out, t);
     }
-  else 
+  else
     {
       sb_add_char (out, '\\');
       sb_add_sb (out, t);
@@ -672,13 +686,8 @@ sub_actual (start, in, t, formal_hash, kind, out, copyifnotthere)
 /* Expand the body of a macro.  */
 
 static const char *
-macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
-     sb *in;
-     sb *out;
-     formal_entry *formals;
-     struct hash_control *formal_hash;
-     int comment_char;
-     int locals;
+macro_expand_body (sb *in, sb *out, formal_entry *formals,
+                  struct hash_control *formal_hash, int locals)
 {
   sb t;
   int src = 0;
@@ -702,22 +711,16 @@ macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
          else
            {
              /* FIXME: Why do we do this?  */
+             /* At least in alternate mode this seems correct.  */
              src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
            }
        }
       else if (in->ptr[src] == '\\')
        {
          src++;
-         if (in->ptr[src] == comment_char && comment_char != '\0')
+         if (src < in->len && in->ptr[src] == '(')
            {
-             /* This is a comment, just drop the rest of the line */
-             while (src < in->len
-                    && in->ptr[src] != '\n')
-               src++;
-           }
-         else if (in->ptr[src] == '(')
-           {
-             /* Sub in till the next ')' literally */
+             /* Sub in till the next ')' literally.  */
              src++;
              while (src < in->len && in->ptr[src] != ')')
                {
@@ -726,34 +729,33 @@ macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
              if (in->ptr[src] == ')')
                src++;
              else
-               return _("missplaced )");
+               return _("misplaced `)'");
            }
-         else if (in->ptr[src] == '@')
+         else if (src < in->len && in->ptr[src] == '@')
            {
-             /* Sub in the macro invocation number */
+             /* Sub in the macro invocation number */
 
              char buffer[10];
              src++;
-             sprintf (buffer, "%05d", macro_number);
+             sprintf (buffer, "%d", macro_number);
              sb_add_string (out, buffer);
            }
-         else if (in->ptr[src] == '&')
+         else if (src < in->len && in->ptr[src] == '&')
            {
              /* This is a preprocessor variable name, we don't do them
-                here */
+                here */
              sb_add_char (out, '\\');
              sb_add_char (out, '&');
              src++;
            }
-         else if (macro_mri
-                  && isalnum ((unsigned char) in->ptr[src]))
+         else if (macro_mri && src < in->len && ISALNUM (in->ptr[src]))
            {
              int ind;
              formal_entry *f;
 
-             if (isdigit ((unsigned char) in->ptr[src]))
+             if (ISDIGIT (in->ptr[src]))
                ind = in->ptr[src] - '0';
-             else if (isupper ((unsigned char) in->ptr[src]))
+             else if (ISUPPER (in->ptr[src]))
                ind = in->ptr[src] - 'A' + 10;
              else
                ind = in->ptr[src] - 'a' + 10;
@@ -777,9 +779,7 @@ macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
            }
        }
       else if ((macro_alternate || macro_mri)
-              && (isalpha ((unsigned char) in->ptr[src])
-                  || in->ptr[src] == '_'
-                  || in->ptr[src] == '$')
+              && is_name_beginner (in->ptr[src])
               && (! inquote
                   || ! macro_strip_at
                   || (src > 0 && in->ptr[src - 1] == '@')))
@@ -799,7 +799,7 @@ macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
              formal_entry *f;
 
              src = sb_skip_white (src + 5, in);
-             while (in->ptr[src] != '\n' && in->ptr[src] != comment_char)
+             while (in->ptr[src] != '\n')
                {
                  static int loccnt;
                  char buf[20];
@@ -815,7 +815,7 @@ macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
 
                  src = get_token (src, in, &f->name);
                  ++loccnt;
-                 sprintf (buf, "LL%04x", loccnt);
+                 sprintf (buf, IS_ELF ? ".LL%04x" : "LL%04x", loccnt);
                  sb_add_string (&f->actual, buf);
 
                  err = hash_jam (formal_hash, sb_terminate (&f->name), f);
@@ -826,17 +826,6 @@ macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
                }
            }
        }
-      else if (comment_char != '\0'
-              && in->ptr[src] == comment_char
-              && src + 1 < in->len
-              && in->ptr[src + 1] == comment_char
-              && !inquote)
-       {
-         /* Two comment chars in a row cause the rest of the line to
-             be dropped.  */
-         while (src < in->len && in->ptr[src] != '\n')
-           src++;
-       }
       else if (in->ptr[src] == '"'
               || (macro_mri && in->ptr[src] == '\''))
        {
@@ -919,12 +908,7 @@ macro_expand_body (in, out, formals, formal_hash, comment_char, locals)
    body.  */
 
 static const char *
-macro_expand (idx, in, m, out, comment_char)
-     int idx;
-     sb *in;
-     macro_entry *m;
-     sb *out;
-     int comment_char;
+macro_expand (int idx, sb *in, macro_entry *m, sb *out)
 {
   sb t;
   formal_entry *ptr;
@@ -935,10 +919,10 @@ macro_expand (idx, in, m, out, comment_char)
   const char *err;
 
   sb_new (&t);
-  
-  /* Reset any old value the actuals may have */
+
+  /* Reset any old value the actuals may have */
   for (f = m->formals; f; f = f->next)
-      sb_reset (&f->actual);
+    sb_reset (&f->actual);
   f = m->formals;
   while (f != NULL && f->index < 0)
     f = f->next;
@@ -949,28 +933,36 @@ macro_expand (idx, in, m, out, comment_char)
          be referred to in the macro body as \0.  */
       if (idx < in->len && in->ptr[idx] == '.')
        {
-         formal_entry *n;
+         /* The Microtec assembler ignores this if followed by a white space.
+            (Macro invocation with empty extension) */
+         idx++;
+         if (    idx < in->len
+                 && in->ptr[idx] != ' '
+                 && in->ptr[idx] != '\t')
+           {
+             formal_entry *n;
 
-         n = (formal_entry *) xmalloc (sizeof (formal_entry));
-         sb_new (&n->name);
-         sb_new (&n->def);
-         sb_new (&n->actual);
-         n->index = QUAL_INDEX;
+             n = (formal_entry *) xmalloc (sizeof (formal_entry));
+             sb_new (&n->name);
+             sb_new (&n->def);
+             sb_new (&n->actual);
+             n->index = QUAL_INDEX;
 
-         n->next = m->formals;
-         m->formals = n;
+             n->next = m->formals;
+             m->formals = n;
 
-         idx = get_any_string (idx + 1, in, &n->actual, 1, 0);
+             idx = get_any_string (idx, in, &n->actual, 1, 0);
+           }
        }
     }
 
-  /* Peel off the actuals and store them away in the hash tables' actuals */
+  /* Peel off the actuals and store them away in the hash tables' actuals */
   idx = sb_skip_white (idx, in);
-  while (idx < in->len && in->ptr[idx] != comment_char)
+  while (idx < in->len)
     {
       int scan;
 
-      /* Look and see if it's a positional or keyword arg */
+      /* Look and see if it's a positional or keyword arg */
       scan = idx;
       while (scan < in->len
             && !ISSEP (in->ptr[scan])
@@ -984,19 +976,19 @@ macro_expand (idx, in, m, out, comment_char)
          /* It's OK to go from positional to keyword.  */
 
          /* This is a keyword arg, fetch the formal name and
-            then the actual stuff */
+            then the actual stuff */
          sb_reset (&t);
          idx = get_token (idx, in, &t);
          if (in->ptr[idx] != '=')
            return _("confusion in formal parameters");
 
-         /* Lookup the formal in the macro's list */
+         /* Lookup the formal in the macro's list */
          ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t));
          if (!ptr)
            return _("macro formal argument does not exist");
          else
            {
-             /* Insert this value into the right place */
+             /* Insert this value into the right place */
              sb_reset (&ptr->actual);
              idx = get_any_string (idx + 1, in, &ptr->actual, 0, 0);
              if (ptr->actual.len > 0)
@@ -1005,7 +997,7 @@ macro_expand (idx, in, m, out, comment_char)
        }
       else
        {
-         /* This is a positional arg */
+         /* This is a positional arg */
          is_positional = 1;
          if (is_keyword)
            return _("can't mix positional and keyword arguments");
@@ -1068,8 +1060,7 @@ macro_expand (idx, in, m, out, comment_char)
       sb_add_string (&ptr->actual, buffer);
     }
 
-  err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash,
-                          comment_char, 1);
+  err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, 1);
   if (err != NULL)
     return err;
 
@@ -1102,39 +1093,32 @@ macro_expand (idx, in, m, out, comment_char)
 }
 
 /* Check for a macro.  If one is found, put the expansion into
-   *EXPAND.  COMMENT_CHAR is the comment character--this is used by
-   gasp.  Return 1 if a macro is found, 0 otherwise.  */
+   *EXPAND.  Return 1 if a macro is found, 0 otherwise.  */
 
 int
-check_macro (line, expand, comment_char, error)
-     const char *line;
-     sb *expand;
-     int comment_char;
-     const char **error;
+check_macro (const char *line, sb *expand,
+            const char **error, macro_entry **info)
 {
   const char *s;
   char *copy, *cs;
   macro_entry *macro;
   sb line_sb;
 
-  if (! isalpha ((unsigned char) *line)
-      && *line != '_'
-      && *line != '$'
+  if (! is_name_beginner (*line)
       && (! macro_mri || *line != '.'))
     return 0;
 
   s = line + 1;
-  while (isalnum ((unsigned char) *s)
-        || *s == '_'
-        || *s == '$')
+  while (is_part_of_name (*s))
+    ++s;
+  if (is_name_ender (*s))
     ++s;
 
   copy = (char *) alloca (s - line + 1);
   memcpy (copy, line, s - line);
   copy[s - line] = '\0';
   for (cs = copy; *cs != '\0'; cs++)
-    if (isupper ((unsigned char) *cs))
-      *cs = tolower (*cs);
+    *cs = TOLOWER (*cs);
 
   macro = (macro_entry *) hash_find (macro_hash, copy);
 
@@ -1147,20 +1131,63 @@ check_macro (line, expand, comment_char, error)
     sb_add_char (&line_sb, *s++);
 
   sb_new (expand);
-  *error = macro_expand (0, &line_sb, macro, expand, comment_char);
+  *error = macro_expand (0, &line_sb, macro, expand);
 
   sb_kill (&line_sb);
 
+  /* Export the macro information if requested.  */
+  if (info)
+    *info = macro;
+
   return 1;
 }
 
+/* Free the memory allocated to a macro.  */
+
+static void
+free_macro(macro_entry *macro)
+{
+  formal_entry *formal;
+
+  for (formal = macro->formals; formal; )
+    {
+      void *ptr;
+
+      sb_kill (&formal->name);
+      sb_kill (&formal->def);
+      sb_kill (&formal->actual);
+      ptr = formal;
+      formal = formal->next;
+      free (ptr);
+    }
+  hash_die (macro->formal_hash);
+  sb_kill (&macro->sub);
+  free (macro);
+}
+
 /* Delete a macro.  */
 
 void
-delete_macro (name)
-     const char *name;
+delete_macro (const char *name)
 {
-  hash_delete (macro_hash, name);
+  char *copy;
+  size_t i, len;
+  macro_entry *macro;
+
+  len = strlen (name);
+  copy = (char *) alloca (len + 1);
+  for (i = 0; i < len; ++i)
+    copy[i] = TOLOWER (name[i]);
+  copy[i] = '\0';
+
+  /* Since hash_delete doesn't free memory, just clear out the entry.  */
+  if ((macro = hash_find (macro_hash, copy)) != NULL)
+    {
+      hash_jam (macro_hash, copy, NULL);
+      free_macro (macro);
+    }
+  else
+    as_warn (_("Attempt to purge non-existant macro `%s'"), copy);
 }
 
 /* Handle the MRI IRP and IRPC pseudo-ops.  These are handled as a
@@ -1168,31 +1195,19 @@ delete_macro (name)
    success, or an error message otherwise.  */
 
 const char *
-expand_irp (irpc, idx, in, out, get_line, comment_char)
-     int irpc;
-     int idx;
-     sb *in;
-     sb *out;
-     int (*get_line) PARAMS ((sb *));
-     int comment_char;
+expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *))
 {
-  const char *mn;
   sb sub;
   formal_entry f;
   struct hash_control *h;
   const char *err;
 
-  if (irpc)
-    mn = "IRPC";
-  else
-    mn = "IRP";
-
   idx = sb_skip_white (idx, in);
 
   sb_new (&sub);
-  if (! buffer_and_nest (mn, "ENDR", &sub, get_line))
+  if (! buffer_and_nest (NULL, "ENDR", &sub, get_line))
     return _("unexpected end of file in irp or irpc");
-  
+
   sb_new (&f.name);
   sb_new (&f.def);
   sb_new (&f.actual);
@@ -1212,10 +1227,10 @@ expand_irp (irpc, idx, in, out, get_line, comment_char)
   sb_reset (out);
 
   idx = sb_skip_comma (idx, in);
-  if (idx >= in->len || in->ptr[idx] == comment_char)
+  if (idx >= in->len)
     {
       /* Expand once with a null string.  */
-      err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
+      err = macro_expand_body (&sub, out, &f, h, 0);
       if (err != NULL)
        return err;
     }
@@ -1223,7 +1238,7 @@ expand_irp (irpc, idx, in, out, get_line, comment_char)
     {
       if (irpc && in->ptr[idx] == '"')
        ++idx;
-      while (idx < in->len && in->ptr[idx] != comment_char)
+      while (idx < in->len)
        {
          if (!irpc)
            idx = get_any_string (idx, in, &f.actual, 1, 0);
@@ -1234,7 +1249,7 @@ expand_irp (irpc, idx, in, out, get_line, comment_char)
                  int nxt;
 
                  nxt = sb_skip_white (idx + 1, in);
-                 if (nxt >= in->len || in->ptr[nxt] == comment_char)
+                 if (nxt >= in->len)
                    {
                      idx = nxt;
                      break;
@@ -1244,7 +1259,7 @@ expand_irp (irpc, idx, in, out, get_line, comment_char)
              sb_add_char (&f.actual, in->ptr[idx]);
              ++idx;
            }
-         err = macro_expand_body (&sub, out, &f, h, comment_char, 0);
+         err = macro_expand_body (&sub, out, &f, h, 0);
          if (err != NULL)
            return err;
          if (!irpc)
This page took 0.036997 seconds and 4 git commands to generate.