* dlltool.c (dump_iat): Remove unused function.
[deliverable/binutils-gdb.git] / gas / read.c
index 430a67e3c5d4146cd06d05fd27f91bce6db6d1d9..daea0f9a071fda41c92f226c75d2fa785d168298 100644 (file)
@@ -1,6 +1,7 @@
 /* read.c - read a source file -
    Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
 
 This file is part of GAS, the GNU Assembler.
 
@@ -216,6 +217,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 int hex_float (int, char *);
 static segT get_known_segmented_expression (expressionS * expP);
 static void pobegin (void);
@@ -251,6 +253,7 @@ static struct hash_control *po_hash;
 static const pseudo_typeS potable[] = {
   {"abort", s_abort, 0},
   {"align", s_align_ptwo, 0},
+  {"altmacro", s_altmacro, 1},
   {"ascii", stringer, 0},
   {"asciz", stringer, 1},
   {"balign", s_align_bytes, 0},
@@ -304,6 +307,7 @@ static const pseudo_typeS potable[] = {
   {"equ", s_set, 0},
   {"equiv", s_set, 1},
   {"err", s_err, 0},
+  {"error", s_errwarn, 1},
   {"exitm", s_mexit, 0},
 /* extend  */
   {"extern", s_ignore, 0},     /* We treat all undef as ext.  */
@@ -351,6 +355,7 @@ static const pseudo_typeS potable[] = {
   {"mri", s_mri, 0},
   {".mri", s_mri, 0},  /* Special case so .mri works in MRI mode.  */
   {"name", s_ignore, 0},
+  {"noaltmacro", s_altmacro, 0},
   {"noformat", s_ignore, 0},
   {"nolist", listing_list, 0}, /* Turn listing off.  */
   {"nopage", listing_nopage, 0},
@@ -408,6 +413,7 @@ static const pseudo_typeS potable[] = {
   {"xdef", s_globl, 0},
   {"xref", s_ignore, 0},
   {"xstabs", s_xstab, 's'},
+  {"warning", s_errwarn, 0},
   {"word", cons, 2},
   {"zero", s_space, 0},
   {NULL, NULL, 0}                      /* End sentinel.  */
@@ -1077,6 +1083,29 @@ read_a_source_file (char *name)
 #endif
 }
 
+/* Convert O_constant expression EXP into the equivalent O_big representation.
+   Take the sign of the number from X_unsigned rather than X_add_number.  */
+
+static void
+convert_to_bignum (expressionS *exp)
+{
+  valueT value;
+  unsigned int i;
+
+  value = exp->X_add_number;
+  for (i = 0; i < sizeof (exp->X_add_number) / CHARS_PER_LITTLENUM; i++)
+    {
+      generic_bignum[i] = value & LITTLENUM_MASK;
+      value >>= LITTLENUM_NUMBER_OF_BITS;
+    }
+  /* Add a sequence of sign bits if the top bit of X_add_number is not
+     the sign of the original value.  */
+  if ((exp->X_add_number < 0) != !exp->X_unsigned)
+    generic_bignum[i++] = exp->X_unsigned ? 0 : LITTLENUM_MASK;
+  exp->X_op = O_big;
+  exp->X_add_number = i;
+}
+
 /* For most MRI pseudo-ops, the line actually ends at the first
    nonquoted space.  This function looks for that point, stuffs a null
    in, and sets *STOPCP to the character that used to be there, and
@@ -1155,6 +1184,9 @@ do_align (int n, char *fill, int len, int max)
       len = 0;
     }
 
+#ifdef md_flush_pending_output
+  md_flush_pending_output ();
+#endif
 #ifdef md_do_align
   md_do_align (n, fill, len, max, just_record_alignment);
 #endif
@@ -1187,10 +1219,17 @@ do_align (int n, char *fill, int len, int max)
    fill pattern.  BYTES_P is non-zero if the alignment value should be
    interpreted as the byte boundary, rather than the power of 2.  */
 
+#ifdef BFD_ASSEMBLER
+#define ALIGN_LIMIT (stdoutput->arch_info->bits_per_address - 1)
+#else
+#define ALIGN_LIMIT 15
+#endif
+
 static void
 s_align (int arg, int bytes_p)
 {
-  register unsigned int align;
+  unsigned int align_limit = ALIGN_LIMIT;
+  unsigned int align;
   char *stop = NULL;
   char stopc;
   offsetT fill = 0;
@@ -1229,9 +1268,9 @@ s_align (int arg, int bytes_p)
        }
     }
 
