[binutils-gdb] gas: fix hex float parsing from .dcb.? directives

Jan Beulich jbeulich@sourceware.org
Wed Jun 16 06:56:07 GMT 2021


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=bb32eac5a90b2b141fed4ce490aded74134f1d75

commit bb32eac5a90b2b141fed4ce490aded74134f1d75
Author: Jan Beulich <jbeulich@suse.com>
Date:   Wed Jun 16 08:55:52 2021 +0200

    gas: fix hex float parsing from .dcb.? directives
    
    Unlike for .dc.? the parsing here failed to skip the colon before
    calling hex_float(). To avoid both variants of parsing going out of sync
    again, introduce a helper used by both.

Diff:
---
 gas/ChangeLog                 |   6 ++
 gas/read.c                    | 124 ++++++++++++++++++------------------------
 gas/testsuite/gas/all/float.s |  16 ++++++
 3 files changed, 75 insertions(+), 71 deletions(-)

diff --git a/gas/ChangeLog b/gas/ChangeLog
index ebbf27f0b66..8fa1be88e81 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,9 @@
+2021-06-16  Jan Beulich  <jbeulich@suse.com>
+
+	* read.c (parse_one_float): New.
+	(s_float_space, float_cons): Use it.
+	* testsuite/gas/all/float.s: Add .dc.*, .dcb.*, and .ds.* cases.
+
 2021-06-16  Jan Beulich  <jbeulich@suse.com>
 
 	* read.c (emit_expr_with_reloc): Adjust overflow check. Drop
diff --git a/gas/read.c b/gas/read.c
index db1011b6392..935b1fa7bde 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -3616,6 +3616,51 @@ s_nops (int ignore ATTRIBUTE_UNUSED)
   *p = val.X_add_number;
 }
 
+static int
+parse_one_float (int float_type, char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT])
+{
+  int length;
+
+  SKIP_WHITESPACE ();
+
+  /* Skip any 0{letter} that may be present.  Don't even check if the
+     letter is legal.  Someone may invent a "z" format and this routine
+     has no use for such information. Lusers beware: you get
+     diagnostics if your input is ill-conditioned.  */
+  if (input_line_pointer[0] == '0'
+      && ISALPHA (input_line_pointer[1]))
+    input_line_pointer += 2;
+
+  /* Accept :xxxx, where the x's are hex digits, for a floating point
+     with the exact digits specified.  */
+  if (input_line_pointer[0] == ':')
+    {
+      ++input_line_pointer;
+      length = hex_float (float_type, temp);
+      if (length < 0)
+	{
+	  ignore_rest_of_line ();
+	  return length;
+	}
+    }
+  else
+    {
+      const char *err;
+
+      err = md_atof (float_type, temp, &length);
+      know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
+      know (err != NULL || length > 0);
+      if (err)
+	{
+	  as_bad (_("bad floating literal: %s"), err);
+	  ignore_rest_of_line ();
+	  return -1;
+	}
+    }
+
+  return length;
+}
+
 /* This is like s_space, but the value is a floating point number with
    the given precision.  This is for the MRI dcb.s pseudo-op and
    friends.  */
@@ -3650,42 +3695,12 @@ s_float_space (int float_type)
 
   ++input_line_pointer;
 
-  SKIP_WHITESPACE ();
-
-  /* Skip any 0{letter} that may be present.  Don't even check if the
-   * letter is legal.  */
-  if (input_line_pointer[0] == '0'
-      && ISALPHA (input_line_pointer[1]))
-    input_line_pointer += 2;
-
-  /* Accept :xxxx, where the x's are hex digits, for a floating point
-     with the exact digits specified.  */
-  if (input_line_pointer[0] == ':')
-    {
-      flen = hex_float (float_type, temp);
-      if (flen < 0)
-	{
-	  ignore_rest_of_line ();
-	  if (flag_mri)
-	    mri_comment_end (stop, stopc);
-	  return;
-	}
-    }
-  else
+  flen = parse_one_float (float_type, temp);
+  if (flen < 0)
     {
-      const char *err;
-
-      err = md_atof (float_type, temp, &flen);
-      know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
-      know (err != NULL || flen > 0);
-      if (err)
-	{
-	  as_bad (_("bad floating literal: %s"), err);
-	  ignore_rest_of_line ();
-	  if (flag_mri)
-	    mri_comment_end (stop, stopc);
-	  return;
-	}
+      if (flag_mri)
+	mri_comment_end (stop, stopc);
+      return;
     }
 
   while (--count >= 0)
@@ -4909,7 +4924,6 @@ float_cons (/* Clobbers input_line-pointer, checks end-of-line.  */
 {
   char *p;
   int length;			/* Number of chars in an object.  */
-  const char *err;		/* Error from scanning floating literal.  */
   char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
 
   if (is_it_end_of_statement ())
@@ -4943,41 +4957,9 @@ float_cons (/* Clobbers input_line-pointer, checks end-of-line.  */
 
   do
     {
-      /* input_line_pointer->1st char of a flonum (we hope!).  */
-      SKIP_WHITESPACE ();
-
-      /* Skip any 0{letter} that may be present. Don't even check if the
-	 letter is legal. Someone may invent a "z" format and this routine
-	 has no use for such information. Lusers beware: you get
-	 diagnostics if your input is ill-conditioned.  */
-      if (input_line_pointer[0] == '0'
-	  && ISALPHA (input_line_pointer[1]))
-	input_line_pointer += 2;
-
-      /* Accept :xxxx, where the x's are hex digits, for a floating
-	 point with the exact digits specified.  */
-      if (input_line_pointer[0] == ':')
-	{
-	  ++input_line_pointer;
-	  length = hex_float (float_type, temp);
-	  if (length < 0)
-	    {
-	      ignore_rest_of_line ();
-	      return;
-	    }
-	}
-      else
-	{
-	  err = md_atof (float_type, temp, &length);
-	  know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
-	  know (err != NULL || length > 0);
-	  if (err)
-	    {
-	      as_bad (_("bad floating literal: %s"), err);
-	      ignore_rest_of_line ();
-	      return;
-	    }
-	}
+      length = parse_one_float (float_type, temp);
+      if (length < 0)
+	return;
 
       if (!need_pass_2)
 	{
diff --git a/gas/testsuite/gas/all/float.s b/gas/testsuite/gas/all/float.s
index 902914f4dc8..579ca89af37 100644
--- a/gas/testsuite/gas/all/float.s
+++ b/gas/testsuite/gas/all/float.s
@@ -4,3 +4,19 @@ foo:	.single	0r1.2345e+06
 	.double 0r2.718282
         .double .0000000000000000000001
         .double 1e-22
+
+	.dc.s 1
+	.dc.s 0f:1234
+	.dcb.s 1, 1
+	.dcb.s 1, 0s:4321
+	.ds.s 1, -1
+
+	.dc.d 1
+	.dc.d 0d:1234
+	.dcb.d 1, 1
+	.dcb.d 1, 0r:4321
+	.ds.d 1, -1
+
+	.dc.x 0x:1234
+	.dcb.x 1, 0x:4321
+	.ds.x 1, -1


More information about the Binutils-cvs mailing list