* macro.c (sub_actual): Don't lose string if it turns out that
[deliverable/binutils-gdb.git] / gas / read.c
index 30ad92c4ec14942b70c66db2ae49ae3e93a36a61..d75083e546b0ff1c1db1b8cb11d4c7dbbafc7f54 100644 (file)
@@ -1,6 +1,6 @@
 /* read.c - read a source file -
-   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
-   2000 Free Software Foundation, Inc.
+   Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GAS, the GNU Assembler.
 
@@ -17,7 +17,7 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 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. */
+02111-1307, USA.  */
 
 #if 0
 /* If your chars aren't 8 bits, you will change this a bit.
@@ -35,19 +35,18 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 /* Routines that read assembler source text to build spagetti in memory.
    Another group of these functions is in the expr.c module.  */
 
-/* For isdigit ().  */
-#include <ctype.h>
-
 #include "as.h"
+#include "safe-ctype.h"
 #include "subsegs.h"
 #include "sb.h"
 #include "macro.h"
 #include "obstack.h"
 #include "listing.h"
 #include "ecoff.h"
+#include "dw2gencfi.h"
 
 #ifndef TC_START_LABEL
-#define TC_START_LABEL(x,y) (x==':')
+#define TC_START_LABEL(x,y) (x == ':')
 #endif
 
 /* Set by the object-format or the target.  */
@@ -67,13 +66,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
   while (0)
 #endif
 
-/* The NOP_OPCODE is for the alignment fill value.
-   Fill it a nop instruction so that the disassembler does not choke
-   on it.  */
-#ifndef NOP_OPCODE
-#define NOP_OPCODE 0x00
-#endif
-
 char *input_line_pointer;      /*->next char of source file to parse.  */
 
 #if BITS_PER_CHAR != 8
@@ -119,8 +111,7 @@ die horribly;
 #endif
 
 /* Used by is_... macros. our ctype[].  */
