* [PATCH] gas: extend \+ support to .rept
@ 2024-05-27 11:51 Jan Beulich
2024-05-29 5:21 ` Fangrui Song
[not found] ` <CAN30aBGnGkS_vwC_23peBx9QJLSbejHU4PtYjY5NKOeESgLX5w@mail.gmail.com>
0 siblings, 2 replies; 3+ messages in thread
From: Jan Beulich @ 2024-05-27 11:51 UTC (permalink / raw)
To: Binutils
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.
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,7 +1,7 @@
-*- text -*-
-* 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.
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -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}"}
--- a/gas/read.c
+++ b/gas/read.c
@@ -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 *sta
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)
--- a/gas/testsuite/gas/macros/macros.exp
+++ b/gas/testsuite/gas/macros/macros.exp
@@ -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
--- /dev/null
+++ b/gas/testsuite/gas/macros/rept-count.l
@@ -0,0 +1,15 @@
+#...
+>0<
+>1<
+>2<
+>3<
+>4<
+>0<
+>0:0<
+>0:1<
+>1<
+>1:0<
+>1:1<
+>2<
+>2:0<
+>2:1<
--- /dev/null
+++ b/gas/testsuite/gas/macros/rept-count.s
@@ -0,0 +1,10 @@
+ .rept 5
+ .print ">\+<"
+ .endr
+
+ .rept 3
+ .print ">\+<"
+ .rept 2
+ .print ">\+:\\+<"
+ .endr
+ .endr
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] gas: extend \+ support to .rept
2024-05-27 11:51 [PATCH] gas: extend \+ support to .rept Jan Beulich
@ 2024-05-29 5:21 ` Fangrui Song
[not found] ` <CAN30aBGnGkS_vwC_23peBx9QJLSbejHU4PtYjY5NKOeESgLX5w@mail.gmail.com>
1 sibling, 0 replies; 3+ messages in thread
From: Fangrui Song @ 2024-05-29 5:21 UTC (permalink / raw)
To: Jan Beulich; +Cc: Binutils
On Mon, May 27, 2024 at 4:51 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> 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.
>
> --- a/gas/NEWS
> +++ b/gas/NEWS
> @@ -1,7 +1,7 @@
> -*- text -*-
>
> -* 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.
>
> --- a/gas/doc/as.texi
> +++ b/gas/doc/as.texi
> @@ -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}"}
>
> --- a/gas/read.c
> +++ b/gas/read.c
> @@ -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 *sta
> 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)
> --- a/gas/testsuite/gas/macros/macros.exp
> +++ b/gas/testsuite/gas/macros/macros.exp
> @@ -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
> --- /dev/null
> +++ b/gas/testsuite/gas/macros/rept-count.l
> @@ -0,0 +1,15 @@
> +#...
> +>0<
> +>1<
> +>2<
> +>3<
> +>4<
> +>0<
> +>0:0<
> +>0:1<
> +>1<
> +>1:0<
> +>1:1<
> +>2<
> +>2:0<
> +>2:1<
> --- /dev/null
> +++ b/gas/testsuite/gas/macros/rept-count.s
> @@ -0,0 +1,10 @@
> + .rept 5
> + .print ">\+<"
> + .endr
LGTM.
Perhaps this .print directive can be changed to print \+ \+
to show that the \+ expanded value is identical within one iteration.
> +
> + .rept 3
> + .print ">\+<"
> + .rept 2
> + .print ">\+:\\+<"
> + .endr
> + .endr
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] gas: extend \+ support to .rept
[not found] ` <CAN30aBGnGkS_vwC_23peBx9QJLSbejHU4PtYjY5NKOeESgLX5w@mail.gmail.com>
@ 2024-05-29 5:40 ` Fangrui Song
0 siblings, 0 replies; 3+ messages in thread
From: Fangrui Song @ 2024-05-29 5:40 UTC (permalink / raw)
To: Jan Beulich; +Cc: Binutils
On Tue, May 28, 2024 at 10:21 PM Fangrui Song <i@maskray.me> wrote:
>
> On Mon, May 27, 2024 at 4:51 AM Jan Beulich <jbeulich@suse.com> wrote:
> >
> > 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.
> >
> > --- a/gas/NEWS
> > +++ b/gas/NEWS
> > @@ -1,7 +1,7 @@
> > -*- text -*-
> >
> > -* 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.
> >
> > --- a/gas/doc/as.texi
> > +++ b/gas/doc/as.texi
> > @@ -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}"}
> >
> > --- a/gas/read.c
> > +++ b/gas/read.c
> > @@ -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 *sta
> > 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)
Nit: done = 0; done < count; ++done) might be more idiomatic (avoid
changing `count`).
> > + {
> > + 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)
> > --- a/gas/testsuite/gas/macros/macros.exp
> > +++ b/gas/testsuite/gas/macros/macros.exp
> > @@ -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
> > --- /dev/null
> > +++ b/gas/testsuite/gas/macros/rept-count.l
> > @@ -0,0 +1,15 @@
> > +#...
> > +>0<
> > +>1<
> > +>2<
> > +>3<
> > +>4<
> > +>0<
> > +>0:0<
> > +>0:1<
> > +>1<
> > +>1:0<
> > +>1:1<
> > +>2<
> > +>2:0<
> > +>2:1<
> > --- /dev/null
> > +++ b/gas/testsuite/gas/macros/rept-count.s
> > @@ -0,0 +1,10 @@
> > + .rept 5
> > + .print ">\+<"
> > + .endr
>
> LGTM.
>
> Perhaps this .print directive can be changed to print \+ \+
> to show that the \+ expanded value is identical within one iteration.
>
> > +
> > + .rept 3
> > + .print ">\+<"
> > + .rept 2
> > + .print ">\+:\\+<"
> > + .endr
> > + .endr
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2024-05-29 5:47 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-27 11:51 [PATCH] gas: extend \+ support to .rept Jan Beulich
2024-05-29 5:21 ` Fangrui Song
[not found] ` <CAN30aBGnGkS_vwC_23peBx9QJLSbejHU4PtYjY5NKOeESgLX5w@mail.gmail.com>
2024-05-29 5:40 ` Fangrui Song
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).