gas/
authorJan Beulich <jbeulich@novell.com>
Mon, 11 Apr 2005 12:46:38 +0000 (12:46 +0000)
committerJan Beulich <jbeulich@novell.com>
Mon, 11 Apr 2005 12:46:38 +0000 (12:46 +0000)
2005-04-11  Jan Beulich  <jbeulich@novell.com>

* NEWS: Mention these changes and their effects.
* macro.c (get_token): Use is_name_beginner/is_part_of_name/
is_name_ender.
(check_macro): Likewise.
(buffer_and_nest): Likewise. Permit multiple labels. Don't discard
labels together with the closing pseudo-op.
(macro_expand_body): Adjust comment. Range-check input before use.
Adjust mis-spelled diagnostic. Use is_name_beginner.
* read.c (try_macro): New.
(read_a_source_file): New static variable last_eol. Don't list
macro expansion lines more than once. Call try_macro.
(s_macro): Set section of line_label to absolute instead of undefined.
* doc/as.texinfo: Add information on the caveats of these changes.

gas/testsuite/
2005-04-11  Jan Beulich  <jbeulich@novell.com>

* gas/macros/dot.[ls]: New.
* gas/macros/macros.exp: Run new test.

gas/ChangeLog
gas/NEWS
gas/doc/as.texinfo
gas/macro.c
gas/read.c
gas/testsuite/ChangeLog
gas/testsuite/gas/macros/dot.l [new file with mode: 0644]
gas/testsuite/gas/macros/dot.s [new file with mode: 0644]
gas/testsuite/gas/macros/macros.exp

index f6c8d4e4590169e859b49a159d6bbca2c5af2060..2f5c5a1d147aefc0df4bd6c5081ce58330260793 100644 (file)
@@ -1,3 +1,19 @@
+2005-04-11  Jan Beulich  <jbeulich@novell.com>
+
+       * NEWS: Mention these changes and their effects.
+       * macro.c (get_token): Use is_name_beginner/is_part_of_name/
+       is_name_ender.
+       (check_macro): Likewise.
+       (buffer_and_nest): Likewise. Permit multiple labels. Don't discard
+       labels together with the closing pseudo-op.
+       (macro_expand_body): Adjust comment. Range-check input before use.
+       Adjust mis-spelled diagnostic. Use is_name_beginner.
+       * read.c (try_macro): New.
+       (read_a_source_file): New static variable last_eol. Don't list
+       macro expansion lines more than once. Call try_macro.
+       (s_macro): Set section of line_label to absolute instead of undefined.
+       * doc/as.texinfo: Add information on the caveats of these changes.
+
 2005-04-11  Alan Modra  <amodra@bigpond.net.au>
 
        * symbols.c (symbol_X_add_number): Change return type to "offsetT *".
index 0e9b332501a3294be55c832c2cfe01744d928161..816a2c417bab2ee0314b9765fa4d5b4d41f38c24 100644 (file)
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,11 @@
 -*- text -*-
 
+* Macro names and macro parameter names can now be any identifier that would
+  also be legal as a symbol elsewhere. For macro parameter names, this is
+  known to cause problems in certain sources when the respective target uses
+  characters inconsistently, and thus macro parameter references may no longer
+  be recognized as such (see the documentation for details).
+
 * Support the .f_floating, .d_floating, .g_floating and .h_floating directives
   for the VAX target in order to be more compatible with the VAX MACRO
   assembler.
index a3164511e73ea75a837112c0b2e9845c940e1dba..02e4ab44b71a79d95e0d0523048f978bba2e1e38 100644 (file)
@@ -4594,6 +4594,9 @@ is equivalent to assembling
         move    d3,sp@@-
 @end example
 
+For some caveats with the spelling of @var{symbol}, see also the discussion
+at @xref{Macro}.
+
 @node Irpc
 @section @code{.irpc @var{symbol},@var{values}}@dots{}
 
@@ -4622,6 +4625,9 @@ is equivalent to assembling
         move    d3,sp@@-
 @end example
 
+For some caveats with the spelling of @var{symbol}, see also the discussion
+at @xref{Macro}.
+
 @node Lcomm
 @section @code{.lcomm @var{symbol} , @var{length}}
 