-char lex_type[256] =
-{
+char lex_type[256] = {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      /* @ABCDEFGHIJKLMNO */
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      /* PQRSTUVWXYZ[\]^_ */
   0, 0, 0, LEX_HASH, LEX_DOLLAR, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
@@ -141,8 +132,7 @@ char lex_type[256] =
 
 /* In: a character.
    Out: 1 if this character ends a line.  */
-char is_end_of_line[256] =
-{
+char is_end_of_line[256] = {
 #ifdef CR_EOL
   1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,      /* @abcdefghijklmno */
 #else
@@ -165,6 +155,10 @@ char is_end_of_line[256] =
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0       /* */
 };
 
+#ifdef  IGNORE_OPCODE_CASE
+char original_case_string[128];
+#endif
+
 /* Functions private to this file.  */
 
 static char *buffer;   /* 1st char of each buffer of lines is here.  */
@@ -175,10 +169,6 @@ static char *buffer_limit; /*->1 + last char in buffer.  */
    internals manual.  */
 int target_big_endian = TARGET_BYTES_BIG_ENDIAN;
 
-static char *old_buffer;       /* JF a hack.  */
-static char *old_input;
-static char *old_limit;
-
 /* Variables for handling include file directory table.  */
 
 /* Table of pointers to directories to search for .include's.  */
@@ -271,8 +261,7 @@ read_begin ()
 
 static struct hash_control *po_hash;
 
-static const pseudo_typeS potable[] =
-{
+static const pseudo_typeS potable[] = {
   {"abort", s_abort, 0},
   {"align", s_align_ptwo, 0},
   {"ascii", stringer, 0},
@@ -323,6 +312,7 @@ static const pseudo_typeS potable[] =
   {"endc", s_endif, 0},
   {"endfunc", s_func, 1},
   {"endif", s_endif, 0},
+  {"endr", s_bad_endr, 0},
 /* endef  */
   {"equ", s_set, 0},
   {"equiv", s_set, 1},
@@ -355,6 +345,7 @@ static const pseudo_typeS potable[] =
   {"ifne", s_if, (int) O_ne},
   {"ifnes", s_ifeqs, 1},
   {"ifnotdef", s_ifdef, 1},
+  {"incbin", s_incbin, 0},
   {"include", s_include, 0},
   {"int", cons, 4},
   {"irp", s_irp, 0},
@@ -461,6 +452,10 @@ pop_insert (table)
 #define obj_pop_insert()       pop_insert(obj_pseudo_table)
 #endif
 
+#ifndef cfi_pop_insert
+#define cfi_pop_insert()       pop_insert(cfi_pseudo_table)
+#endif
+
 static void
 pobegin ()
 {
@@ -478,6 +473,12 @@ pobegin ()
   /* Now portable ones.  Skip any that we've seen already.  */
   pop_table_name = "standard";
   pop_insert (potable);
+  
+#ifdef TARGET_USE_CFIPOP
+  pop_table_name = "cfi";
+  pop_override_ok = 1;
+  cfi_pop_insert ();
+#endif
 }
 \f
 #define HANDLE_CONDITIONAL_ASSEMBLY()                                  \
@@ -521,6 +522,10 @@ read_a_source_file (name)
   register int temp;
   pseudo_typeS *pop;
 
+#ifdef WARN_COMMENTS
+  found_comment = 0;
+#endif
+
   buffer = input_scrub_new_file (name);
 
   listing_file (name);
@@ -535,9 +540,7 @@ read_a_source_file (name)
   while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0)
     {                          /* We have another line to parse.  */
       know (buffer_limit[-1] == '\n'); /* Must have a sentinel.  */
-    contin:                    /* JF this goto is my fault I admit it.
-                                  Someone brave please re-write the whole
-                                  input section here?  Pleeze???  */
+
       while (input_line_pointer < buffer_limit)
        {
          /* We have more of this buffer to parse.  */
@@ -602,10 +605,10 @@ read_a_source_file (name)
                          symbol in the symbol table.  */
                      if (!mri_line_macro
 #ifdef TC_START_LABEL_WITHOUT_COLON
-                          && TC_START_LABEL_WITHOUT_COLON(c,
-                                                          input_line_pointer)
+                         && TC_START_LABEL_WITHOUT_COLON(c,
+                                                         input_line_pointer)
 #endif
-                          )
+                         )
                        line_label = colon (line_start);
                      else
                        line_label = symbol_create (line_start,
@@ -623,7 +626,7 @@ read_a_source_file (name)
          /* We are at the begining of a line, or similar place.
             We expect a well-formed assembler statement.
             A "symbol-name:" is a statement.
-           
+
             Depending on what compiler is used, the order of these tests
             may vary to catch most common case 1st.
             Each test is independent of all other tests at the (top) level.
@@ -651,13 +654,13 @@ read_a_source_file (name)
                  int len;
 
                  /* Find the end of the current expanded macro line.  */
-                 for (s = input_line_pointer - 1; *s ; ++s)
+                 for (s = input_line_pointer - 1; *s; ++s)
                    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);
+                 len = s - (input_line_pointer - 1);
                  copy = (char *) xmalloc (len + macro_nest + 2);
                  memset (copy, '>', macro_nest);
                  copy[macro_nest] = ' ';
@@ -695,10 +698,10 @@ read_a_source_file (name)
                      /* In MRI mode, \tsym: set 0 is permitted.  */
                      if (*rest == ':')
                        ++rest;
-                     
+
                      if (*rest == ' ' || *rest == '\t')
                        ++rest;
-                     
+
                      if ((strncasecmp (rest, "EQU", 3) == 0
                           || strncasecmp (rest, "SET", 3) == 0)
                          && (rest[3] == ' ' || rest[3] == '\t'))
@@ -712,6 +715,9 @@ read_a_source_file (name)
                  line_label = colon (s);       /* User-defined label.  */
                  /* Put ':' back for error messages' sake.  */
                  *input_line_pointer++ = ':';
+#ifdef tc_check_label
+                 tc_check_label (line_label);
+#endif
                  /* Input_line_pointer->after ':'.  */
                  SKIP_WHITESPACE ();
                }
@@ -731,14 +737,16 @@ read_a_source_file (name)
                  /* Expect pseudo-op or machine instruction.  */
                  pop = NULL;
 
-#define IGNORE_OPCODE_CASE
 #ifdef IGNORE_OPCODE_CASE
                  {
                    char *s2 = s;
+
+                   strncpy (original_case_string, s2, sizeof (original_case_string));
+                   original_case_string[sizeof (original_case_string) - 1] = 0;
+
                    while (*s2)
                      {
-                       if (isupper ((unsigned char) *s2))
-                         *s2 = tolower (*s2);
+                       *s2 = TOLOWER (*s2);
                        s2++;
                      }
                  }
@@ -756,7 +764,7 @@ read_a_source_file (name)
                      || (!flag_m68k_mri && *s == '.'))
                    {
                      /* PSEUDO - OP.
-                       
+
                         WARNING: c has next char, which may be end-of-line.
                         We lookup the pseudo-op table with s+1 because we
                         already know that the pseudo-op begins with a '.'.  */
@@ -787,7 +795,7 @@ read_a_source_file (name)
                        {
                          do_align (1, (char *) NULL, 0, 0);
                          mri_pending_align = 0;
-                         
+
                          if (line_label != NULL)
                            {
                              symbol_set_frag (line_label, frag_now);
@@ -798,7 +806,7 @@ read_a_source_file (name)
                      /* Print the error msg now, while we still can.  */
                      if (pop == NULL)
                        {
-                         as_bad (_("Unknown pseudo-op:  `%s'"), s);
+                         as_bad (_("unknown pseudo-op: `%s'"), s);
                          *input_line_pointer = c;
                          s_ignore (0);
                          continue;
@@ -862,7 +870,7 @@ read_a_source_file (name)
                          const char *err;
                          macro_entry *macro;
 
-                         if (check_macro (s, &out, '\0', &err, &macro))
+                         if (check_macro (s, &out, &err, &macro))
                            {
                              if (err != NULL)
                                as_bad ("%s", err);
@@ -905,8 +913,7 @@ read_a_source_file (name)
          if (is_end_of_line[(unsigned char) c])
            continue;
 
-         if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB)
-             && isdigit ((unsigned char) c))
+         if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c))
            {
              /* local label  ("4:")  */
              char *backup = input_line_pointer;
@@ -916,7 +923,7 @@ read_a_source_file (name)
              temp = c - '0';
 
              /* Read the whole number.  */
-             while (isdigit ((unsigned char) *input_line_pointer))
+             while (ISDIGIT (*input_line_pointer))
                {
                  temp = (temp * 10) + *input_line_pointer - '0';
                  ++input_line_pointer;
@@ -951,6 +958,7 @@ read_a_source_file (name)
 
          if (c && strchr (line_comment_chars, c))
            {                   /* Its a comment.  Better say APP or NO_APP.  */
+             sb sbuf;
              char *ends;
              char *new_buf;
              char *new_tmp;
@@ -963,6 +971,7 @@ read_a_source_file (name)
                continue;       /* We ignore it */
              s += 4;
 
+             sb_new (&sbuf);
              ends = strstr (s, "#NO_APP\n");
 
              if (!ends)
@@ -1024,7 +1033,7 @@ read_a_source_file (name)
 
                  if (size < space)
                    {
-                     new_tmp += size;
+                     new_tmp[size] = 0;
                      break;
                    }
 
@@ -1035,13 +1044,19 @@ read_a_source_file (name)
 
              if (tmp_buf)
                free (tmp_buf);
-             old_buffer = buffer;
-             old_input = input_line_pointer;
-             old_limit = buffer_limit;
-             buffer = new_buf;
-             input_line_pointer = new_buf;
-             buffer_limit = new_tmp;
-             
+
+             /* We've "scrubbed" input to the preferred format.  In the
+                process we may have consumed the whole of the remaining
+                file (and included files).  We handle this formatted
+                input similar to that of macro expansion, letting
+                actual macro expansion (possibly nested) and other
+                input expansion work.  Beware that in messages, line
+                numbers and possibly file names will be incorrect.  */
+             sb_add_string (&sbuf, new_buf);
+             input_scrub_include_sb (&sbuf, input_line_pointer, 0);
+             sb_kill (&sbuf);
+             buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+             free (new_buf);
              continue;
            }
 
@@ -1051,28 +1066,14 @@ read_a_source_file (name)
          if (tc_unrecognized_line (c))
            continue;
 #endif
-         /* as_warn (_("Junk character %d."),c); Now done by ignore_rest.  */
-         input_line_pointer--; /* Report unknown char as ignored.  */
+         input_line_pointer--;
+         /* Report unknown char as ignored.  */
          ignore_rest_of_line ();
        }
 
 #ifdef md_after_pass_hook
       md_after_pass_hook ();
 #endif
-
-      if (old_buffer)
-       {
-         free (buffer);
-         bump_line_counters ();
-         if (old_input != 0)
-           {
-             buffer = old_buffer;
-             input_line_pointer = old_input;
-             buffer_limit = old_limit;
-             old_buffer = 0;
-             goto contin;
-           }
-       }
     }
 
  quit:
@@ -1082,6 +1083,13 @@ read_a_source_file (name)
 #endif
   /* Close the input file.  */
   input_scrub_close ();
+#ifdef WARN_COMMENTS
+  {
+    if (warn_comment && found_comment)
+      as_warn_where (found_comment_file, found_comment,
+                    "first comment found here");
+  }
+#endif
 }
 
 /* For most MRI pseudo-ops, the line actually ends at the first
@@ -1118,7 +1126,7 @@ mri_comment_field (stopcp)
 #endif
   *stopcp = *s;
   *s = '\0';
-  
+
   return s;
 }
 
@@ -1157,33 +1165,41 @@ do_align (n, fill, len, max)
      int len;
      int max;
 {
-  char default_fill;
+  if (now_seg == absolute_section)
+    {
+      if (fill != NULL)
+       while (len-- > 0)
+         if (*fill++ != '\0')
+           {
+             as_warn (_("ignoring fill value in absolute section"));
+             break;
+           }
+      fill = NULL;
+      len = 0;
+    }
 
 #ifdef md_do_align
   md_do_align (n, fill, len, max, just_record_alignment);
 #endif
 
-  if (fill == NULL)
-    {
-      if (subseg_text_p (now_seg))
-       default_fill = NOP_OPCODE;
-      else
-       default_fill = 0;
-      fill = &default_fill;
-      len = 1;
-    }
-
   /* Only make a frag if we HAVE to...  */
   if (n != 0 && !need_pass_2)
     {
-      if (len <= 1)
+      if (fill == NULL)
+       {
+         if (subseg_text_p (now_seg))
+           frag_align_code (n, max);
+         else
+           frag_align (n, 0, max);
+       }
+      else if (len <= 1)
        frag_align (n, *fill, max);
       else
        frag_align_pattern (n, fill, len, max);
     }
 
 #ifdef md_do_align
- just_record_alignment:
+ just_record_alignment: ATTRIBUTE_UNUSED_LABEL
 #endif
 
   record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
@@ -1232,8 +1248,8 @@ s_align (arg, bytes_p)
          for (i = 0; (align & 1) == 0; align >>= 1, ++i)
            ;
          if (align != 1)
-           as_bad (_("Alignment not a power of 2"));
-         
+           as_bad (_("alignment not a power of 2"));
+
          align = i;
        }
     }
@@ -1241,7 +1257,7 @@ s_align (arg, bytes_p)
   if (align > 15)
     {
       align = 15;
-      as_bad (_("Alignment too large: %u assumed"), align);
+      as_warn (_("alignment too large: %u assumed"), align);
     }
 
   if (*input_line_pointer != ',')
@@ -1348,46 +1364,56 @@ s_comm (ignore)
   /* Just after name is now '\0'.  */
   p = input_line_pointer;
   *p = c;
+
+  if (name == p)
+    {
+      as_bad (_("expected symbol name"));
+      discard_rest_of_line ();
+      return;
+    }
+
   SKIP_WHITESPACE ();
-  
+
   if (*input_line_pointer != ',')
     {
-      as_bad (_("Expected comma after symbol-name: rest of line ignored."));
+      *p = 0;
+      as_bad (_("expected comma after \"%s\""), name);
+      *p = c;
       ignore_rest_of_line ();
       if (flag_mri)
        mri_comment_end (stop, stopc);
       return;
     }
-  
+
   input_line_pointer++;                /* skip ',' */
-  
+
   if ((temp = get_absolute_expression ()) < 0)
     {
-      as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) temp);
+      as_warn (_(".COMMon length (%ld) < 0 ignored"), (long) temp);
       ignore_rest_of_line ();
       if (flag_mri)
        mri_comment_end (stop, stopc);
       return;
     }
