gas/:
[deliverable/binutils-gdb.git] / gas / read.c
index daea0f9a071fda41c92f226c75d2fa785d168298..7938a57fef85c38bf5ff0c4a1c2184889e94a59d 100644 (file)
@@ -20,14 +20,10 @@ along with GAS; see the file COPYING.  If not, write to the Free
 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
-#if 0
-/* If your chars aren't 8 bits, you will change this a bit.
+/* If your chars aren't 8 bits, you will change this a bit (eg. to 0xFF).
    But then, GNU isn't spozed to run on your machine anyway.
    (RMS is so shortsighted sometimes.)  */
-#define MASK_CHAR (0xFF)
-#else
 #define MASK_CHAR ((int)(unsigned char) -1)
-#endif
 
 /* This is the largest known floating point format (for now). It will
    grow when we do 4361 style flonums.  */
@@ -218,6 +214,7 @@ static int dwarf_file_string;
 static void do_align (int, char *, int, int);
 static void s_align (int, int);
 static void s_altmacro (int);
+static void s_bad_end (int);
 static int hex_float (int, char *);
 static segT get_known_segmented_expression (expressionS * expP);
 static void pobegin (void);
@@ -246,6 +243,24 @@ read_begin (void)
     lex_type['?'] = 3;
 }
 \f
+#ifndef TC_ADDRESS_BYTES
+#ifdef BFD_ASSEMBLER
+#define TC_ADDRESS_BYTES address_bytes
+
+static inline int
+address_bytes (void)
+{
+  /* Choose smallest of 1, 2, 4, 8 bytes that is large enough to
+     contain an address.  */
+  int n = (stdoutput->arch_info->bits_per_address - 1) / 8;
+  n |= n >> 1;
+  n |= n >> 2;
+  n += 1;
+  return n;
+}
+#endif
+#endif
+
 /* Set up pseudo-op tables.  */
 
 static struct hash_control *po_hash;
@@ -266,6 +281,9 @@ static const pseudo_typeS potable[] = {
   {"common.s", s_mri_common, 1},
   {"data", s_data, 0},
   {"dc", cons, 2},
+#ifdef TC_ADDRESS_BYTES
+  {"dc.a", cons, 0},
+#endif
   {"dc.b", cons, 1},
   {"dc.d", float_cons, 'd'},
   {"dc.l", cons, 4},
@@ -302,7 +320,8 @@ static const pseudo_typeS potable[] = {
   {"endc", s_endif, 0},
   {"endfunc", s_func, 1},
   {"endif", s_endif, 0},
-  {"endr", s_bad_endr, 0},
+  {"endm", s_bad_end, 0},
+  {"endr", s_bad_end, 1},
 /* endef  */
   {"equ", s_set, 0},
   {"equiv", s_set, 1},
@@ -501,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
@@ -528,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)
@@ -647,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);
@@ -710,13 +766,13 @@ read_a_source_file (char *name)
                  /* Input_line_pointer->after ':'.  */
                  SKIP_WHITESPACE ();
                }
-             else if (c == '='
-                      || ((c == ' ' || c == '\t')
-                          && input_line_pointer[1] == '='
+              else if ((c == '='
+                       || ((c == ' ' || c == '\t')
+                            && input_line_pointer[1] == '='))
 #ifdef TC_EQUAL_IN_INSN
-                          && !TC_EQUAL_IN_INSN (c, input_line_pointer)
+                           && !TC_EQUAL_IN_INSN (c, s)
 #endif
-                          ))
+                           )
                {
                  equals (s, 1);
                  demand_empty_rest_of_line ();
@@ -797,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;
                        }
 
@@ -855,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)
                        {
@@ -1453,7 +1498,6 @@ s_comm_internal (int param,
 #endif
     }
 
-  know (symbolP == NULL || symbolP->sy_frag == &zero_address_frag);
   demand_empty_rest_of_line ();
  out:
   if (flag_mri)
@@ -1601,7 +1645,7 @@ s_data (int ignore ATTRIBUTE_UNUSED)
    .file.  */
 
 void
-s_app_file_string (char *file, int appfile)
+s_app_file_string (char *file, int appfile ATTRIBUTE_UNUSED)
 {
 #ifdef LISTING
   if (listing)
@@ -2301,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);
        }