-  if (align > 15)
+  if (align > align_limit)
     {
-      align = 15;
+      align = align_limit;
       as_warn (_("alignment too large: %u assumed"), align);
     }
 
@@ -1317,6 +1356,15 @@ s_align_ptwo (int arg)
   s_align (arg, 0);
 }
 
+/* Switch in and out of alternate macro mode.  */
+
+void
+s_altmacro (int on)
+{
+  demand_empty_rest_of_line ();
+  macro_set_alternate (on);
+}
+
 symbolS *
 s_comm_internal (int param,
                 symbolS *(*comm_parse_extra) (int, symbolS *, addressT))
@@ -1353,7 +1401,6 @@ s_comm_internal (int param,
   if (*input_line_pointer == ',')
     input_line_pointer++;
 
-  *p = 0;
   temp = get_absolute_expr (&exp);
   size = temp;
 #ifdef BFD_ASSEMBLER
@@ -1362,18 +1409,17 @@ s_comm_internal (int param,
   if (exp.X_op == O_absent)
     {
       as_bad (_("missing size expression"));
-      *p = c;
       ignore_rest_of_line ();
       goto out;
     }
   else if (temp != size || !exp.X_unsigned)
     {
       as_warn (_("size (%ld) out of range, ignored"), (long) temp);
-      *p = c;
       ignore_rest_of_line ();
       goto out;
     }
 
+  *p = 0;
   symbolP = symbol_find_or_make (name);
   if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP))
     {
@@ -1555,7 +1601,7 @@ s_data (int ignore ATTRIBUTE_UNUSED)
    .file.  */
 
 void
-s_app_file_string (char *file)
+s_app_file_string (char *file, int appfile)
 {
 #ifdef LISTING
   if (listing)
@@ -1563,7 +1609,7 @@ s_app_file_string (char *file)
 #endif
   register_dependency (file);
 #ifdef obj_app_file
-  obj_app_file (file);
+  obj_app_file (file, appfile);
 #endif
 }
 
@@ -1591,7 +1637,7 @@ s_app_file (int appfile)
 
       demand_empty_rest_of_line ();
       if (!may_omit)
-       s_app_file_string (s);
+       s_app_file_string (s, appfile);
     }
 }
 
