X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fread.c;h=5d7a0d2d2254098f47791c8c3c47c1a46675db3d;hb=baee4c9eb00a09d53db7718dbdcb747b8cbafd95;hp=8e4e1bce60d3cabfc229d39c293d9a4f8a900340;hpb=66bd02d33d0451bc127a1166f09f03ea66f273d5;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/read.c b/gas/read.c index 8e4e1bce60..5d7a0d2d22 100644 --- a/gas/read.c +++ b/gas/read.c @@ -1,6 +1,6 @@ /* read.c - read a source file - Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -38,7 +38,6 @@ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA #include "sb.h" #include "macro.h" #include "obstack.h" -#include "listing.h" #include "ecoff.h" #include "dw2gencfi.h" @@ -323,6 +322,7 @@ static const pseudo_typeS potable[] = { /* endef */ {"equ", s_set, 0}, {"equiv", s_set, 1}, + {"eqv", s_set, -1}, {"err", s_err, 0}, {"error", s_errwarn, 1}, {"exitm", s_mexit, 0}, @@ -433,6 +433,7 @@ static const pseudo_typeS potable[] = { {"xref", s_ignore, 0}, {"xstabs", s_xstab, 's'}, {"warning", s_errwarn, 0}, + {"weakref", s_weakref, 0}, {"word", cons, 2}, {"zero", s_space, 0}, {NULL, NULL, 0} /* End sentinel. */ @@ -441,7 +442,7 @@ static const pseudo_typeS potable[] = { static offsetT get_absolute_expr (expressionS *exp) { - expression (exp); + expression_and_evaluate (exp); if (exp->X_op != O_constant) { if (exp->X_op != O_absent) @@ -787,6 +788,14 @@ read_a_source_file (char *name) /* Input_line_pointer->after ':'. */ SKIP_WHITESPACE (); } + else if (input_line_pointer[1] == '=' + && (c == '=' + || ((c == ' ' || c == '\t') + && input_line_pointer[2] == '='))) + { + equals (s, -1); + demand_empty_rest_of_line (); + } else if ((c == '=' || ((c == ' ' || c == '\t') && input_line_pointer[1] == '=')) @@ -998,10 +1007,14 @@ read_a_source_file (char *name) unsigned int new_length; char *tmp_buf = 0; - bump_line_counters (); s = input_line_pointer; if (strncmp (s, "APP\n", 4)) - continue; /* We ignore it */ + { + /* We ignore it. */ + ignore_rest_of_line (); + continue; + } + bump_line_counters (); s += 4; sb_new (&sbuf); @@ -1100,7 +1113,7 @@ read_a_source_file (char *name) continue; #endif input_line_pointer--; - /* Report unknown char as ignored. */ + /* Report unknown char as error. */ demand_empty_rest_of_line (); } @@ -1269,7 +1282,7 @@ s_align (int arg, int bytes_p) unsigned int align_limit = ALIGN_LIMIT; unsigned int align; char *stop = NULL; - char stopc; + char stopc = 0; offsetT fill = 0; int max; int fill_p; @@ -1413,7 +1426,7 @@ s_comm_internal (int param, offsetT temp, size; symbolS *symbolP = NULL; char *stop = NULL; - char stopc; + char stopc = 0; expressionS exp; if (flag_mri) @@ -1457,13 +1470,22 @@ s_comm_internal (int param, *p = 0; symbolP = symbol_find_or_make (name); - if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP)) + if ((S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP)) + && !S_IS_COMMON (symbolP)) { - symbolP = NULL; - as_bad (_("symbol `%s' is already defined"), name); - *p = c; - ignore_rest_of_line (); - goto out; + if (!S_IS_VOLATILE (symbolP)) + { + symbolP = NULL; + as_bad (_("symbol `%s' is already defined"), name); + *p = c; + ignore_rest_of_line (); + goto out; + } + symbolP = symbol_clone (symbolP, 1); + S_SET_SEGMENT (symbolP, undefined_section); + S_SET_VALUE (symbolP, 0); + symbol_set_frag (symbolP, &zero_address_frag); + S_CLEAR_VOLATILE (symbolP); } size = S_GET_VALUE (symbolP); @@ -1480,6 +1502,7 @@ s_comm_internal (int param, { S_SET_VALUE (symbolP, (valueT) size); S_SET_EXTERNAL (symbolP); + S_SET_SEGMENT (symbolP, bfd_com_section_ptr); #ifdef OBJ_VMS { extern int flag_one; @@ -1515,7 +1538,7 @@ s_mri_common (int small ATTRIBUTE_UNUSED) symbolS *sym; offsetT align; char *stop = NULL; - char stopc; + char stopc = 0; if (!flag_mri) { @@ -1573,6 +1596,7 @@ s_mri_common (int small ATTRIBUTE_UNUSED) } S_SET_EXTERNAL (sym); + S_SET_SEGMENT (sym, bfd_com_section_ptr); mri_common_symbol = sym; #ifdef S_SET_ALIGN @@ -1783,7 +1807,7 @@ s_fail (int ignore ATTRIBUTE_UNUSED) { offsetT temp; char *stop = NULL; - char stopc; + char stopc = 0; if (flag_mri) stop = mri_comment_field (&stopc); @@ -1905,7 +1929,7 @@ s_globl (int ignore ATTRIBUTE_UNUSED) int c; symbolS *symbolP; char *stop = NULL; - char stopc; + char stopc = 0; if (flag_mri) stop = mri_comment_field (&stopc); @@ -2210,7 +2234,7 @@ s_lsym (int ignore ATTRIBUTE_UNUSED) } input_line_pointer++; - expression (&exp); + expression_and_evaluate (&exp); if (exp.X_op != O_constant && exp.X_op != O_register) @@ -2223,15 +2247,7 @@ s_lsym (int ignore ATTRIBUTE_UNUSED) *p = 0; symbolP = symbol_find_or_make (name); - /* FIXME-SOON I pulled a (&& symbolP->sy_other == 0 && - symbolP->sy_desc == 0) out of this test because coff doesn't have - those fields, and I can't see when they'd ever be tripped. I - don't think I understand why they were here so I may have - introduced a bug. As recently as 1.37 didn't have this test - anyway. xoxorich. */ - - if (S_GET_SEGMENT (symbolP) == undefined_section - && S_GET_VALUE (symbolP) == 0) + if (S_GET_SEGMENT (symbolP) == undefined_section) { /* The name might be an undefined .global symbol; be sure to keep the "external" bit. */ @@ -2743,7 +2759,7 @@ end_repeat (int extra) } static void -assign_symbol (char *name, int no_reassign) +assign_symbol (char *name, int mode) { symbolS *symbolP; @@ -2784,18 +2800,34 @@ assign_symbol (char *name, int no_reassign) #endif } - /* Permit register names to be redefined. */ - if (no_reassign - && S_IS_DEFINED (symbolP) - && S_GET_SEGMENT (symbolP) != reg_section) - as_bad (_("symbol `%s' is already defined"), name); + if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP)) + { + /* Permit register names to be redefined. */ + if ((mode != 0 || !S_IS_VOLATILE (symbolP)) + && S_GET_SEGMENT (symbolP) != reg_section) + { + as_bad (_("symbol `%s' is already defined"), name); + symbolP = symbol_clone (symbolP, 0); + } + /* If the symbol is volatile, copy the symbol and replace the + original with the copy, so that previous uses of the symbol will + retain the value of the symbol at the point of use. */ + else if (S_IS_VOLATILE (symbolP)) + symbolP = symbol_clone (symbolP, 1); + } + + if (mode == 0) + S_SET_VOLATILE (symbolP); + else if (mode < 0) + S_SET_FORWARD_REF (symbolP); pseudo_set (symbolP); } -/* Handle the .equ, .equiv and .set directives. If EQUIV is 1, then - this is .equiv, and it is an error if the symbol is already - defined. */ +/* Handle the .equ, .equiv, .eqv, and .set directives. If EQUIV is 1, + then this is .equiv, and it is an error if the symbol is already + defined. If EQUIV is -1, the symbol additionally is a forward + reference. */ void s_set (int equiv) @@ -2846,7 +2878,7 @@ s_space (int mult) expressionS val; char *p = 0; char *stop = NULL; - char stopc; + char stopc = 0; int bytes; #ifdef md_flush_pending_output @@ -2917,6 +2949,7 @@ s_space (int mult) || val.X_add_number > 0xff || (mult != 0 && mult != 1 && val.X_add_number != 0)) { + resolve_expression (&exp); if (exp.X_op != O_constant) as_bad (_("unsupported variable size or fill value")); else @@ -2932,6 +2965,9 @@ s_space (int mult) } else { + if (now_seg == absolute_section || mri_common_symbol != NULL) + resolve_expression (&exp); + if (exp.X_op == O_constant) { long repeat; @@ -3018,7 +3054,7 @@ s_float_space (int float_type) int flen; char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT]; char *stop = NULL; - char stopc; + char stopc = 0; if (flag_mri) stop = mri_comment_field (&stopc); @@ -3095,11 +3131,17 @@ void s_struct (int ignore ATTRIBUTE_UNUSED) { char *stop = NULL; - char stopc; + char stopc = 0; if (flag_mri) stop = mri_comment_field (&stopc); abs_section_offset = get_absolute_expression (); +#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) + /* The ELF backend needs to know that we are changing sections, so + that .previous works correctly. */ + if (IS_ELF) + obj_elf_section_change_hook (); +#endif subseg_set (absolute_section, 0); demand_empty_rest_of_line (); if (flag_mri) @@ -3118,6 +3160,137 @@ s_text (int ignore ATTRIBUTE_UNUSED) const_flag &= ~IN_DEFAULT_SECTION; #endif } + +/* .weakref x, y sets x as an alias to y that, as long as y is not + referenced directly, will cause y to become a weak symbol. */ +void +s_weakref (int ignore ATTRIBUTE_UNUSED) +{ + char *name; + char delim; + char *end_name; + symbolS *symbolP; + symbolS *symbolP2; + expressionS exp; + + name = input_line_pointer; + delim = get_symbol_end (); + end_name = input_line_pointer; + + if (name == end_name) + { + as_bad (_("expected symbol name")); + *end_name = delim; + ignore_rest_of_line (); + return; + } + + symbolP = symbol_find_or_make (name); + + if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP)) + { + if (!S_IS_VOLATILE (symbolP)) + { + as_bad (_("symbol `%s' is already defined"), name); + *end_name = delim; + ignore_rest_of_line (); + return; + } + symbolP = symbol_clone (symbolP, 1); + S_CLEAR_VOLATILE (symbolP); + } + + *end_name = delim; + + SKIP_WHITESPACE (); + + if (*input_line_pointer != ',') + { + *end_name = 0; + as_bad (_("expected comma after \"%s\""), name); + *end_name = delim; + ignore_rest_of_line (); + return; + } + + input_line_pointer++; + + SKIP_WHITESPACE (); + + name = input_line_pointer; + delim = get_symbol_end (); + end_name = input_line_pointer; + + if (name == end_name) + { + as_bad (_("expected symbol name")); + ignore_rest_of_line (); + return; + } + + if ((symbolP2 = symbol_find_noref (name, 1)) == NULL + && (symbolP2 = md_undefined_symbol (name)) == NULL) + { + symbolP2 = symbol_find_or_make (name); + S_SET_WEAKREFD (symbolP2); + } + else + { + symbolS *symp = symbolP2; + + while (S_IS_WEAKREFR (symp) && symp != symbolP) + { + expressionS *expP = symbol_get_value_expression (symp); + + assert (expP->X_op == O_symbol + && expP->X_add_number == 0); + symp = expP->X_add_symbol; + } + if (symp == symbolP) + { + char *loop; + + loop = concat (S_GET_NAME (symbolP), + " => ", S_GET_NAME (symbolP2), NULL); + + symp = symbolP2; + while (symp != symbolP) + { + char *old_loop = loop; + symp = symbol_get_value_expression (symp)->X_add_symbol; + loop = concat (loop, " => ", S_GET_NAME (symp), NULL); + free (old_loop); + } + + as_bad (_("%s: would close weakref loop: %s"), + S_GET_NAME (symbolP), loop); + + free (loop); + + *end_name = delim; + ignore_rest_of_line (); + return; + } + + /* Short-circuiting instead of just checking here might speed + things up a tiny little bit, but loop error messages would + miss intermediate links. */ + /* symbolP2 = symp; */ + } + + *end_name = delim; + + memset (&exp, 0, sizeof (exp)); + exp.X_op = O_symbol; + exp.X_add_symbol = symbolP2; + + S_SET_SEGMENT (symbolP, undefined_section); + symbol_set_value_expression (symbolP, &exp); + symbol_set_frag (symbolP, &zero_address_frag); + S_SET_WEAKREFR (symbolP); + + demand_empty_rest_of_line (); +} /* Verify that we are at the end of a line. If not, issue an error and @@ -3185,7 +3358,10 @@ pseudo_set (symbolS *symbolP) know (symbolP); /* NULL pointer is logic error. */ - (void) expression (&exp); + if (!S_IS_FORWARD_REF (symbolP)) + (void) expression (&exp); + else + (void) deferred_expression (&exp); if (exp.X_op == O_illegal) as_bad (_("illegal expression")); @@ -3199,6 +3375,7 @@ pseudo_set (symbolS *symbolP) as_bad (_("floating point number invalid")); } else if (exp.X_op == O_subtract + && !S_IS_FORWARD_REF (symbolP) && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol)) && (symbol_get_frag (exp.X_add_symbol) == symbol_get_frag (exp.X_op_symbol))) @@ -3245,7 +3422,7 @@ pseudo_set (symbolS *symbolP) *symbol_X_add_number (symbolP) += exp.X_add_number; break; } - else if (seg != undefined_section) + else if (!S_IS_FORWARD_REF (symbolP) && seg != undefined_section) { symbolS *s = exp.X_add_symbol; @@ -3337,7 +3514,7 @@ cons_worker (register int nbytes, /* 1=.byte, 2=.word, 4=.long. */ int c; expressionS exp; char *stop = NULL; - char stopc; + char stopc = 0; #ifdef md_flush_pending_output md_flush_pending_output (); @@ -4833,11 +5010,13 @@ void equals (char *sym_name, int reassign) { char *stop = NULL; - char stopc; + char stopc = 0; input_line_pointer++; if (*input_line_pointer == '=') input_line_pointer++; + if (reassign < 0 && *input_line_pointer == '=') + input_line_pointer++; while (*input_line_pointer == ' ' || *input_line_pointer == '\t') input_line_pointer++; @@ -4845,7 +5024,7 @@ equals (char *sym_name, int reassign) if (flag_mri) stop = mri_comment_field (&stopc); - assign_symbol (sym_name, !reassign); + assign_symbol (sym_name, reassign >= 0 ? !reassign : reassign); if (flag_mri) {