diff options
-rw-r--r-- | gas/ChangeLog | 16 | ||||
-rw-r--r-- | gas/NEWS | 6 | ||||
-rw-r--r-- | gas/doc/as.texinfo | 32 | ||||
-rw-r--r-- | gas/macro.c | 88 | ||||
-rw-r--r-- | gas/read.c | 96 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gas/testsuite/gas/macros/dot.l | 22 | ||||
-rw-r--r-- | gas/testsuite/gas/macros/dot.s | 28 | ||||
-rw-r--r-- | gas/testsuite/gas/macros/macros.exp | 9 |
9 files changed, 231 insertions, 71 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index f6c8d4e..2f5c5a1 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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 *". @@ -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. diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo index a316451..02e4ab4 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -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. diff --git a/gas/macro.c b/gas/macro.c index 131838e..4f934ae 100644 --- a/gas/macro.c +++ b/gas/macro.c @@ -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++; - - /* Skip over a label. */ - while (i < ptr->len - && (ISALNUM (ptr->ptr[i]) - || ptr->ptr[i] == '_' - || ptr->ptr[i] == '$')) - i++; + if (! LABELS_WITHOUT_COLONS) + { + /* Skip leading whitespace. */ + while (i < ptr->len && ISWHITE (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); @@ -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, ¯o)) + { + 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'; - - /* Install the line with the listing facility. */ - listing_newline (copy); + 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); + } } 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, ¯o)) - { - 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); } diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 9628cbc..5afbf51 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -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. diff --git a/gas/testsuite/gas/macros/dot.l b/gas/testsuite/gas/macros/dot.l new file mode 100644 index 0000000..e74e4f3 --- /dev/null +++ b/gas/testsuite/gas/macros/dot.l @@ -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 diff --git a/gas/testsuite/gas/macros/dot.s b/gas/testsuite/gas/macros/dot.s new file mode 100644 index 0000000..10ed42f --- /dev/null +++ b/gas/testsuite/gas/macros/dot.s @@ -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 diff --git a/gas/testsuite/gas/macros/macros.exp b/gas/testsuite/gas/macros/macros.exp index 37435cc..5b924ac 100644 --- a/gas/testsuite/gas/macros/macros.exp +++ b/gas/testsuite/gas/macros/macros.exp @@ -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 "" |