@@ -2663,12 +2707,14 @@ s_purgem (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
-/* Handle the .rept pseudo-op.  */
+/* Handle the .endm/.endr pseudo-ops.  */
 
-void
-s_bad_endr (int ignore ATTRIBUTE_UNUSED)
+static void
+s_bad_end (int endr)
 {
-  as_warn (_(".endr encountered without preceeding .rept, .irc, or .irp"));
+  as_warn (_(".end%c encountered without preceeding %s"),
+          endr ? 'r' : 'm',
+          endr ? ".rept, .irp, or .irpc" : ".macro");
   demand_empty_rest_of_line ();
 }
 
@@ -2727,6 +2773,57 @@ end_repeat (int extra)
     buffer_limit = input_scrub_next_buffer (&input_line_pointer);
 }
 
+static void
+assign_symbol (char *name, int no_reassign)
+{
+  symbolS *symbolP;
+
+  if (name[0] == '.' && name[1] == '\0')
+    {
+      /* Turn '. = mumble' into a .org mumble.  */
+      segT segment;
+      expressionS exp;
+
+      segment = get_known_segmented_expression (&exp);
+
+      if (!need_pass_2)
+       do_org (segment, &exp, 0);
+
+      return;
+    }
+
+  if ((symbolP = symbol_find (name)) == NULL
+      && (symbolP = md_undefined_symbol (name)) == NULL)
+    {
+      symbolP = symbol_find_or_make (name);
+#ifndef NO_LISTING
+      /* When doing symbol listings, play games with dummy fragments living
+        outside the normal fragment chain to record the file and line info
+        for this symbol.  */
+      if (listing & LISTING_SYMBOLS)
+       {
+         extern struct list_info_struct *listing_tail;
+         fragS *dummy_frag = (fragS *) xcalloc (1, sizeof (fragS));
+         dummy_frag->line = listing_tail;
+         dummy_frag->fr_symbol = symbolP;
+         symbol_set_frag (symbolP, dummy_frag);
+       }
+#endif
+#ifdef OBJ_COFF
+      /* "set" symbols are local unless otherwise specified.  */
+      SF_SET_LOCAL (symbolP);
+#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);
+
+  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.  */
@@ -2734,10 +2831,9 @@ end_repeat (int extra)
 void
 s_set (int equiv)
 {
-  register char *name;
-  register char delim;
-  register char *end_name;
-  register symbolS *symbolP;
+  char *name;
+  char delim;
+  char *end_name;
 
   /* Especial apologies for the random logic:
      this just grew, and could be parsed much more simply!
@@ -2768,58 +2864,9 @@ s_set (int equiv)
   input_line_pointer++;
   *end_name = 0;
 
-  if (name[0] == '.' && name[1] == '\0')
-    {
-      /* Turn '. = mumble' into a .org mumble.  */
-      register segT segment;
-      expressionS exp;
-
-      segment = get_known_segmented_expression (&exp);
-
-      if (!need_pass_2)
-       do_org (segment, &exp, 0);
-
-      *end_name = delim;
-      return;
-    }
-
-  if ((symbolP = symbol_find (name)) == NULL
-      && (symbolP = md_undefined_symbol (name)) == NULL)
-    {
-#ifndef NO_LISTING
-      /* When doing symbol listings, play games with dummy fragments living
-        outside the normal fragment chain to record the file and line info
-        for this symbol.  */
-      if (listing & LISTING_SYMBOLS)
-       {
-         extern struct list_info_struct *listing_tail;
-         fragS *dummy_frag = (fragS *) xmalloc (sizeof (fragS));
-         memset (dummy_frag, 0, sizeof (fragS));
-         dummy_frag->fr_type = rs_fill;
-         dummy_frag->line = listing_tail;
-         symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
-         dummy_frag->fr_symbol = symbolP;
-       }
-      else
-#endif
-       symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
-
-#ifdef OBJ_COFF
-      /* "set" symbols are local unless otherwise specified.  */
-      SF_SET_LOCAL (symbolP);
-#endif /* OBJ_COFF */
-    }
-
-  symbol_table_insert (symbolP);
-
+  assign_symbol (name, equiv);
   *end_name = delim;
 
-  if (equiv
-      && S_IS_DEFINED (symbolP)
-      && S_GET_SEGMENT (symbolP) != reg_section)
-    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
-
-  pseudo_set (symbolP);
   demand_empty_rest_of_line ();
 }
 
@@ -3157,6 +3204,16 @@ discard_rest_of_line (void)
   know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
 }
 