@@ -4869,6 +4875,32 @@ When you call a macro, you can specify the argument values either by
 position, or by keyword.  For example, @samp{sum 9,17} is equivalent to
 @samp{sum to=17, from=9}.
 
+Note that since each of the @var{macargs} can be an identifier exactly
+as any other one permitted by the target architecture, there may be
+occasional problems if the target hand-crafts special meanings to certain
+characters when they occur in a special position.  For example, if colon
+(@code{:}) is generally permitted to be part of a symbol name, but the
+architecture specific code special-cases it when occuring as the final
+character of a symbol (to denote a label), then the macro parameter
+replacement code will have no way of knowing that and consider the whole
+construct (including the colon) an identifier, and check only this
+identifier for being the subject to parameter substitution.  In this
+example, besides the potential of just separating identifier and colon
+by white space, using alternate macro syntax (@xref{Altmacro}.) and
+ampersand (@code{&}) as the character to separate literal text from macro
+parameters (or macro parameters from one another) would provide a way to
+achieve the same effect:
+
+@example
+       .altmacro
+       .macro label l
+l&:
+       .endm
+@end example
+
+This applies identically to the identifiers used in @code{.irp} (@xref{Irp}.)
+and @code{.irpc} (@xref{Irpc}.).
+
 @item .endm
 @cindex @code{endm} directive
 Mark the end of a macro definition.