-  
+
   *p = 0;
   symbolP = symbol_find_or_make (name);
   *p = c;
-  
+
   if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP))
     {
-      as_bad (_("Ignoring attempt to re-define symbol `%s'."),
+      as_bad (_("symbol `%s' is already defined"),
              S_GET_NAME (symbolP));
       ignore_rest_of_line ();
       if (flag_mri)
        mri_comment_end (stop, stopc);
       return;
     }
-  
+
   if (S_GET_VALUE (symbolP))
     {
       if (S_GET_VALUE (symbolP) != (valueT) temp)
-       as_bad (_("Length of .comm \"%s\" is already %ld. Not changed to %ld."),
+       as_bad (_("length of .comm \"%s\" is already %ld; not changing to %ld"),
                S_GET_NAME (symbolP),
                (long) S_GET_VALUE (symbolP),
                (long) temp);
@@ -1439,7 +1465,7 @@ s_mri_common (small)
   SKIP_WHITESPACE ();
 
   name = input_line_pointer;
-  if (!isdigit ((unsigned char) *name))
+  if (!ISDIGIT (*name))
     c = get_symbol_end ();
   else
     {
@@ -1447,8 +1473,8 @@ s_mri_common (small)
        {
          ++input_line_pointer;
        }
-      while (isdigit ((unsigned char) *input_line_pointer));
-      
+      while (ISDIGIT (*input_line_pointer));
+
       c = *input_line_pointer;
       *input_line_pointer = '\0';
 
@@ -1477,7 +1503,7 @@ s_mri_common (small)
 
   if (S_IS_DEFINED (sym) && !S_IS_COMMON (sym))
     {
-      as_bad (_("attempt to re-define symbol `%s'"), S_GET_NAME (sym));
+      as_bad (_("symbol `%s' is already defined"), S_GET_NAME (sym));
       ignore_rest_of_line ();
       mri_comment_end (stop, stopc);
       return;
@@ -1547,6 +1573,20 @@ s_data (ignore)
    definition for .file; the APPFILE argument is 1 for .appfile, 0 for
    .file.  */
 
+void
+s_app_file_string (file)
+     char *file;
+{
+#ifdef LISTING
+  if (listing)
+    listing_source_file (file);
+#endif
+  register_dependency (file);
+#ifdef obj_app_file
+  obj_app_file (file);
+#endif
+}
+
 void
 s_app_file (appfile)
      int appfile;
@@ -1572,16 +1612,7 @@ s_app_file (appfile)
 
       demand_empty_rest_of_line ();
       if (!may_omit)
-       {
-#ifdef LISTING
-         if (listing)
-           listing_source_file (s);
-#endif
-         register_dependency (s);
-#ifdef obj_app_file
-         obj_app_file (s);
-#endif
-       }
+       s_app_file_string (s);
     }
 }
 
@@ -1601,7 +1632,7 @@ s_app_line (ignore)
   if (l < 0)
     /* Some of the back ends can't deal with non-positive line numbers.
        Besides, it's silly.  */
-    as_warn (_("Line numbers must be positive; line number %d rejected."),
+    as_warn (_("line numbers must be positive; line number %d rejected"),
             l + 1);
   else
     {
@@ -1697,18 +1728,18 @@ s_fill (ignore)
 #define BSD_FILL_SIZE_CROCK_8 (8)
   if (size > BSD_FILL_SIZE_CROCK_8)
     {
-      as_warn (_(".fill size clamped to %d."), BSD_FILL_SIZE_CROCK_8);
+      as_warn (_(".fill size clamped to %d"), BSD_FILL_SIZE_CROCK_8);
       size = BSD_FILL_SIZE_CROCK_8;
     }
   if (size < 0)
     {
-      as_warn (_("Size negative: .fill ignored."));
+      as_warn (_("size negative; .fill ignored"));
       size = 0;
     }
   else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0)
     {
       if (rep_exp.X_add_number < 0)
-       as_warn (_("Repeat < 0, .fill ignored"));
+       as_warn (_("repeat < 0; .fill ignored"));
       size = 0;
     }
 
@@ -1746,14 +1777,14 @@ s_fill (ignore)
          p = frag_var (rs_space, (int) size, (int) size,
                        (relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0);
        }
-      
+
       memset (p, 0, (unsigned int) size);
-      
+
       /* The magic number BSD_FILL_SIZE_CROCK_4 is from BSD 4.2 VAX
-         flavoured AS.  The following bizzare behaviour is to be
+         flavoured AS.  The following bizarre behaviour is to be
          compatible with above.  I guess they tried to take up to 8
          bytes from a 4-byte expression and they forgot to sign
-         extend. Un*x Sux.  */
+         extend.  */
 #define BSD_FILL_SIZE_CROCK_4 (4)
       md_number_to_chars (p, (valueT) fill,
                          (size > BSD_FILL_SIZE_CROCK_4
@@ -1794,7 +1825,7 @@ s_globl (ignore)
        {
          input_line_pointer++;
          SKIP_WHITESPACE ();
-         if (*input_line_pointer == '\n')
+         if (is_end_of_line[(unsigned char) *input_line_pointer])
            c = '\n';
        }
     }
@@ -1826,7 +1857,7 @@ s_irp (irpc)
 
   sb_new (&out);
 
-  err = expand_irp (irpc, 0, &s, &out, get_line_sb, '\0');
+  err = expand_irp (irpc, 0, &s, &out, get_line_sb);
   if (err != NULL)
     as_bad_where (file, line, "%s", err);
 
@@ -1938,6 +1969,14 @@ s_lcomm_internal (needs_align, bytes_p)
   c = get_symbol_end ();
   p = input_line_pointer;
   *p = c;
+
+  if (name == p)
+    {
+      as_bad (_("expected symbol name"));
+      discard_rest_of_line ();
+      return;
+    }
+
   SKIP_WHITESPACE ();
 
   /* Accept an optional comma after the name.  The comma used to be
@@ -1948,15 +1987,15 @@ s_lcomm_internal (needs_align, bytes_p)
       SKIP_WHITESPACE ();
     }
 
-  if (*input_line_pointer == '\n')
+  if (is_end_of_line[(unsigned char) *input_line_pointer])
     {
-      as_bad (_("Missing size expression"));
+      as_bad (_("missing size expression"));
       return;
     }
 
   if ((temp = get_absolute_expression ()) < 0)
     {
-      as_warn (_("BSS length (%d.) <0! Ignored."), temp);
+      as_warn (_("BSS length (%d) < 0 ignored"), temp);
       ignore_rest_of_line ();
       return;
     }
@@ -1966,7 +2005,7 @@ s_lcomm_internal (needs_align, bytes_p)
       || OUTPUT_FLAVOR == bfd_target_elf_flavour)
     {
       /* For MIPS and Alpha ECOFF or ELF, small objects are put in .sbss.  */
-      if (temp <= bfd_get_gp_size (stdoutput))
+      if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
        {
          bss_seg = subseg_new (".sbss", 1);
          seg_info (bss_seg)->bss = 1;
@@ -1992,25 +2031,25 @@ s_lcomm_internal (needs_align, bytes_p)
     {
       align = 0;
       SKIP_WHITESPACE ();
-      
+
       if (*input_line_pointer != ',')
        {
-         as_bad (_("Expected comma after size"));
+         as_bad (_("expected comma after size"));
          ignore_rest_of_line ();
          return;
        }
-      
+
       input_line_pointer++;
       SKIP_WHITESPACE ();
-      
-      if (*input_line_pointer == '\n')
+
+      if (is_end_of_line[(unsigned char) *input_line_pointer])
        {
-         as_bad (_("Missing alignment"));
+         as_bad (_("missing alignment"));
          return;
        }
-      
+
       align = get_absolute_expression ();
-      
+
       if (bytes_p)
        {
          /* Convert to a power of 2.  */
@@ -2021,22 +2060,22 @@ s_lcomm_internal (needs_align, bytes_p)
              for (i = 0; (align & 1) == 0; align >>= 1, ++i)
                ;
              if (align != 1)
-               as_bad (_("Alignment not a power of 2"));
+               as_bad (_("alignment not a power of 2"));
              align = i;
            }
        }
-      
+
       if (align > max_alignment)
        {
          align = max_alignment;
-         as_warn (_("Alignment too large: %d. assumed."), align);
+         as_warn (_("alignment too large; %d assumed"), align);
        }
       else if (align < 0)
        {
          align = 0;
-         as_warn (_("Alignment negative. 0 assumed."));
+         as_warn (_("alignment negative; 0 assumed"));
        }
-      
+
       record_alignment (bss_seg, align);
     }
   else
@@ -2075,8 +2114,8 @@ s_lcomm_internal (needs_align, bytes_p)
 
       if (align)
        frag_align (align, 0, 0);
-      
-      /* Detach from old frag. */
+
+      /* Detach from old frag.  */
       if (S_GET_SEGMENT (symbolP) == bss_seg)
        symbol_get_frag (symbolP)->fr_symbol = NULL;
 
@@ -2102,8 +2141,7 @@ s_lcomm_internal (needs_align, bytes_p)
 #endif
     }
   else
-    as_bad (_("Ignoring attempt to re-define symbol `%s'."),
-           S_GET_NAME (symbolP));
+    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
 
   subseg_set (current_seg, current_subseg);
 
@@ -2139,20 +2177,28 @@ s_lsym (ignore)
   c = get_symbol_end ();
   p = input_line_pointer;
   *p = c;
+
+  if (name == p)
+    {
+      as_bad (_("expected symbol name"));
+      discard_rest_of_line ();
+      return;
+    }
+
   SKIP_WHITESPACE ();
-  
+
   if (*input_line_pointer != ',')
     {
       *p = 0;
-      as_bad (_("Expected comma after name \"%s\""), name);
+      as_bad (_("expected comma after \"%s\""), name);
       *p = c;
       ignore_rest_of_line ();
       return;
     }
-  
+
   input_line_pointer++;
   expression (&exp);
-  
+
   if (exp.X_op != O_constant
       && exp.X_op != O_register)
     {
@@ -2160,7 +2206,7 @@ s_lsym (ignore)
       ignore_rest_of_line ();
       return;
     }
-  
+
   *p = 0;
   symbolP = symbol_find_or_make (name);
 
@@ -2184,20 +2230,22 @@ s_lsym (ignore)
     }
   else
     {
-      as_bad (_("Symbol %s already defined"), name);
+      as_bad (_("symbol `%s' is already defined"), name);
     }
-  
+
   *p = c;
   demand_empty_rest_of_line ();
 }
 
-/* Read a line into an sb.  */
+/* Read a line into an sb.  Returns the character that ended the line
+   or zero if there are no more lines.  */
 
 static int
 get_line_sb (line)
      sb *line;
 {
   char quote1, quote2, inquote;
+  unsigned char c;
 
   if (input_line_pointer[-1] == '\n')
     bump_line_counters ();
@@ -2224,36 +2272,33 @@ get_line_sb (line)
 #endif
 
   inquote = '\0';
-  
-  while (!is_end_of_line[(unsigned char) *input_line_pointer]
-        || (inquote != '\0' && *input_line_pointer != '\n'))
+
+  while ((c = * input_line_pointer ++) != 0
+        && (!is_end_of_line[c]
+            || (inquote != '\0' && c != '\n')))
     {
-      if (inquote == *input_line_pointer)
+      if (inquote == c)
        inquote = '\0';
       else if (inquote == '\0')
        {
-         if (*input_line_pointer == quote1)
+         if (c == quote1)
            inquote = quote1;
-         else if (*input_line_pointer == quote2)
+         else if (c == quote2)
            inquote = quote2;
        }
-      
-      sb_add_char (line, *input_line_pointer++);
-    }
-  
-  while (input_line_pointer < buffer_limit
-        && is_end_of_line[(unsigned char) *input_line_pointer])
-    {
-      if (input_line_pointer[-1] == '\n')
-       bump_line_counters ();
-      ++input_line_pointer;
+
+      sb_add_char (line, c);
     }
-  
-  return 1;
+
+  /* Don't skip multiple end-of-line characters, because that breaks support
+     for the IA-64 stop bit (;;) which looks like two consecutive end-of-line
+     characters but isn't.  Instead just skip one end of line character and
+     return the character skipped so that the caller can re-insert it if
+     necessary.   */
+  return c;
 }
 
-/* Define a macro.  This is an interface to macro.c, which is shared
-   between gas and gasp.  */
+/* Define a macro.  This is an interface to macro.c.  */
 
 void
 s_macro (ignore)
@@ -2359,8 +2404,7 @@ do_org (segment, exp, fill)
      int fill;
 {
   if (segment != now_seg && segment != absolute_section)
-    as_bad (_("invalid segment \"%s\"; segment \"%s\" assumed"),
-           segment_name (segment), segment_name (now_seg));
+    as_bad (_("invalid segment \"%s\""), segment_name (segment));
 
   if (now_seg == absolute_section)
     {
@@ -2376,9 +2420,17 @@ do_org (segment, exp, fill)
   else
     {
       char *p;
+      symbolS *sym = exp->X_add_symbol;
+      offsetT off = exp->X_add_number * OCTETS_PER_BYTE;
+
+      if (exp->X_op != O_constant && exp->X_op != O_symbol)
+       {
+         /* Handle complex expressions.  */
+         sym = make_expr_symbol (exp);
+         off = 0;
+       }
 
-      p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp->X_add_symbol,
-                   exp->X_add_number * OCTETS_PER_BYTE, (char *) NULL);
+      p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0);
       *p = fill;
     }
 }
@@ -2452,7 +2504,7 @@ s_mri_sect (type)
   SKIP_WHITESPACE ();
 
   name = input_line_pointer;
-  if (!isdigit ((unsigned char) *name))
+  if (!ISDIGIT (*name))
     c = get_symbol_end ();
   else
     {
@@ -2460,8 +2512,8 @@ s_mri_sect (type)
        {
          ++input_line_pointer;
        }
-      while (isdigit ((unsigned char) *input_line_pointer));
-      
+      while (ISDIGIT (*input_line_pointer));
+
       c = *input_line_pointer;
       *input_line_pointer = '\0';
     }
@@ -2485,7 +2537,7 @@ s_mri_sect (type)
   if (*input_line_pointer == ',')
     {
       c = *++input_line_pointer;
-      c = toupper ((unsigned char) c);
+      c = TOUPPER (c);
       if (c == 'C' || c == 'D' || c == 'M' || c == 'R')
        *type = c;
       else
@@ -2648,6 +2700,16 @@ s_purgem (ignore)
 
 /* Handle the .rept pseudo-op.  */
 
+void
+s_bad_endr (ignore)
+     int ignore ATTRIBUTE_UNUSED;
+{
+  as_warn (_(".endr encountered without preceeding .rept, .irc, or .irp"));
+  demand_empty_rest_of_line ();
+}
+
+/* Handle the .rept pseudo-op.  */
+
 void
 s_rept (ignore)
      int ignore ATTRIBUTE_UNUSED;
@@ -2726,12 +2788,20 @@ s_set (equiv)
   delim = get_symbol_end ();
   end_name = input_line_pointer;
   *end_name = delim;
+
+  if (name == end_name)
+    {
+      as_bad (_("expected symbol name"));
+      discard_rest_of_line ();
+      return;
+    }
+
   SKIP_WHITESPACE ();
 
   if (*input_line_pointer != ',')
     {
       *end_name = 0;
-      as_bad (_("Expected comma after name \"%s\""), name);
+      as_bad (_("expected comma after \"%s\""), name);
       *end_name = delim;
       ignore_rest_of_line ();
       return;
@@ -2789,7 +2859,7 @@ s_set (equiv)
   if (equiv
       && S_IS_DEFINED (symbolP)
       && S_GET_SEGMENT (symbolP) != reg_section)
-    as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
+    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
 
   pseudo_set (symbolP);
   demand_empty_rest_of_line ();
@@ -2875,7 +2945,7 @@ s_space (mult)
       || (mult != 0 && mult != 1 && val.X_add_number != 0))
     {
       if (exp.X_op != O_constant)
-       as_bad (_("Unsupported variable size or fill value"));
+       as_bad (_("unsupported variable size or fill value"));
       else
        {
          offsetT i;
@@ -2934,13 +3004,13 @@ s_space (mult)
              as_bad (_("space allocation too complex in absolute section"));
              subseg_set (text_section, 0);
            }
-         
+
          if (mri_common_symbol != NULL)
            {
              as_bad (_("space allocation too complex in common section"));
              mri_common_symbol = NULL;
            }
-         
+
          if (!need_pass_2)
            p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
                          make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
@@ -3000,7 +3070,7 @@ s_float_space (float_type)
   /* Skip any 0{letter} that may be present.  Don't even check if the
    * letter is legal.  */
   if (input_line_pointer[0] == '0'
-      && isalpha ((unsigned char) input_line_pointer[1]))
+      && ISALPHA (input_line_pointer[1]))
     input_line_pointer += 2;
 
   /* Accept :xxxx, where the x's are hex digits, for a floating point
@@ -3025,7 +3095,7 @@ s_float_space (float_type)
       know (flen > 0);
       if (err)
        {
-         as_bad (_("Bad floating literal: %s"), err);
+         as_bad (_("bad floating literal: %s"), err);
          ignore_rest_of_line ();
          if (flag_mri)
            mri_comment_end (stop, stopc);
@@ -3097,18 +3167,18 @@ ignore_rest_of_line ()
   /* For suspect lines: gives warning.  */
   if (!is_end_of_line[(unsigned char) *input_line_pointer])
     {
-      if (isprint ((unsigned char) *input_line_pointer))
-       as_bad (_("Rest of line ignored. First ignored character is `%c'."),
-               *input_line_pointer);
+      if (ISPRINT (*input_line_pointer))
+       as_warn (_("rest of line ignored; first ignored character is `%c'"),
+                *input_line_pointer);
       else
-       as_bad (_("Rest of line ignored. First ignored character valued 0x%x."),
-               *input_line_pointer);
-      
+       as_warn (_("rest of line ignored; first ignored character valued 0x%x"),
+                *input_line_pointer);
+
       while (input_line_pointer < buffer_limit
             && !is_end_of_line[(unsigned char) *input_line_pointer])
        input_line_pointer++;
     }
-  
+
   input_line_pointer++;
 
   /* Return pointing just after end-of-line.  */
@@ -3123,14 +3193,14 @@ discard_rest_of_line ()
     input_line_pointer++;
 
   input_line_pointer++;
-  
+
   /* Return pointing just after end-of-line.  */
   know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
 }
 
 /* In: Pointer to a symbol.
        Input_line_pointer->expression.
-  
+
    Out:        Input_line_pointer->just after any whitespace after expression.
        Tried to set symbol to value of expression.
        Will change symbols type, value, and frag;  */
@@ -3152,19 +3222,17 @@ pseudo_set (symbolP)
   (void) expression (&exp);
 
   if (exp.X_op == O_illegal)
-    as_bad (_("illegal expression; zero assumed"));
+    as_bad (_("illegal expression"));
   else if (exp.X_op == O_absent)
-    as_bad (_("missing expression; zero assumed"));
+    as_bad (_("missing expression"));
   else if (exp.X_op == O_big)
     {
       if (exp.X_add_number > 0)
-       as_bad (_("bignum invalid; zero assumed"));
+       as_bad (_("bignum invalid"));
       else
-       as_bad (_("floating point number invalid; zero assumed"));
+       as_bad (_("floating point number invalid"));
     }
   else if (exp.X_op == O_subtract
-          && (S_GET_SEGMENT (exp.X_add_symbol)
-              == S_GET_SEGMENT (exp.X_op_symbol))
           && SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
           && (symbol_get_frag (exp.X_add_symbol)
               == symbol_get_frag (exp.X_op_symbol)))
@@ -3205,7 +3273,7 @@ pseudo_set (symbolP)
          || exp.X_add_number != 0)
        symbol_set_value_expression (symbolP, &exp);
       else if (symbol_section_p (symbolP))
