[PATCH] Re: .macro behavior

Jan Beulich JBeulich@novell.com
Tue Mar 29 16:26:00 GMT 2005


This is a resubmission of the patch at
http://sourceware.org/ml/binutils/2005-02/msg00120.html to address the
inconsistent acceptance of identifiers between the macro handling code and
the rest of the assembler, including the unability to use a macro the name
of which starts with a dot.
Over the previously submitted revisions, this has a small bug fixed and the
new test case slightly changed.

Originally built and tested natively on ia64-unknown-linux-gnu and as cross
tools for a large number of targets. Re-built and re-tested on
x86_64-unknown-linux-gnu.

Jan

gas/
2005-03-29  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.

gas/testsuite/
2005-03-29  Jan Beulich  <jbeulich@novell.com>

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

--- /home/jbeulich/src/binutils/mainline/2005-03-29/gas/NEWS	2005-03-29 15:26:51.000000000 +0200
+++ 2005-03-29/gas/NEWS	2005-03-29 16:00:15.131442440 +0200
@@ -1,11 +1,17 @@
 -*- text -*-
 
+* Redefinition of macros now results in an error.
+
+* 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 are no longer
+  recognized as such.
+
 * New command line option -mtune=[itanium1|itanium2] for IA64 targets.
 
 Changes in 2.16:
 
-* Redefinition of macros now results in an error.
-
 * New command line option -mhint.b=[ok|warning|error] for IA64 targets.
 
 * New command line option -munwind-check=[warning|error] for IA64
--- /home/jbeulich/src/binutils/mainline/2005-03-29/gas/macro.c	2005-03-04 15:51:40.000000000 +0100
+++ 2005-03-29/gas/macro.c	2005-03-29 15:57:46.380056088 +0200
@@ -187,21 +187,37 @@ buffer_and_nest (const char *from, const
 	     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++;
-
-	  /* And a colon.  */
-	  if (i < ptr->len
-	      && ptr->ptr[i] == ':')
-	    i++;
+	  if (! LABELS_WITHOUT_COLONS)
+	    {
+	      /* Skip leading whitespace.  */
+	      while (i < ptr->len && ISWHITE (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
 	       ? 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, form
 	  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, form
 	      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, form
 	      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, form
 	      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, form
 	    }
 	}
       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 *expan
   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);
--- /home/jbeulich/src/binutils/mainline/2005-03-29/gas/read.c	2005-03-02 08:46:24.000000000 +0100
+++ 2005-03-29/gas/read.c	2005-03-29 16:22:02.120749864 +0200
@@ -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';
+		  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);
+		      /* 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);
 	}
--- /home/jbeulich/src/binutils/mainline/2005-03-29/gas/testsuite/gas/macros/dot.l	1970-01-01 01:00:00.000000000 +0100
+++ 2005-03-29/gas/testsuite/gas/macros/dot.l	2005-03-29 16:26:54.000000000 +0200
@@ -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
--- /home/jbeulich/src/binutils/mainline/2005-03-29/gas/testsuite/gas/macros/dot.s	1970-01-01 01:00:00.000000000 +0100
+++ 2005-03-29/gas/testsuite/gas/macros/dot.s	2005-02-08 09:57:12.000000000 +0100
@@ -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
--- /home/jbeulich/src/binutils/mainline/2005-03-29/gas/testsuite/gas/macros/macros.exp	2005-03-04 15:51:53.000000000 +0100
+++ 2005-03-29/gas/testsuite/gas/macros/macros.exp	2005-03-29 15:57:46.389054720 +0200
@@ -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 ""

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: binutils-mainline-macro-identifiers.patch
URL: <https://sourceware.org/pipermail/binutils/attachments/20050329/1455f2a2/attachment.ksh>


More information about the Binutils mailing list