@@ -1650,6 +1696,43 @@ s_err (int ignore ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
+/* Handle the .error and .warning pseudo-ops.  */
+
+void
+s_errwarn (int err)
+{
+  int len;
+  /* The purpose for the conditional assignment is not to
+     internationalize the directive itself, but that we need a
+     self-contained message, one that can be passed like the
+     demand_copy_C_string return value, and with no assumption on the
+     location of the name of the directive within the message.  */
+  char *msg
+    = (err ? _(".error directive invoked in source file")
+       : _(".warning directive invoked in source file"));
+
+  if (!is_it_end_of_statement ())
+    {
+      if (*input_line_pointer != '\"')
+       {
+         as_bad (_("%s argument must be a string"),
+                 err ? ".error" : ".warning");
+         discard_rest_of_line ();
+         return;
+       }
+
+      msg = demand_copy_C_string (&len);
+      if (msg == NULL)
+       return;
+    }
+
+  if (err)
+    as_bad ("%s", msg);
+  else
+    as_warn ("%s", msg);
+  demand_empty_rest_of_line ();
+}
+
 /* Handle the MRI fail pseudo-op.  */
 
 void
@@ -3482,22 +3565,9 @@ emit_expr (expressionS *exp, unsigned int nbytes)
      pass to md_number_to_chars, handle it as a bignum.  */
   if (op == O_constant && nbytes > sizeof (valueT))
     {
-      valueT val;
-      int gencnt;
-
-      if (!exp->X_unsigned && exp->X_add_number < 0)
-       extra_digit = (valueT) -1;
-      val = (valueT) exp->X_add_number;
-      gencnt = 0;
-      do
-       {
-         generic_bignum[gencnt] = val & LITTLENUM_MASK;
-         val >>= LITTLENUM_NUMBER_OF_BITS;
-         ++gencnt;
-       }
-      while (val != 0);
-      op = exp->X_op = O_big;
-      exp->X_add_number = gencnt;
+      extra_digit = exp->X_unsigned ? 0 : -1;
+      convert_to_bignum (exp);
+      op = O_big;
     }
 
   if (op == O_constant)
@@ -4217,36 +4287,48 @@ output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
   unsigned byte;
 
   /* Strip leading sign extensions off the bignum.  */
-  while (size > 0 && bignum[size - 1] == (LITTLENUM_TYPE) -1)
+  while (size > 1
+        && bignum[size - 1] == LITTLENUM_MASK
+        && bignum[size - 2] > LITTLENUM_MASK / 2)
     size--;
 
   do
     {
-      if (loaded < 7 && size > 0)
-       {
-         val |= (*bignum << loaded);
-         loaded += 8 * CHARS_PER_LITTLENUM;
-         size--;
-         bignum++;
-       }
-
-      byte = val & 0x7f;
-      loaded -= 7;
-      val >>= 7;
+      /* OR in the next part of the littlenum.  */
+      val |= (*bignum << loaded);
+      loaded += LITTLENUM_NUMBER_OF_BITS;
+      size--;
+      bignum++;
 
-      if (size == 0)
+      /* Add bytes until there are less than 7 bits left in VAL
+        or until every non-sign bit has been written.  */
+      do
        {
-         if ((val == 0 && (byte & 0x40) == 0)
-             || (~(val | ~(((valueT) 1 << loaded) - 1)) == 0
-                 && (byte & 0x40) != 0))
+         byte = val & 0x7f;
+         loaded -= 7;
+         val >>= 7;
+         if (size > 0
+             || val != ((byte & 0x40) == 0 ? 0 : ((valueT) 1 << loaded) - 1))
            byte |= 0x80;
+
+         if (orig)
+           *p = byte;
+         p++;
        }
+      while ((byte & 0x80) != 0 && loaded >= 7);
+    }
+  while (size > 0);
 
+  /* Mop up any left-over bits (of which there will be less than 7).  */
+  if ((byte & 0x80) != 0)
+    {
+      /* Sign-extend VAL.  */
+      if (val & (1 << (loaded - 1)))
+       val |= ~0 << loaded;
       if (orig)
-       *p = byte;
+       *p = val & 0x7f;
       p++;
     }
-  while (byte & 0x80);
 
   return p - orig;
 }
@@ -4325,6 +4407,16 @@ emit_leb128_expr (expressionS *exp, int sign)
       as_warn (_("register value used as expression"));
       op = O_constant;
     }
+  else if (op == O_constant
+          && sign
+          && (exp->X_add_number < 0) != !exp->X_unsigned)
+    {
+      /* We're outputting a signed leb128 and the sign of X_add_number
+        doesn't reflect the sign of the original value.  Convert EXP
+        to a correctly-extended bignum instead.  */
+      convert_to_bignum (exp);
+      op = O_big;
+    }
 
   /* 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.  */
@@ -4908,13 +5000,13 @@ s_incbin (int x ATTRIBUTE_UNUSED)
        }
       file_len = ftell (binfile);
 
-      /* If a count was not specified use the size of the file.  */
+      /* If a count was not specified use the remainder of the file.  */
       if (count == 0)
-       count = file_len;
+       count = file_len - skip;
 
-      if (skip + count > file_len)
+      if (skip < 0 || count < 0 || file_len < 0 || skip + count > file_len)
        {
-         as_bad (_("skip (%ld) + count (%ld) larger than file size (%ld)"),
+         as_bad (_("skip (%ld) or count (%ld) invalid for file size (%ld)"),
                  skip, count, file_len);
          goto done;
        }
This page took 0.026993 seconds and 4 git commands to generate.