-       as_bad ("invalid attempt to set value of section symbol");
+       as_bad ("attempt to set value of section symbol");
       else
        {
          symbolS *s = exp.X_add_symbol;
@@ -3233,13 +3301,13 @@ pseudo_set (symbolP)
 }
 \f
 /*                     cons()
-  
+
    CONStruct more frag of .bytes, or .words etc.
    Should need_pass_2 be 1 then emit no frag(s).
    This understands EXPRESSIONS.
-  
+
    Bug (?)
-  
+
    This has a split personality. We use expression() to read the
    value. We can detect if the value won't fit in a byte or word.
    But we can't detect if expression() discarded significant digits
@@ -3493,7 +3561,7 @@ emit_expr (exp, nbytes)
     }
   else if (op == O_big && exp->X_add_number <= 0)
     {
-      as_bad (_("floating point number invalid; zero assumed"));
+      as_bad (_("floating point number invalid"));
       exp->X_add_number = 0;
       op = O_constant;
     }
@@ -3524,6 +3592,7 @@ emit_expr (exp, nbytes)
       x->sub = exp->X_op_symbol;
       x->addnum = exp->X_add_number;
       x->added = 0;
+      x->use_jump = 0;
       new_broken_words++;
       return;
     }
@@ -3589,7 +3658,7 @@ emit_expr (exp, nbytes)
          && ((get & mask) != mask
              || (get & hibit) == 0))
        {               /* Leading bits contain both 0s & 1s.  */
