[binutils-gdb] gas: generalize / tighten #APP / #NO_APP recognition

Jan Beulich jbeulich@sourceware.org
Mon Aug 5 14:30:11 GMT 2024


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

commit 526363dbe4524a5364853276caba3306b813b71c
Author: Jan Beulich <jbeulich@suse.com>
Date:   Mon Aug 5 16:29:28 2024 +0200

    gas: generalize / tighten #APP / #NO_APP recognition
    
    For one '#' may not be in line_comment_chars[] in the first place. Look
    for just it when it is (these "directives" are akin to C preprocessor
    directives after all), but accept any other line comment character
    otherwise (in read.c further requiring a match on the counterpart
    "directive").
    
    Then, when in the middle of a file, the constructs should be all on
    their own on a line.  There needs to be a newline ahead of them and
    after them.
    
    Finally '\n' may not be the only end-of-line character. Accept any (but
    not end-of-statement ones) in read.c, while making sure in input-file.c
    there is one in the first place - merely any kind of whitespace isn't
    good enough.

Diff:
---
 gas/input-file.c | 16 ++++++++++------
 gas/read.c       | 35 ++++++++++++++++++++++++++++++-----
 2 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/gas/input-file.c b/gas/input-file.c
index 89f03a98be8..c96d2760a47 100644
--- a/gas/input-file.c
+++ b/gas/input-file.c
@@ -164,34 +164,38 @@ input_file_open (const char *filename,
     }
   gas_assert (c != EOF);
 
-  if (c == '#')
+  if (strchr (line_comment_chars, '#')
+      ? c == '#'
+      : c && strchr (line_comment_chars, c))
     {
       /* Begins with comment, may not want to preprocess.  */
+      int lead = c;
+
       c = getc (f_in);
       if (c == 'N')
 	{
 	  char *p = fgets (buf, sizeof (buf), f_in);
-	  if (p && startswith (p, "O_APP") && ISSPACE (p[5]))
+	  if (p && startswith (p, "O_APP") && is_end_of_line (p[5]))
 	    preprocess = 0;
 	  if (!p || !strchr (p, '\n'))
-	    ungetc ('#', f_in);
+	    ungetc (lead, f_in);
 	  else
 	    ungetc ('\n', f_in);
 	}
       else if (c == 'A')
 	{
 	  char *p = fgets (buf, sizeof (buf), f_in);
-	  if (p && startswith (p, "PP") && ISSPACE (p[2]))
+	  if (p && startswith (p, "PP") && is_end_of_line (p[2]))
 	    preprocess = 1;
 	  if (!p || !strchr (p, '\n'))
-	    ungetc ('#', f_in);
+	    ungetc (lead, f_in);
 	  else
 	    ungetc ('\n', f_in);
 	}
       else if (c == '\n')
 	ungetc ('\n', f_in);
       else
-	ungetc ('#', f_in);
+	ungetc (lead, f_in);
     }
   else
     ungetc (c, f_in);
diff --git a/gas/read.c b/gas/read.c
index c6fb3dc5a1d..78551937ccd 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -864,6 +864,29 @@ do_align (unsigned int n, char *fill, unsigned int len, unsigned int max)
     record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
 }
 
+/* Find first <eol><next_char>NO_APP<eol>, if any, in the supplied buffer.
+   Return NULL if there's none, or else the position of <next_char>.  */
+static char *
+find_no_app (const char *s, char next_char)
+{
+  const char *start = s;
+  const char srch[] = { next_char, 'N', 'O', '_', 'A', 'P', 'P', '\0' };
+
+  for (;;)
+    {
+      char *ends = strstr (s, srch);
+
+      if (ends == NULL)
+	break;
+      if (is_end_of_line (ends[sizeof (srch) - 1])
+	  && (ends == start || is_end_of_line (ends[-1])))
+	return ends;
+      s = ends + sizeof (srch) - 1;
+    }
+
+  return NULL;
+}
+
 /* We read the file, putting things into a web that represents what we
    have been reading.  */
 void
@@ -955,8 +978,10 @@ read_a_source_file (const char *name)
 #endif
 
 	  next_char = *input_line_pointer;
-	  if (was_new_line == 1 && next_char
-	      && strchr (line_comment_chars, next_char))
+	  if (was_new_line == 1
+             && (strchr (line_comment_chars, '#')
+		  ? next_char == '#'
+		  : next_char && strchr (line_comment_chars, next_char)))
 	    {
 	      /* Its a comment.  Check for APP followed by NO_APP.  */
 	      sb sbuf;
@@ -964,7 +989,7 @@ read_a_source_file (const char *name)
 	      size_t len;
 
 	      s = input_line_pointer + 1;
-	      if (!startswith (s, "APP\n"))
+	      if (!startswith (s, "APP") || !is_end_of_line (s[3]))
 		{
 		  /* We ignore it.  Note: Not ignore_rest_of_line ()!  */
 		  while (s <= buffer_limit)
@@ -976,7 +1001,7 @@ read_a_source_file (const char *name)
 	      bump_line_counters ();
 	      s += 4;
 
-	      ends = strstr (s, "#NO_APP\n");
+	      ends = find_no_app (s, next_char);
 	      len = ends ? ends - s : buffer_limit - s;
 
 	      sb_build (&sbuf, len + 100);
@@ -992,7 +1017,7 @@ read_a_source_file (const char *name)
 		      buffer_limit = input_scrub_next_buffer (&buffer);
 		      if (!buffer_limit)
 			break;
-		      ends = strstr (buffer, "#NO_APP\n");
+		      ends = find_no_app (buffer, next_char);
 		      len = ends ? ends - buffer : buffer_limit - buffer;
 		      sb_add_buffer (&sbuf, buffer, len);
 		    }


More information about the Binutils-cvs mailing list