+/* Sets frag for given symbol to zero_address_frag, except when the
+   symbol frag is already set to a dummy listing frag.  */
+
+static void
+set_zero_frag (symbolS *symbolP)
+{
+  if (symbol_get_frag (symbolP)->fr_type != rs_dummy)
+    symbol_set_frag (symbolP, &zero_address_frag);
+}
+
 /* In: Pointer to a symbol.
        Input_line_pointer->expression.
 
@@ -3168,14 +3225,12 @@ void
 pseudo_set (symbolS *symbolP)
 {
   expressionS exp;
+  segT seg;
 #if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
   int ext;
 #endif /* OBJ_AOUT or OBJ_BOUT */
 
   know (symbolP);              /* NULL pointer is logic error.  */
-#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
-  ext = S_IS_EXTERNAL (symbolP);
-#endif /* OBJ_AOUT or OBJ_BOUT */
 
   (void) expression (&exp);
 
@@ -3200,6 +3255,15 @@ pseudo_set (symbolS *symbolP)
                          - S_GET_VALUE (exp.X_op_symbol));
     }
 
+  if (symbol_section_p (symbolP))
+    {
+      as_bad ("attempt to set value of section symbol");
+      return;
+    }
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
+  ext = S_IS_EXTERNAL (symbolP);
+#endif /* OBJ_AOUT or OBJ_BOUT */
+
   switch (exp.X_op)
     {
     case O_illegal:
@@ -3209,53 +3273,55 @@ pseudo_set (symbolS *symbolP)
       /* Fall through.  */
     case O_constant:
       S_SET_SEGMENT (symbolP, absolute_section);
-#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
-      if (ext)
-       S_SET_EXTERNAL (symbolP);
-      else
-       S_CLEAR_EXTERNAL (symbolP);
-#endif /* OBJ_AOUT or OBJ_BOUT */
       S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
-      if (exp.X_op != O_constant)
-       symbol_set_frag (symbolP, &zero_address_frag);
+      set_zero_frag (symbolP);
       break;
 
     case O_register:
       S_SET_SEGMENT (symbolP, reg_section);
       S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
-      symbol_set_frag (symbolP, &zero_address_frag);
+      set_zero_frag (symbolP);
       break;
 
     case O_symbol:
-      if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section
-         || exp.X_add_number != 0)
-       symbol_set_value_expression (symbolP, &exp);
-      else if (symbol_section_p (symbolP))
-       as_bad ("attempt to set value of section symbol");
-      else
+      seg = S_GET_SEGMENT (exp.X_add_symbol);
+      /* For x=undef+const, create an expression symbol.
+        For x=x+const, just update x except when x is an undefined symbol
+        For x=defined+const, evaluate x.  */
+      if (symbolP == exp.X_add_symbol
+         && (seg != undefined_section
+             || !symbol_constant_p (symbolP)))
+       {
+         *symbol_X_add_number (symbolP) += exp.X_add_number;
+         break;
+       }
+      else if (seg != undefined_section)
        {
          symbolS *s = exp.X_add_symbol;
 
-         S_SET_SEGMENT (symbolP, S_GET_SEGMENT (s));
-#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
-         if (ext)
-           S_SET_EXTERNAL (symbolP);
-         else
-           S_CLEAR_EXTERNAL (symbolP);
-#endif /* OBJ_AOUT or OBJ_BOUT */
-         S_SET_VALUE (symbolP,
-                      exp.X_add_number + S_GET_VALUE (s));
+         S_SET_SEGMENT (symbolP, seg);
+         S_SET_VALUE (symbolP, exp.X_add_number + S_GET_VALUE (s));
          symbol_set_frag (symbolP, symbol_get_frag (s));
          copy_symbol_attributes (symbolP, s);
+         break;
        }