-         as_warn (_("Value 0x%lx truncated to 0x%lx."),
+         as_warn (_("value 0x%lx truncated to 0x%lx"),
                   (unsigned long) get, (unsigned long) use);
        }
       /* Put bytes in right order.  */
@@ -3605,7 +3674,7 @@ emit_expr (exp, nbytes)
       size = exp->X_add_number * CHARS_PER_LITTLENUM;
       if (nbytes < size)
        {
-         as_warn (_("Bignum truncated to %d bytes"), nbytes);
+         as_warn (_("bignum truncated to %d bytes"), nbytes);
          size = nbytes;
        }
 
@@ -3619,7 +3688,7 @@ emit_expr (exp, nbytes)
            }
 
          nums = generic_bignum + size / CHARS_PER_LITTLENUM;
-         while (size > 0)
+         while (size >= CHARS_PER_LITTLENUM)
            {
              --nums;
              md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
@@ -3630,7 +3699,7 @@ emit_expr (exp, nbytes)
       else
        {
          nums = generic_bignum;
-         while (size > 0)
+         while (size >= CHARS_PER_LITTLENUM)
            {
              md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
              ++nums;
@@ -3639,7 +3708,7 @@ emit_expr (exp, nbytes)
              nbytes -= CHARS_PER_LITTLENUM;
            }
 
-         while (nbytes > 0)
+         while (nbytes >= CHARS_PER_LITTLENUM)
            {
              md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
              nbytes -= CHARS_PER_LITTLENUM;
@@ -3801,7 +3870,8 @@ parse_bitfield_cons (exp, nbytes)
              break;
            }                   /* Won't fit.  */
 
-         hold = ++input_line_pointer; /* skip ':' */
+         /* Skip ':'.  */
+         hold = ++input_line_pointer;
 
          (void) expression (exp);
          if (exp->X_op != O_constant)
@@ -3887,11 +3957,11 @@ parse_mri_cons (exp, nbytes)
          result <<= 8;
          scan++;
        }
-      
+
       /* Create correct expression.  */
       exp->X_op = O_constant;
       exp->X_add_number = result;
-      
+
       /* Fake it so that we can read the next char too.  */
       if (input_line_pointer[0] != '\'' ||
          (input_line_pointer[0] == '\'' && input_line_pointer[1] == '\''))
@@ -3935,7 +4005,7 @@ parse_repeat_cons (exp, nbytes)
   if (count.X_op != O_constant
       || count.X_add_number <= 0)
     {
-      as_warn (_("Unresolvable or nonpositive repeat count; using 1"));
+      as_warn (_("unresolvable or nonpositive repeat count; using 1"));
       return;
     }
 
@@ -3986,7 +4056,7 @@ hex_float (float_type, bytes)
       break;
 
     default:
-      as_bad (_("Unknown floating type type '%c'"), float_type);
+      as_bad (_("unknown floating type type '%c'"), float_type);
       return -1;
     }
 
