X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fmacro.c;h=0d1a1d24eae78ec003b9f7c74e97121c8de598e6;hb=934c26326909f953aaa15edb423dd4af6f33c448;hp=23156a1242a42a5185359eaa72c88b75a5d90bda;hpb=0e470c55e8f94578da761b5c08201b8bb2914902;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/macro.c b/gas/macro.c index 23156a1242..0d1a1d24ea 100644 --- a/gas/macro.c +++ b/gas/macro.c @@ -1,6 +1,5 @@ /* macro.c - macro support for gas - Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1994-2016 Free Software Foundation, Inc. Written by Steve and Judy Chamberlain of Cygnus Support, sac@cygnus.com @@ -9,7 +8,7 @@ GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -22,65 +21,14 @@ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "config.h" - -#ifndef __GNUC__ -# if HAVE_ALLOCA_H -# include -# else -# ifdef _AIX -/* Indented so that pre-ansi C compilers will ignore it, rather than - choke on it. Some versions of AIX require this to be the first - thing in the file. */ - #pragma alloca -# else -# ifndef alloca /* predefined by HP cc +Olibcalls */ -# if !defined (__STDC__) && !defined (__hpux) -extern char *alloca (); -# else -extern void *alloca (); -# endif /* __STDC__, __hpux */ -# endif /* alloca */ -# endif /* _AIX */ -# endif /* HAVE_ALLOCA_H */ -#endif /* __GNUC__ */ - -#include -#ifdef HAVE_STRING_H -#include -#else -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif #include "as.h" -#include "libiberty.h" #include "safe-ctype.h" #include "sb.h" -#include "hash.h" #include "macro.h" -#include "asintl.h" - /* The routines in this file handle macro definition and expansion. They are called by gas. */ -/* Internal functions. */ - -static int get_token (int, sb *, sb *); -static int getstring (int, sb *, sb *); -static int get_any_string (int, sb *, sb *); -static formal_entry *new_formal (void); -static void del_formal (formal_entry *); -static int do_formals (macro_entry *, int, sb *); -static int get_apost_token (int, sb *, sb *, int); -static int sub_actual (int, sb *, sb *, struct hash_control *, int, sb *, int); -static const char *macro_expand_body - (sb *, sb *, formal_entry *, struct hash_control *, const macro_entry *); -static const char *macro_expand (int, sb *, macro_entry *, sb *); -static void free_macro(macro_entry *); - #define ISWHITE(x) ((x) == ' ' || (x) == '\t') #define ISSEP(x) \ @@ -116,7 +64,7 @@ static int macro_strip_at; /* Function to use to parse an expression. */ -static int (*macro_expr) (const char *, int, sb *, int *); +static size_t (*macro_expr) (const char *, size_t, sb *, offsetT *); /* Number of macro expansions that have been done. */ @@ -126,14 +74,14 @@ static int macro_number; void macro_init (int alternate, int mri, int strip_at, - int (*expr) (const char *, int, sb *, int *)) + size_t (*exp) (const char *, size_t, sb *, offsetT *)) { macro_hash = hash_new (); macro_defined = 0; macro_alternate = alternate; macro_mri = mri; macro_strip_at = strip_at; - macro_expr = expr; + macro_expr = exp; } /* Switch in and out of alternate mode on the fly. */ @@ -161,16 +109,15 @@ macro_mri_mode (int mri) int buffer_and_nest (const char *from, const char *to, sb *ptr, - int (*get_line) (sb *)) + size_t (*get_line) (sb *)) { - int from_len; - int to_len = strlen (to); + size_t from_len; + size_t to_len = strlen (to); int depth = 1; - int line_start = ptr->len; - - int more = get_line (ptr); + size_t line_start = ptr->len; + size_t more = get_line (ptr); - if (to_len == 4 && strcasecmp(to, "ENDR") == 0) + if (to_len == 4 && strcasecmp (to, "ENDR") == 0) { from = NULL; from_len = 0; @@ -181,7 +128,8 @@ buffer_and_nest (const char *from, const char *to, sb *ptr, while (more) { /* Try to find the first pseudo op on the line. */ - int i = line_start; + size_t i = line_start; + bfd_boolean had_colon = FALSE; /* With normal syntax we can suck what we want till we get to the dot. With the alternate, labels have to start in @@ -205,19 +153,24 @@ buffer_and_nest (const char *from, const char *to, sb *ptr, 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] != ':') { + /* LABELS_WITHOUT_COLONS doesn't mean we cannot have a + colon after a label. If we do have a colon on the + first label then handle more than one label on the + line, assuming that each label has a colon. */ + if (LABELS_WITHOUT_COLONS && !had_colon) + break; i = line_start; break; } i++; line_start = i; + had_colon = TRUE; } /* Skip trailing whitespace. */ @@ -258,6 +211,28 @@ buffer_and_nest (const char *from, const char *to, sb *ptr, break; } } + + /* PR gas/16908 + Apply and discard .linefile directives that appear within + the macro. For long macros, one might want to report the + line number information associated with the lines within + the macro definition, but we would need more infrastructure + to make that happen correctly (e.g. resetting the line + number when expanding the macro), and since for short + macros we clearly prefer reporting the point of expansion + anyway, there's not an obviously better fix here. */ + if (strncasecmp (ptr->ptr + i, "linefile", 8) == 0) + { + char *saved_input_line_pointer = input_line_pointer; + char saved_eol_char = ptr->ptr[ptr->len]; + + ptr->ptr[ptr->len] = '\0'; + input_line_pointer = ptr->ptr + i + 8; + s_app_line (0); + ptr->ptr[ptr->len] = saved_eol_char; + input_line_pointer = saved_input_line_pointer; + ptr->len = line_start; + } } /* Add the original end-of-line char to the end and keep running. */ @@ -272,8 +247,8 @@ buffer_and_nest (const char *from, const char *to, sb *ptr, /* Pick up a token. */ -static int -get_token (int idx, sb *in, sb *name) +static size_t +get_token (size_t idx, sb *in, sb *name) { if (idx < in->len && is_name_beginner (in->ptr[idx])) @@ -298,23 +273,19 @@ get_token (int idx, sb *in, sb *name) /* Pick up a string. */ -static int -getstring (int idx, sb *in, sb *acc) +static size_t +getstring (size_t idx, sb *in, sb *acc) { while (idx < in->len && (in->ptr[idx] == '"' - || in->ptr[idx] == '(' || (in->ptr[idx] == '<' && (macro_alternate || macro_mri)) || (in->ptr[idx] == '\'' && macro_alternate))) { if (in->ptr[idx] == '<') { int nest = 0; - char start_char = '>'; - char end_char = '>'; - idx++; - while ((in->ptr[idx] != end_char || nest) + while ((in->ptr[idx] != '>' || nest) && idx < in->len) { if (in->ptr[idx] == '!') @@ -324,37 +295,15 @@ getstring (int idx, sb *in, sb *acc) } else { - if (in->ptr[idx] == end_char) + if (in->ptr[idx] == '>') nest--; - if (in->ptr[idx] == start_char) + if (in->ptr[idx] == '<') nest++; sb_add_char (acc, in->ptr[idx++]); } } idx++; } - else if (in->ptr[idx] == '(') - { - int nest = 0; - char c; - - do - { - c = in->ptr[idx]; - - if (c == '!') - c = in->ptr[++idx]; - else if (c == ')') - nest--; - else if (c == '(') - nest++; - - sb_add_char (acc, c); - idx++; - } - while ((c != ')' || nest) - && idx < in->len); - } else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'') { char tchar = in->ptr[idx]; @@ -410,8 +359,8 @@ getstring (int idx, sb *in, sb *acc) (string) -> return (string-including-whitespaces) xyx -> return xyz. */ -static int -get_any_string (int idx, sb *in, sb *out) +static size_t +get_any_string (size_t idx, sb *in, sb *out) { sb_reset (out); idx = sb_skip_white (idx, in); @@ -425,7 +374,7 @@ get_any_string (int idx, sb *in, sb *out) } else if (in->ptr[idx] == '%' && macro_alternate) { - int val; + offsetT val; char buf[20]; /* Turns the next expression into a string. */ @@ -434,21 +383,19 @@ get_any_string (int idx, sb *in, sb *out) idx + 1, in, &val); - sprintf (buf, "%d", val); + sprintf (buf, "%" BFD_VMA_FMT "d", val); sb_add_string (out, buf); } else if (in->ptr[idx] == '"' - || in->ptr[idx] == '(' || (in->ptr[idx] == '<' && (macro_alternate || macro_mri)) || (macro_alternate && in->ptr[idx] == '\'')) { - if (macro_alternate && ! macro_strip_at) + if (macro_alternate && ! macro_strip_at && in->ptr[idx] != '<') { /* Keep the quotes. */ - sb_add_char (out, '\"'); - + sb_add_char (out, '"'); idx = getstring (idx, in, out); - sb_add_char (out, '\"'); + sb_add_char (out, '"'); } else { @@ -457,27 +404,60 @@ get_any_string (int idx, sb *in, sb *out) } else { + char *br_buf = XNEWVEC (char, 1); + char *in_br = br_buf; + + *in_br = '\0'; while (idx < in->len - && in->ptr[idx] != ' ' - && in->ptr[idx] != '\t' + && (*in_br + || (in->ptr[idx] != ' ' + && in->ptr[idx] != '\t')) && in->ptr[idx] != ',' && (in->ptr[idx] != '<' || (! macro_alternate && ! macro_mri))) { - if (in->ptr[idx] == '"' - || in->ptr[idx] == '\'') - { - char tchar = in->ptr[idx]; + char tchar = in->ptr[idx]; + switch (tchar) + { + case '"': + case '\'': sb_add_char (out, in->ptr[idx++]); while (idx < in->len && in->ptr[idx] != tchar) sb_add_char (out, in->ptr[idx++]); if (idx == in->len) - return idx; + { + free (br_buf); + return idx; + } + break; + case '(': + case '[': + if (in_br > br_buf) + --in_br; + else + { + br_buf = XNEWVEC (char, strlen (in_br) + 2); + strcpy (br_buf + 1, in_br); + free (in_br); + in_br = br_buf; + } + *in_br = tchar; + break; + case ')': + if (*in_br == '(') + ++in_br; + break; + case ']': + if (*in_br == '[') + ++in_br; + break; } - sb_add_char (out, in->ptr[idx++]); + sb_add_char (out, tchar); + ++idx; } + free (br_buf); } } @@ -491,7 +471,7 @@ new_formal (void) { formal_entry *formal; - formal = xmalloc (sizeof (formal_entry)); + formal = XNEW (formal_entry); sb_new (&formal->name); sb_new (&formal->def); @@ -514,8 +494,8 @@ del_formal (formal_entry *formal) /* Pick up the formal parameters of a macro definition. */ -static int -do_formals (macro_entry *macro, int idx, sb *in) +static size_t +do_formals (macro_entry *macro, size_t idx, sb *in) { formal_entry **p = ¯o->formals; const char *name; @@ -524,13 +504,14 @@ do_formals (macro_entry *macro, int idx, sb *in) while (idx < in->len) { formal_entry *formal = new_formal (); - int cidx; + size_t cidx; idx = get_token (idx, in, &formal->name); if (formal->name.len == 0) { if (macro->formal_count) --idx; + del_formal (formal); /* 'formal' goes out of scope. */ break; } idx = sb_skip_white (idx, in); @@ -614,9 +595,9 @@ do_formals (macro_entry *macro, int idx, sb *in) formal_entry *formal = new_formal (); /* Add a special NARG formal, which macro_expand will set to the - number of arguments. */ + number of arguments. */ /* The same MRI assemblers which treat '@' characters also use - the name $NARG. At least until we find an exception. */ + the name $NARG. At least until we find an exception. */ if (macro_strip_at) name = "$NARG"; else @@ -640,21 +621,41 @@ do_formals (macro_entry *macro, int idx, sb *in) return idx; } +/* Free the memory allocated to a macro. */ + +static void +free_macro (macro_entry *macro) +{ + formal_entry *formal; + + for (formal = macro->formals; formal; ) + { + formal_entry *f; + + f = formal; + formal = formal->next; + del_formal (f); + } + hash_die (macro->formal_hash); + sb_kill (¯o->sub); + free (macro); +} + /* Define a new macro. Returns NULL on success, otherwise returns an error message. If NAMEP is not NULL, *NAMEP is set to the name of the macro which was defined. */ const char * -define_macro (int idx, sb *in, sb *label, - int (*get_line) (sb *), - char *file, unsigned int line, +define_macro (size_t idx, sb *in, sb *label, + size_t (*get_line) (sb *), + const char *file, unsigned int line, const char **namep) { macro_entry *macro; sb name; const char *error = NULL; - macro = (macro_entry *) xmalloc (sizeof (macro_entry)); + macro = XNEW (macro_entry); sb_new (¯o->sub); sb_new (&name); macro->file = file; @@ -662,7 +663,7 @@ define_macro (int idx, sb *in, sb *label, macro->formal_count = 0; macro->formals = 0; - macro->formal_hash = hash_new (); + macro->formal_hash = hash_new_sized (7); idx = sb_skip_white (idx, in); if (! buffer_and_nest ("MACRO", "ENDM", ¯o->sub, get_line)) @@ -688,7 +689,7 @@ define_macro (int idx, sb *in, sb *label, } else { - int cidx; + size_t cidx; idx = get_token (idx, in, &name); macro->name = sb_terminate (&name); @@ -710,7 +711,7 @@ define_macro (int idx, sb *in, sb *label, if (hash_find (macro_hash, macro->name)) error = _("Macro `%s' was already defined"); if (!error) - error = hash_jam (macro_hash, macro->name, (PTR) macro); + error = hash_jam (macro_hash, macro->name, (void *) macro); if (namep != NULL) *namep = macro->name; @@ -725,8 +726,8 @@ define_macro (int idx, sb *in, sb *label, /* Scan a token, and then skip KIND. */ -static int -get_apost_token (int idx, sb *in, sb *name, int kind) +static size_t +get_apost_token (size_t idx, sb *in, sb *name, int kind) { idx = get_token (idx, in, name); if (idx < in->len @@ -739,11 +740,11 @@ get_apost_token (int idx, sb *in, sb *name, int kind) /* Substitute the actual value for a formal parameter. */ -static int -sub_actual (int start, sb *in, sb *t, struct hash_control *formal_hash, +static size_t +sub_actual (size_t start, sb *in, sb *t, struct hash_control *formal_hash, int kind, sb *out, int copyifnotthere) { - int src; + size_t src; formal_entry *ptr; src = get_apost_token (start, in, t, kind); @@ -771,6 +772,8 @@ sub_actual (int start, sb *in, sb *t, struct hash_control *formal_hash, /* Doing this permits people to use & in macro bodies. */ sb_add_char (out, '&'); sb_add_sb (out, t); + if (src != start && in->ptr[src - 1] == '&') + sb_add_char (out, '&'); } else if (copyifnotthere) { @@ -791,7 +794,8 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals, struct hash_control *formal_hash, const macro_entry *macro) { sb t; - int src = 0, inquote = 0, macro_line = 0; + size_t src = 0; + int inquote = 0, macro_line = 0; formal_entry *loclist = NULL; const char *err = NULL; @@ -811,9 +815,8 @@ 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; without this - one can't append a literal to a parameter. */ + /* Permit macro parameter substition delineated with + an '&' prefix and optional '&' suffix. */ src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0); } } @@ -891,7 +894,9 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals, if (! macro || src + 5 >= in->len || strncasecmp (in->ptr + src, "LOCAL", 5) != 0 - || ! ISWHITE (in->ptr[src + 5])) + || ! ISWHITE (in->ptr[src + 5]) + /* PR 11507: Skip keyword LOCAL if it is found inside a quoted string. */ + || inquote) { sb_reset (&t); src = sub_actual (src, in, &t, formal_hash, @@ -966,13 +971,13 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals, if (ptr == NULL) { /* FIXME: We should really return a warning string here, - but we can't, because the == might be in the MRI - comment field, and, since the nature of the MRI - comment field depends upon the exact instruction - being used, we don't have enough information here to - figure out whether it is or not. Instead, we leave - the == in place, which should cause a syntax error if - it is not in a comment. */ + but we can't, because the == might be in the MRI + comment field, and, since the nature of the MRI + comment field depends upon the exact instruction + being used, we don't have enough information here to + figure out whether it is or not. Instead, we leave + the == in place, which should cause a syntax error if + it is not in a comment. */ sb_add_char (out, '='); sb_add_char (out, '='); sb_add_sb (out, &t); @@ -1002,11 +1007,11 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals, while (loclist != NULL) { formal_entry *f; + const char *name; f = loclist->next; - /* Setting the value to NULL effectively deletes the entry. We - avoid calling hash_delete because it doesn't reclaim memory. */ - hash_jam (formal_hash, sb_terminate (&loclist->name), NULL); + name = sb_terminate (&loclist->name); + hash_delete (formal_hash, name, f == NULL); del_formal (loclist); loclist = f; } @@ -1018,12 +1023,11 @@ macro_expand_body (sb *in, sb *out, formal_entry *formals, body. */ static const char * -macro_expand (int idx, sb *in, macro_entry *m, sb *out) +macro_expand (size_t idx, sb *in, macro_entry *m, sb *out) { sb t; formal_entry *ptr; formal_entry *f; - int is_positional = 0; int is_keyword = 0; int narg = 0; const char *err = NULL; @@ -1040,7 +1044,7 @@ macro_expand (int idx, sb *in, macro_entry *m, sb *out) if (macro_mri) { /* The macro may be called with an optional qualifier, which may - be referred to in the macro body as \0. */ + be referred to in the macro body as \0. */ if (idx < in->len && in->ptr[idx] == '.') { /* The Microtec assembler ignores this if followed by a white space. @@ -1066,7 +1070,7 @@ macro_expand (int idx, sb *in, macro_entry *m, sb *out) idx = sb_skip_white (idx, in); while (idx < in->len) { - int scan; + size_t scan; /* Look and see if it's a positional or keyword arg. */ scan = idx; @@ -1094,9 +1098,13 @@ macro_expand (int idx, sb *in, macro_entry *m, sb *out) /* Lookup the formal in the macro's list. */ ptr = (formal_entry *) hash_find (m->formal_hash, sb_terminate (&t)); if (!ptr) - as_bad (_("Parameter named `%s' does not exist for macro `%s'"), - t.ptr, - m->name); + { + as_bad (_("Parameter named `%s' does not exist for macro `%s'"), + t.ptr, + m->name); + sb_reset (&t); + idx = get_any_string (idx + 1, in, &t); + } else { /* Insert this value into the right place. */ @@ -1114,8 +1122,6 @@ macro_expand (int idx, sb *in, macro_entry *m, sb *out) } else { - /* This is a positional arg. */ - is_positional = 1; if (is_keyword) { err = _("can't mix positional and keyword arguments"); @@ -1230,7 +1236,7 @@ check_macro (const char *line, sb *expand, const char **error, macro_entry **info) { const char *s; - char *copy, *cs; + char *copy, *cls; macro_entry *macro; sb line_sb; @@ -1244,13 +1250,12 @@ check_macro (const char *line, sb *expand, if (is_name_ender (*s)) ++s; - copy = (char *) alloca (s - line + 1); - memcpy (copy, line, s - line); - copy[s - line] = '\0'; - for (cs = copy; *cs != '\0'; cs++) - *cs = TOLOWER (*cs); + copy = xmemdup0 (line, s - line); + for (cls = copy; *cls != '\0'; cls ++) + *cls = TOLOWER (*cls); macro = (macro_entry *) hash_find (macro_hash, copy); + free (copy); if (macro == NULL) return 0; @@ -1272,26 +1277,6 @@ check_macro (const char *line, sb *expand, return 1; } -/* Free the memory allocated to a macro. */ - -static void -free_macro(macro_entry *macro) -{ - formal_entry *formal; - - for (formal = macro->formals; formal; ) - { - formal_entry *f; - - f = formal; - formal = formal->next; - del_formal (f); - } - hash_die (macro->formal_hash); - sb_kill (¯o->sub); - free (macro); -} - /* Delete a macro. */ void @@ -1302,19 +1287,22 @@ delete_macro (const char *name) macro_entry *macro; len = strlen (name); - copy = (char *) alloca (len + 1); + copy = XNEWVEC (char, len + 1); for (i = 0; i < len; ++i) copy[i] = TOLOWER (name[i]); copy[i] = '\0'; - /* Since hash_delete doesn't free memory, just clear out the entry. */ - if ((macro = hash_find (macro_hash, copy)) != NULL) + /* We can only ask hash_delete to free memory if we are deleting + macros in reverse order to their definition. + So just clear out the entry. */ + if ((macro = (macro_entry *) hash_find (macro_hash, copy)) != NULL) { hash_jam (macro_hash, copy, NULL); free_macro (macro); } else as_warn (_("Attempt to purge non-existant macro `%s'"), copy); + free (copy); } /* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a @@ -1322,7 +1310,7 @@ delete_macro (const char *name) success, or an error message otherwise. */ const char * -expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *)) +expand_irp (int irpc, size_t idx, sb *in, sb *out, size_t (*get_line) (sb *)) { sb sub; formal_entry f; @@ -1362,8 +1350,14 @@ expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *)) } else { + bfd_boolean in_quotes = FALSE; + if (irpc && in->ptr[idx] == '"') - ++idx; + { + in_quotes = TRUE; + ++idx; + } + while (idx < in->len) { if (!irpc) @@ -1372,7 +1366,10 @@ expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *)) { if (in->ptr[idx] == '"') { - int nxt; + size_t nxt; + + if (irpc) + in_quotes = ! in_quotes; nxt = sb_skip_white (idx + 1, in); if (nxt >= in->len) @@ -1385,12 +1382,13 @@ expand_irp (int irpc, int idx, sb *in, sb *out, int (*get_line) (sb *)) sb_add_char (&f.actual, in->ptr[idx]); ++idx; } + err = macro_expand_body (&sub, out, &f, h, 0); if (err != NULL) break; if (!irpc) idx = sb_skip_comma (idx, in); - else + else if (! in_quotes) idx = sb_skip_white (idx, in); } }