-      break;
+      /* Fall thru */
 
     default:
       /* The value is some complex expression.
-        FIXME: Should we set the segment to anything?  */
+        Set segment and frag back to that of a newly created symbol.  */
+      S_SET_SEGMENT (symbolP, undefined_section);
       symbol_set_value_expression (symbolP, &exp);
+      set_zero_frag (symbolP);
       break;
     }
+
+#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
+  if (ext)
+    S_SET_EXTERNAL (symbolP);
+  else
+    S_CLEAR_EXTERNAL (symbolP);
+#endif /* OBJ_AOUT or OBJ_BOUT */
 }
 \f
 /*                     cons()
@@ -3339,6 +3405,11 @@ cons_worker (register int nbytes,        /* 1=.byte, 2=.word, 4=.long.  */
       return;
     }
 
+#ifdef TC_ADDRESS_BYTES
+  if (nbytes == 0)
+    nbytes = TC_ADDRESS_BYTES ();
+#endif
+
 #ifdef md_cons_align
   md_cons_align (nbytes);
 #endif
@@ -4388,7 +4459,7 @@ void
 emit_leb128_expr (expressionS *exp, int sign)
 {
   operatorT op = exp->X_op;
-  int nbytes;
+  unsigned int nbytes;
 
   if (op == O_absent || op == O_illegal)
     {
@@ -4420,7 +4491,7 @@ emit_leb128_expr (expressionS *exp, int sign)
 
   /* Let check_eh_frame know that data is being emitted.  nbytes == -1 is
      a signal that this is leb128 data.  It shouldn't optimize this away.  */
-  nbytes = -1;
+  nbytes = (unsigned int) -1;
   if (check_eh_frame (exp, &nbytes))
     abort ();
 
@@ -4859,7 +4930,6 @@ is_it_end_of_statement (void)
 void
 equals (char *sym_name, int reassign)
 {
-  register symbolS *symbolP;   /* Symbol we are working with.  */
   char *stop = NULL;
   char stopc;
 
@@ -4873,44 +4943,10 @@ equals (char *sym_name, int reassign)
   if (flag_mri)
     stop = mri_comment_field (&stopc);
 
-  if (sym_name[0] == '.' && sym_name[1] == '\0')
-    {
-      /* Turn '. = mumble' into a .org mumble.  */
-      register segT segment;
-      expressionS exp;
-
-      segment = get_known_segmented_expression (&exp);
-      if (!need_pass_2)
-       do_org (segment, &exp, 0);
-    }
-  else
-    {
-#ifdef OBJ_COFF
-      int local;
-
-      symbolP = symbol_find (sym_name);
-      local = symbolP == NULL;
-      if (local)
-#endif /* OBJ_COFF */
-      symbolP = symbol_find_or_make (sym_name);
-      /* Permit register names to be redefined.  */
-      if (!reassign
-         && S_IS_DEFINED (symbolP)
-         && S_GET_SEGMENT (symbolP) != reg_section)
-       as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
-
-#ifdef OBJ_COFF
-      /* "set" symbols are local unless otherwise specified.  */
-      if (local)
-       SF_SET_LOCAL (symbolP);
-#endif /* OBJ_COFF */
-
-      pseudo_set (symbolP);
-    }
+  assign_symbol (sym_name, !reassign);
 
   if (flag_mri)
     {
-      /* Check garbage after the expression.  */
       demand_empty_rest_of_line ();
       mri_comment_end (stop, stopc);
     }
This page took 0.036282 seconds and 4 git commands to generate.