@@ -4008,7 +4078,7 @@ hex_float (float_type, bytes)
 
       if (i >= length)
        {
-         as_warn (_("Floating point constant too large"));
+         as_warn (_("floating point constant too large"));
          return -1;
        }
       d = hex_value (*input_line_pointer) << 4;
@@ -4039,12 +4109,12 @@ hex_float (float_type, bytes)
 }
 
 /*                     float_cons()
-  
+
    CONStruct some more frag chars of .floats .ffloats etc.
    Makes 0 or more new frags.
    If need_pass_2 == 1, no frags are emitted.
    This understands only floating literals, not expressions. Sorry.
-  
+
    A floating constant is defined by atof_generic(), except it is preceded
    by 0d 0f 0g or 0h. After observing the STRANGE way my BSD AS does its
    reading, I decided to be incompatible. This always tries to give you
@@ -4052,7 +4122,7 @@ hex_float (float_type, bytes)
    truncatation, restored noisy bits instead of trailing 0s AND gave you
    a choice of 2 flavours of noise according to which of 2 floating-point
    scanners you directed AS to use.
-  
+
    In: input_line_pointer->whitespace before, or '0' of flonum.  */
 
 void
@@ -4085,7 +4155,7 @@ float_cons (float_type)
          has no use for such information. Lusers beware: you get
          diagnostics if your input is ill-conditioned.  */
       if (input_line_pointer[0] == '0'
-         && isalpha ((unsigned char) input_line_pointer[1]))
+         && ISALPHA (input_line_pointer[1]))
        input_line_pointer += 2;
 
       /* Accept :xxxx, where the x's are hex digits, for a floating
@@ -4107,7 +4177,7 @@ float_cons (float_type)
          know (length > 0);
          if (err)
            {
-             as_bad (_("Bad floating literal: %s"), err);
+             as_bad (_("bad floating literal: %s"), err);
              ignore_rest_of_line ();
              return;
            }
@@ -4126,7 +4196,7 @@ float_cons (float_type)
 
              ++input_line_pointer;
              expression (&count_exp);
-             
+
              if (count_exp.X_op != O_constant
                  || count_exp.X_add_number <= 0)
                as_warn (_("unresolvable or nonpositive repeat count; using 1"));
@@ -4381,6 +4451,7 @@ emit_leb128_expr (exp, sign)
      int sign;
 {
   operatorT op = exp->X_op;
+  int nbytes;
 
   if (op == O_absent || op == O_illegal)
     {
@@ -4390,7 +4461,7 @@ emit_leb128_expr (exp, sign)
     }
   else if (op == O_big && exp->X_add_number <= 0)
     {
-      as_bad (_("floating point number invalid; zero assumed"));
+      as_bad (_("floating point number invalid"));
       exp->X_add_number = 0;
       op = O_constant;
     }
@@ -4400,6 +4471,17 @@ emit_leb128_expr (exp, sign)
       op = O_constant;
     }
 
+  /* 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;
+  if (check_eh_frame (exp, &nbytes))
+    abort ();
+
+  /* Let the backend know that subsequent data may be byte aligned.  */
+#ifdef md_cons_align
+  md_cons_align (1);
+#endif
+
   if (op == O_constant)
     {
       /* If we've got a constant, emit the thing directly right now.  */
@@ -4482,6 +4564,15 @@ stringer (append_zero)           /* Worker to do .ascii etc statements.  */
     {
       c = ',';                 /* Do loop.  */
     }
+  /* If we have been switched into the abs_section then we
+     will not have an obstack onto which we can hang strings.  */
+  if (now_seg == absolute_section)
+    {
+      as_bad (_("strings must be placed into a section"));
+      c = 0;
+      ignore_rest_of_line ();
+    }
+  
   while (c == ',' || c == '<' || c == '"')
     {
       SKIP_WHITESPACE ();
@@ -4527,7 +4618,7 @@ stringer (append_zero)            /* Worker to do .ascii etc statements.  */
          FRAG_APPEND_1_CHAR (c);
          if (*input_line_pointer != '>')
            {
-             as_bad (_("Expected <nn>"));
+             as_bad (_("expected <nn>"));
            }
          input_line_pointer++;
          break;
@@ -4560,7 +4651,7 @@ next_char_of_string ()
       break;
 
     case '\n':
-      as_warn (_("Unterminated string: Newline inserted."));
+      as_warn (_("unterminated string; newline inserted"));
       bump_line_counters ();
       break;
 
@@ -4611,12 +4702,12 @@ next_char_of_string ()
            int i;
 
            for (i = 0, number = 0;
-                isdigit (c) && i < 3;
+                ISDIGIT (c) && i < 3;
                 c = *input_line_pointer++, i++)
              {
                number = number * 8 + c - '0';
              }
-           
+
            c = number & 0xff;
          }
          --input_line_pointer;
@@ -4629,11 +4720,11 @@ next_char_of_string ()
 
            number = 0;
            c = *input_line_pointer++;
-           while (isxdigit (c))
+           while (ISXDIGIT (c))
              {
-               if (isdigit (c))
+               if (ISDIGIT (c))
                  number = number * 16 + c - '0';
-               else if (isupper (c))
+               else if (ISUPPER (c))
                  number = number * 16 + c - 'A' + 10;
                else
                  number = number * 16 + c - 'a' + 10;
@@ -4646,7 +4737,7 @@ next_char_of_string ()
 
        case '\n':
          /* To be compatible with BSD 4.2 as: give the luser a linefeed!!  */
-         as_warn (_("Unterminated string: Newline inserted."));
+         as_warn (_("unterminated string; newline inserted"));
          c = '\n';
          bump_line_counters ();
          break;
@@ -4654,7 +4745,7 @@ next_char_of_string ()
        default:
 
 #ifdef ONLY_STANDARD_ESCAPES
-         as_bad (_("Bad escaped character in string, '?' assumed"));
+         as_bad (_("bad escaped character in string"));
          c = '?';
 #endif /* ONLY_STANDARD_ESCAPES */
 
@@ -4680,7 +4771,7 @@ get_segmented_expression (expP)
       || expP->X_op == O_absent
       || expP->X_op == O_big)
     {
-      as_bad (_("expected address expression; zero assumed"));
+      as_bad (_("expected address expression"));
       expP->X_op = O_constant;
       expP->X_add_number = 0;
       retval = absolute_section;
@@ -4712,19 +4803,26 @@ get_known_segmented_expression (expP)
   return (retval);
 }
 
+offsetT
+get_absolute_expr (exp)
+     expressionS *exp;
+{
+  expression (exp);
+  if (exp->X_op != O_constant)
+    {
+      if (exp->X_op != O_absent)
+       as_bad (_("bad or irreducible absolute expression"));
+      exp->X_add_number = 0;
+    }
+  return exp->X_add_number;
+}
+
 offsetT
 get_absolute_expression ()
 {
   expressionS exp;
 
-  expression (&exp);
-  if (exp.X_op != O_constant)
-    {
-      if (exp.X_op != O_absent)
-       as_bad (_("bad or irreducible absolute expression; zero assumed"));
-      exp.X_add_number = 0;
-    }
-  return exp.X_add_number;
+  return get_absolute_expr (&exp);
 }
 
 char                           /* Return terminator.  */
@@ -4756,11 +4854,11 @@ demand_copy_C_string (len_pointer)
              s = 0;
              len = 1;
              *len_pointer = 0;
-             as_bad (_("This string may not contain \'\\0\'"));
+             as_bad (_("this string may not contain \'\\0\'"));
            }
        }
     }
