Fix score bugs
[deliverable/binutils-gdb.git] / gas / read.c
index 00f676f223ef9a6d6973f372f9d038239358f90c..5d7a0d2d2254098f47791c8c3c47c1a46675db3d 100644 (file)
@@ -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"
 
@@ -434,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.  */
@@ -1007,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);
@@ -1109,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 ();
        }
 
@@ -1278,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;
@@ -1422,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)
@@ -1466,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);
@@ -1489,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;
@@ -1524,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)
     {
@@ -1582,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
@@ -1792,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);
@@ -1914,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);
@@ -2232,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.  */
@@ -2793,7 +2800,7 @@ assign_symbol (char *name, int mode)
 #endif
     }
 
-  if (S_IS_DEFINED (symbolP))
+  if (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
     {
       /* Permit register names to be redefined.  */
       if ((mode != 0 || !S_IS_VOLATILE (symbolP))
@@ -2805,10 +2812,7 @@ assign_symbol (char *name, int mode)
       /* 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)
-         /* This could be avoided when the symbol wasn't used so far, but
-            the comment in struc-symbol.h says this flag isn't reliable.  */
-         && (1 || symbol_used_p (symbolP)))
+      else if (S_IS_VOLATILE (symbolP))
        symbolP = symbol_clone (symbolP, 1);
     }
 
@@ -2874,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
@@ -3050,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);
@@ -3127,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)
@@ -3150,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 ();
+}
 \f
 
 /* Verify that we are at the end of a line.  If not, issue an error and
@@ -3373,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 ();
@@ -4869,7 +5010,7 @@ void
 equals (char *sym_name, int reassign)
 {
   char *stop = NULL;
-  char stopc;
+  char stopc = 0;
 
   input_line_pointer++;
   if (*input_line_pointer == '=')
This page took 0.032503 seconds and 4 git commands to generate.