2005-04-11  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.
	* doc/as.texinfo: Add information on the caveats of these changes.

gas/testsuite/
2005-04-11  Jan Beulich  <jbeulich@novell.com>

	* gas/macros/dot.[ls]: New.
	* gas/macros/macros.exp: Run new test.
This commit is contained in:
Jan Beulich 2005-04-11 12:46:38 +00:00
parent 116c20d240
commit 5e75c3ab6e
9 changed files with 230 additions and 70 deletions

View File

@ -1,3 +1,19 @@
2005-04-11 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.
* doc/as.texinfo: Add information on the caveats of these changes.
2005-04-11 Alan Modra <amodra@bigpond.net.au>
* symbols.c (symbol_X_add_number): Change return type to "offsetT *".

View File

@ -1,5 +1,11 @@
-*- text -*-
* 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 may no longer
be recognized as such (see the documentation for details).
* Support the .f_floating, .d_floating, .g_floating and .h_floating directives
for the VAX target in order to be more compatible with the VAX MACRO
assembler.

View File

@ -4594,6 +4594,9 @@ is equivalent to assembling
move d3,sp@@-
@end example
For some caveats with the spelling of @var{symbol}, see also the discussion
at @xref{Macro}.
@node Irpc
@section @code{.irpc @var{symbol},@var{values}}@dots{}
@ -4622,6 +4625,9 @@ is equivalent to assembling
move d3,sp@@-
@end example
For some caveats with the spelling of @var{symbol}, see also the discussion
at @xref{Macro}.
@node Lcomm
@section @code{.lcomm @var{symbol} , @var{length}}
@ -4869,6 +4875,32 @@ When you call a macro, you can specify the argument values either by
position, or by keyword. For example, @samp{sum 9,17} is equivalent to
@samp{sum to=17, from=9}.
Note that since each of the @var{macargs} can be an identifier exactly
as any other one permitted by the target architecture, there may be
occasional problems if the target hand-crafts special meanings to certain
characters when they occur in a special position. For example, if colon
(@code{:}) is generally permitted to be part of a symbol name, but the
architecture specific code special-cases it when occuring as the final
character of a symbol (to denote a label), then the macro parameter
replacement code will have no way of knowing that and consider the whole
construct (including the colon) an identifier, and check only this
identifier for being the subject to parameter substitution. In this
example, besides the potential of just separating identifier and colon
by white space, using alternate macro syntax (@xref{Altmacro}.) and
ampersand (@code{&}) as the character to separate literal text from macro
parameters (or macro parameters from one another) would provide a way to
achieve the same effect:
@example
.altmacro
.macro label l
l&:
.endm
@end example
This applies identically to the identifiers used in @code{.irp} (@xref{Irp}.)
and @code{.irpc} (@xref{Irpc}.).
@item .endm
@cindex @code{endm} directive
Mark the end of a macro definition.

View File

@ -187,21 +187,37 @@ buffer_and_nest (const char *from, const char *to, sb *ptr,
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++;
if (! LABELS_WITHOUT_COLONS)
{
/* 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++;
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 char *to, sb *ptr,
? 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, formal_entry *formals,
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, formal_entry *formals,
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, formal_entry *formals,
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, formal_entry *formals,
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, formal_entry *formals,
}
}
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 *expand,
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);

View File

@ -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);
}

View File

@ -1,3 +1,8 @@
2005-04-11 Jan Beulich <jbeulich@novell.com>
* gas/macros/dot.[ls]: New.
* gas/macros/macros.exp: Run new test.
2005-04-06 H.J. Lu <hongjiu.lu@intel.com>
* gas/i386/x86-64-pcrel.s: Test R_X86_64_32S.

View File

@ -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

View File

@ -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

View File

@ -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 ""