-  
+
   return s;
 }
 \f
@@ -4793,7 +4891,7 @@ demand_copy_string (lenP)
     }
   else
     {
-      as_warn (_("Missing string"));
+      as_warn (_("missing string"));
       retval = NULL;
       ignore_rest_of_line ();
     }
@@ -4802,9 +4900,9 @@ demand_copy_string (lenP)
 }
 \f
 /* In: Input_line_pointer->next character.
-  
+
    Do: Skip input_line_pointer over all whitespace.
-  
+
    Out:        1 if input_line_pointer->end-of-line.  */
 
 int
@@ -4845,12 +4943,26 @@ equals (sym_name, reassign)
     }
   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' already defined"), S_GET_NAME (symbolP));
+       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);
     }
 
@@ -4862,6 +4974,123 @@ equals (sym_name, reassign)
     }
 }
 
+/* .incbin -- include a file verbatim at the current location.  */
+
+void
+s_incbin (x)
+     int x ATTRIBUTE_UNUSED;
+{
+  FILE * binfile;
+  char * path;
+  char * filename;
+  char * binfrag;
+  long   skip = 0;
+  long   count = 0;
+  long   bytes;
+  int    len;
+
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
+
+  SKIP_WHITESPACE ();
+  filename = demand_copy_string (& len);
+  if (filename == NULL)
+    return;
+
+  SKIP_WHITESPACE ();
+
+  /* Look for optional skip and count.  */
+  if (* input_line_pointer == ',')
+    {
+      ++ input_line_pointer;
+      skip = get_absolute_expression ();
+
+      SKIP_WHITESPACE ();
+
+      if (* input_line_pointer == ',')
+       {
+         ++ input_line_pointer;
+
+         count = get_absolute_expression ();
+         if (count == 0)
+           as_warn (_(".incbin count zero, ignoring `%s'"), filename);
+
+         SKIP_WHITESPACE ();
+       }
+    }
+
+  demand_empty_rest_of_line ();
+
+  /* Try opening absolute path first, then try include dirs.  */
+  binfile = fopen (filename, FOPEN_RB);
+  if (binfile == NULL)
+    {
+      int i;
+
+      path = xmalloc ((unsigned long) len + include_dir_maxlen + 5);
+
+      for (i = 0; i < include_dir_count; i++)
+       {
+         sprintf (path, "%s/%s", include_dirs[i], filename);
+
+         binfile = fopen (path, FOPEN_RB);
+         if (binfile != NULL)
+           break;
+       }
+
+      if (binfile == NULL)
+       as_bad (_("file not found: %s"), filename);
+    }
+  else
+    path = xstrdup (filename);
+
+  if (binfile)
+    {
+      long   file_len;
+
+      register_dependency (path);
+
+      /* Compute the length of the file.  */
+      if (fseek (binfile, 0, SEEK_END) != 0)
+       {
+         as_bad (_("seek to end of .incbin file failed `%s'"), path);
+         goto done;
+       }
+      file_len = ftell (binfile);
+
+      /* If a count was not specified use the size of the file.  */
+      if (count == 0)
+       count = file_len;
+
+      if (skip + count > file_len)
+       {
+         as_bad (_("skip (%ld) + count (%ld) larger than file size (%ld)"),
+                 skip, count, file_len);
+         goto done;
+       }
+
+      if (fseek (binfile, skip, SEEK_SET) != 0)
+       {
+         as_bad (_("could not skip to %ld in file `%s'"), skip, path);
+         goto done;
+       }
+
+      /* Allocate frag space and store file contents in it.  */
+      binfrag = frag_more (count);
+
+      bytes = fread (binfrag, 1, count, binfile);
+      if (bytes < count)
+       as_warn (_("truncated file `%s', %ld of %ld bytes read"),
+                path, bytes, count);
+    }
+done:
+  if (binfile != NULL)
+    fclose (binfile);
+  if (path)
+    free (path);
+}
+
 /* .include -- include a file at this point.  */
 
 void