index 131838efc1eeb0723eb7ea329afa4368767ec08f..4f934ae52de73d540fdb48f42b033b12df55a163 100644 (file)
@@ -187,21 +187,37 @@ buffer_and_nest (const char *from, const char *to, sb *ptr,
             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 (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.  */
@@ -226,11 +242,13 @@ buffer_and_nest (const char *from, const char *to, sb *ptr,
               ? strncasecmp (ptr->ptr + i, from, from_len) == 0
               : from_len > 0)
              && (ptr->len == (i + from_len)
-                 || ! ISALNUM (ptr->ptr[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
              && (ptr->len == (i + to_len)
-                 || ! ISALNUM (ptr->ptr[i + to_len])))
+                 || ! (is_part_of_name (ptr->ptr[i + to_len])
+                       || is_name_ender (ptr->ptr[i + to_len]))))
            {
              depth--;
              if (depth == 0)
@@ -258,15 +276,16 @@ static int
 get_token (int idx, sb *in, sb *name)
 {
   if (idx < in->len
-      && (ISALPHA (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 (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++]);
        }
@@ -692,13 +711,14 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
          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] == '(')
+         if (src < in->len && in->ptr[src] == '(')
            {
              /* Sub in till the next ')' literally.  */
              src++;
@@ -709,9 +729,9 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
              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.  */
 
@@ -720,7 +740,7 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
              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.  */
@@ -728,7 +748,7 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
              sb_add_char (out, '&');
              src++;
            }
-         else if (macro_mri && ISALNUM (in->ptr[src]))
+         else if (macro_mri && src < in->len && ISALNUM (in->ptr[src]))
            {
              int ind;
              formal_entry *f;
@@ -759,9 +779,7 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals,
            }
        }
       else if ((macro_alternate || macro_mri)
-              && (ISALPHA (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] == '@')))
@@ -1086,16 +1104,14 @@ check_macro (const char *line, sb *expand,
   macro_entry *macro;
   sb line_sb;
 
-  if (! ISALPHA (*line)
-      && *line != '_'
-      && *line != '$'
+  if (! is_name_beginner (*line)
       && (! macro_mri || *line != '.'))
     return 0;
 
   s = line + 1;
-  while (ISALNUM (*s)
-        || *s == '_'
-        || *s == '$')
+  while (is_part_of_name (*s))
+    ++s;
+  if (is_name_ender (*s))
     ++s;
 
   copy = (char *) alloca (s - line + 1);
index a606d0318525bebb779a9cf1c8f6fa044812ce52..7938a57fef85c38bf5ff0c4a1c2184889e94a59d 100644 (file)
@@ -520,6 +520,32 @@ scrub_from_string (char *buf, int buflen)
   return copy;
 }
 
+/* Helper function of read_a_source_file, which tries to expand a macro.  */
+static int
+try_macro (char term, const char *line)
+{
+  sb out;
+  const char *err;
+  macro_entry *macro;
+
+  if (check_macro (line, &out, &err, &macro))
+    {
+      if (err != NULL)
+       as_bad ("%s", err);
+      *input_line_pointer++ = term;
+      input_scrub_include_sb (&out,
+                             input_line_pointer, 1);
+      sb_kill (&out);
+      buffer_limit =
+       input_scrub_next_buffer (&input_line_pointer);
+#ifdef md_macro_info
+      md_macro_info (macro);
+#endif
+      return 1;
+    }
+  return 0;
+}
+
 /* We read the file, putting things into a web that represents what we
    have been reading.  */
 void
@@ -547,6 +573,13 @@ read_a_source_file (char *name)
 
   while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0)
     {                          /* We have another line to parse.  */
+#ifndef NO_LISTING
+      /* In order to avoid listing macro expansion lines with labels
+        multiple times, keep track of which line was last issued.  */
+      static char *last_eol;
+
+      last_eol = NULL;
+#endif
       know (buffer_limit[-1] == '\n'); /* Must have a sentinel.  */
 
       while (input_line_pointer < buffer_limit)
@@ -666,17 +699,21 @@ read_a_source_file (char *name)
                    if (is_end_of_line[(unsigned char) *s])
                      break;
 
-                 /* Copy it for safe keeping.  Also give an indication of
-                    how much macro nesting is involved at this point.  */
-                 len = s - (input_line_pointer - 1);
-                 copy = (char *) xmalloc (len + macro_nest + 2);
-                 memset (copy, '>', macro_nest);
-                 copy[macro_nest] = ' ';
-                 memcpy (copy + macro_nest + 1, input_line_pointer - 1, len);
-                 copy[macro_nest + 1 + len] = '\0';
-
-                 /* Install the line with the listing facility.  */
-                 listing_newline (copy);
+                 if (s != last_eol)
+                   {
+                     last_eol = s;
+                     /* Copy it for safe keeping.  Also give an indication of
+                        how much macro nesting is involved at this point.  */
+                     len = s - (input_line_pointer - 1);
+                     copy = (char *) xmalloc (len + macro_nest + 2);
+                     memset (copy, '>', macro_nest);
+                     copy[macro_nest] = ' ';
+                     memcpy (copy + macro_nest + 1, input_line_pointer - 1, len);
+                     copy[macro_nest + 1 + len] = '\0';
+
+                     /* Install the line with the listing facility.  */
+                     listing_newline (copy);
+                   }
                }
              else
                listing_newline (NULL);
@@ -816,9 +853,18 @@ read_a_source_file (char *name)
                      /* Print the error msg now, while we still can.  */
                      if (pop == NULL)
                        {
-                         as_bad (_("unknown pseudo-op: `%s'"), s);
+                         char *end = input_line_pointer;
+
                          *input_line_pointer = c;
                          s_ignore (0);
+                         c = *--input_line_pointer;
+                         *input_line_pointer = '\0';
+                         if (! macro_defined || ! try_macro (c, s))
+                           {
+                             *end = '\0';
+                             as_bad (_("unknown pseudo-op: `%s'"), s);
+                             *input_line_pointer++ = c;
+                           }
                          continue;
                        }
 
@@ -874,28 +920,8 @@ read_a_source_file (char *name)
 
                      generate_lineno_debug ();
 
-                     if (macro_defined)
-                       {
-                         sb out;
-                         const char *err;
-                         macro_entry *macro;
-
-                         if (check_macro (s, &out, &err, &macro))
-                           {
-                             if (err != NULL)
-                               as_bad ("%s", err);
-                             *input_line_pointer++ = c;
-                             input_scrub_include_sb (&out,
-                                                     input_line_pointer, 1);
-                             sb_kill (&out);
-                             buffer_limit =
-                               input_scrub_next_buffer (&input_line_pointer);
-#ifdef md_macro_info
-                             md_macro_info (macro);
-#endif
-                             continue;
-                           }
-                       }
+                     if (macro_defined && try_macro (c, s))
+                       continue;
 
                      if (mri_pending_align)
                        {
@@ -2319,7 +2345,7 @@ s_macro (int ignore ATTRIBUTE_UNUSED)
     {
       if (line_label != NULL)
        {
-         S_SET_SEGMENT (line_label, undefined_section);
+         S_SET_SEGMENT (line_label, absolute_section);
          S_SET_VALUE (line_label, 0);
          symbol_set_frag (line_label, &zero_address_frag);
        }
index 9628cbc0dfd6e2e571f515c9344c46a4dc5e541d..5afbf51a54700fe73feb3e9248c14856b1c64cf1 100644 (file)
@@ -1,3 +1,8 @@
+2005-04-11  Jan Beulich  <jbeulich@novell.com>
+
+       * gas/macros/dot.[ls]: New.
+       * gas/macros/macros.exp: Run new test.
+
 2005-04-06  H.J. Lu  <hongjiu.lu@intel.com>
 
        * gas/i386/x86-64-pcrel.s: Test R_X86_64_32S.
diff --git a/gas/testsuite/gas/macros/dot.l b/gas/testsuite/gas/macros/dot.l
new file mode 100644 (file)
index 0000000..e74e4f3
--- /dev/null
@@ -0,0 +1,22 @@
+.*: Assembler messages:
+.*:[1-9][0-9]*: Warning: attempt to redefine pseudo-op .\.macro. ignored
+.*:27: Error: unknown pseudo-op: .\.xyz.
+.*:28: Error: .*
+(.* )?GAS .*
+#...
+[      ]*[1-9][0-9]*[  ]+m 4, 2
+[      ]*[1-9][0-9]*[  ]+> \.data
+[      ]*[1-9][0-9]*[  ]+> labelA:labelB:labelC:labelD:x\.y\.z 4\+2
+[      ]*[1-9][0-9]*[  ]+>> \.align 4
+[      ]*[1-9][0-9]*[  ]+\?+[  ]+0606[         ]+>> \.byte 4\+2,4\+2
+[      ]*[1-9][0-9]*[  ]+\?+[  ]+0000[         ]+> \.skip 2
+[      ]*[1-9][0-9]*[  ]+> labelZ:labelY:labelX:labelW:\.xyz 4-2
+[      ]*[1-9][0-9]*[  ]+>> \.align 8
+[      ]*[1-9][0-9]*[  ]+\?+[  ]+0202[         ]+>> \.byte 4-2,4-2
+[      ]*[1-9][0-9]*[  ]+\?+[  ]+0000 ?0000[   ]+> \.skip 4\*2
+[      ]*[1-9][0-9]*[  ]+0000 ?0000[   ]*
+[      ]*[1-9][0-9]*[  ]+> label9:label8:label7:label6:
+[      ]*[1-9][0-9]*[  ]+
+[      ]*[1-9][0-9]*[  ]+\.purgem \.xyz, x\.y\.z
+[      ]*[1-9][0-9]*[  ]+\.xyz 0
+[      ]*[1-9][0-9]*[  ]+x\.y\.z 0
diff --git a/gas/testsuite/gas/macros/dot.s b/gas/testsuite/gas/macros/dot.s
new file mode 100644 (file)
index 0000000..10ed42f
--- /dev/null
@@ -0,0 +1,28 @@
+.altmacro
+
+.macro x.y.z val
+ .align 4
+ .byte val, val
+.endm
+
+.macro .xyz val
+ .align 8
+ .byte val, val
+.endm
+
+.macro .macro
+.endm
+
+label1:label2 : label3 :label4: m: .macro arg.1, arg.2
+ .data
+labelA:labelB : labelC :labelD: x.y.z arg.1+arg.2
+ .skip arg.2
+labelZ:labelY : labelX :labelW: .xyz arg.1-arg.2
+ .skip arg.1*arg.2
+label9:label8 : label7 :label6: .endm
+
+m 4, 2
+
+.purgem .xyz, x.y.z
+.xyz 0
+x.y.z 0
index 37435ccc3e6b25ba31b06fcf2d7fdb7e71f8fae7..5b924ac8402c7a3a0f0708b7dab5468795b0fd06 100644 (file)
@@ -68,5 +68,14 @@ run_dump_test app3
 run_dump_test app4
 
 run_list_test badarg ""
+case $target_triplet in {
+    { *c54x*-*-* } { }
+    { *c4x*-*-* } { }
+    { h8500-*-* } { }
+    { m68*-*-* } { }
+    { m88*-*-* } { }
+    { mmix-* } { }
+    default { run_list_test dot "-alm" }
+}
 run_list_test end ""
 run_list_test redef ""