]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: extend \+ support to .rept
authorJan Beulich <jbeulich@suse.com>
Mon, 10 Jun 2024 07:06:37 +0000 (09:06 +0200)
committerJan Beulich <jbeulich@suse.com>
Mon, 10 Jun 2024 07:06:37 +0000 (09:06 +0200)
PR gas/31752

While not quite as macro-like as .irp / .irpc, this perhaps benefits from
supporting \+ even more than those: It allows, where desired, to get away
without maintaining an explicit count variable in source code.

Keep .rep (and custom per-arch uses of s_rept() / do_repeat()) behavior
unaltered.

gas/NEWS
gas/doc/as.texi
gas/read.c
gas/testsuite/gas/macros/macros.exp
gas/testsuite/gas/macros/rept-count.l [new file with mode: 0644]
gas/testsuite/gas/macros/rept-count.s [new file with mode: 0644]

index 145ce413bff5b34143d1d2ebf27f7153d96ac5ea..c52c5934631820c83c0a71454bc7879228cceadb 100644 (file)
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -3,8 +3,8 @@
 * In x86 Intel syntax undue mnemonic suffixes are now warned about.  This is
   a first step towards rejecting their use where unjustified.
 
-* Assembler macros as well as the bodies of .irp / .irpc can now use the
-  syntax \+ to access the number of times a given macro has been executed.
+* Assembler macros as well as the bodies of .irp / .irpc / .rept can now use
+  the syntax \+ to access the number of times a given macro has been executed.
   This is similar to the already existing \@ syntax, except that the count is
   maintained on a per-macro basis.
   
index 90898d7479a09b5b6ebecf794f6405a8a1594582..33169a5ad349b222bcd3fa51d51fd0b026b3a4bb 100644 (file)
@@ -6739,6 +6739,13 @@ is equivalent to assembling
 A count of zero is allowed, but nothing is generated.  Negative counts are not
 allowed and if encountered will be treated as if they were zero.
 
+Much like for macros, @code{.irp}, and @code{.irpc} the @samp{\+} sequence can
+be used to substitute in the number of iterations done so far.  In such cases,
+i.e. when any @samp{\+} character sequence is present between @code{.rept} and
+the corresponding @code{.endr}, other backslashes also need escaping by
+backslashes.  Naturally the amount of escaping necessary may increase when
+using nested constructs.
+
 @node Sbttl
 @section @code{.sbttl "@var{subheading}"}
 
index 8026a6cdb65271e9335b31f54532f968e931bae7..40a91f482db9f808ea3218fe67cd1a5bc3ec82c3 100644 (file)
@@ -482,7 +482,7 @@ static const pseudo_typeS potable[] = {
   {"quad", cons, 8},
   {"reloc", s_reloc, 0},
   {"rep", s_rept, 0},
-  {"rept", s_rept, 0},
+  {"rept", s_rept, 1},
   {"rva", s_rva, 4},
   {"sbttl", listing_title, 1}, /* Subtitle of listing.  */
 /* scl  */
@@ -3066,19 +3066,21 @@ s_bad_end (int endr)
 /* Handle the .rept pseudo-op.  */
 
 void
-s_rept (int ignore ATTRIBUTE_UNUSED)
+s_rept (int expand_count)
 {
   size_t count;
 
   count = (size_t) get_absolute_expression ();
 
-  do_repeat (count, "REPT", "ENDR", NULL);
+  do_repeat (count, "REPT", "ENDR", expand_count ? "" : NULL);
 }
 
 /* This function provides a generic repeat block implementation.   It allows
    different directives to be used as the start/end keys.  Any text matching
    the optional EXPANDER in the block is replaced by the remaining iteration
-   count.  */
+   count.  Except when EXPANDER is the empty string, in which case \+ will
+   be looked for (as also recognized in macros as well as .irp and .irpc),
+   where the replacement will be the number of iterations done so far.  */
 
 void
 do_repeat (size_t count, const char *start, const char *end,
@@ -3101,7 +3103,58 @@ do_repeat (size_t count, const char *start, const char *end,
       return;
     }
 
-  if (expander == NULL || strstr (one.ptr, expander) == NULL)
+  if (expander != NULL && !*expander && strstr (one.ptr, "\\+") != NULL)
+    {
+      /* The 3 here and below are arbitrary, added in an attempt to limit
+        re-allocation needs in sb_add_...() for moderate repeat counts.  */
+      sb_build (&many, count * (one.len + 3));
+
+      for (size_t done = 0; count-- > 0; ++done)
+       {
+         const char *ptr, *bs;
+         sb processed;
+
+         sb_build (&processed, one.len + 3);
+
+         for (ptr = one.ptr;
+              (bs = memchr (ptr, '\\', one.ptr + one.len - ptr)) != NULL; )
+           {
+             sb_add_buffer (&processed, ptr, bs - ptr);
+             switch (bs[1])
+               {
+                 char scratch[24];
+
+               default:
+                 sb_add_char (&processed, '\\');
+                 sb_add_char (&processed, bs[1]);
+                 ptr = bs + 2;
+                 break;
+
+               case '\0':
+                 as_warn (_("`\\' at end of line/statement; ignored"));
+                 ptr = bs + 1;
+                 break;
+
+               case '\\':
+                 sb_add_char (&processed, '\\');
+                 ptr = bs + 2;
+                 break;
+
+               case '+':
+                 snprintf (scratch, ARRAY_SIZE (scratch), "%zu", done);
+                 sb_add_string (&processed, scratch);
+                 ptr = bs + 2;
+                 break;
+               }
+           }
+
+         sb_add_buffer (&processed, ptr, one.ptr + one.len - ptr);
+
+         sb_add_sb (&many, &processed);
+         sb_kill (&processed);
+       }
+    }
+  else if (expander == NULL || !*expander || strstr (one.ptr, expander) == NULL)
     {
       sb_build (&many, count * one.len);
       while (count-- > 0)
index fbe50f3a68dd7cf260352c830fd1ed49bbdc7472..69914f72e42f3e3e992b005691d9f349c8c7a3f9 100644 (file)
@@ -105,3 +105,4 @@ run_list_test altmacro
 run_list_test count
 run_list_test irp-count
 run_list_test irpc-quote
+run_list_test rept-count
diff --git a/gas/testsuite/gas/macros/rept-count.l b/gas/testsuite/gas/macros/rept-count.l
new file mode 100644 (file)
index 0000000..a1a39ba
--- /dev/null
@@ -0,0 +1,15 @@
+#...
+>0<
+>1<
+>2<
+>3<
+>4<
+>0<
+>0:0<
+>0:1<
+>1<
+>1:0<
+>1:1<
+>2<
+>2:0<
+>2:1<
diff --git a/gas/testsuite/gas/macros/rept-count.s b/gas/testsuite/gas/macros/rept-count.s
new file mode 100644 (file)
index 0000000..4f7b3c6
--- /dev/null
@@ -0,0 +1,10 @@
+       .rept 5
+       .print ">\+<"
+       .endr
+
+       .rept 3
+       .print ">\+<"
+       .rept 2
+       .print ">\+:\\+<"
+       .endr
+       .endr