@@ -4895,28 +5124,28 @@ s_include (arg)
          ++input_line_pointer;
          ++i;
        }
-      
+
       obstack_1grow (&notes, '\0');
       filename = obstack_finish (&notes);
       while (!is_end_of_line[(unsigned char) *input_line_pointer])
        ++input_line_pointer;
     }
-  
+
   demand_empty_rest_of_line ();
   path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 /* slop */ );
-  
+
   for (i = 0; i < include_dir_count; i++)
     {
       strcpy (path, include_dirs[i]);
       strcat (path, "/");
       strcat (path, filename);
-      if (0 != (try = fopen (path, "r")))
+      if (0 != (try = fopen (path, FOPEN_RT)))
        {
          fclose (try);
          goto gotit;
        }
     }
-  
+
   free (path);
   path = filename;
 gotit:
@@ -4966,22 +5195,11 @@ generate_file_debug ()
 void
 generate_lineno_debug ()
 {
-#ifdef ECOFF_DEBUGGING
-  /* ECOFF assemblers automatically generate debugging information.
-     FIXME: This should probably be handled elsewhere.  */
-  if (debug_type == DEBUG_UNSPECIFIED)
-    {
-      if (ECOFF_DEBUGGING && ecoff_no_current_file ())
-       debug_type = DEBUG_ECOFF;
-      else
-       debug_type = DEBUG_NONE;
-    }
-#endif
-
   switch (debug_type)
     {
     case DEBUG_UNSPECIFIED:
     case DEBUG_NONE:
+    case DEBUG_DWARF:
       break;
     case DEBUG_STABS:
       stabs_generate_asm_lineno ();
@@ -4989,9 +5207,11 @@ generate_lineno_debug ()
     case DEBUG_ECOFF:
       ecoff_generate_asm_lineno ();
       break;
-    case DEBUG_DWARF:
     case DEBUG_DWARF2:
-      /* FIXME.  */
+      /* ??? We could here indicate to dwarf2dbg.c that something
+        has changed.  However, since there is additional backend
+        support that is required (calling dwarf2_emit_insn), we
+        let dwarf2dbg.c call as_where on its own.  */
       break;
     }
 }
This page took 0.047111 seconds and 4 git commands to generate.