* ehopt.c: Convert to ISO-C.
[binutils-gdb.git] / gas / expr.c
index 633854c37bfd51392e1f2cc5fe35a3aab0a24a62..a18d6d87c0dfadc708226583a6b16150ae1a7ffb 100644 (file)
@@ -1,6 +1,6 @@
 /* expr.c -operands, expressions-
    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001
+   1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
    (It also gives smaller files to re-compile.)
    Here, "operand"s are of expressions, not instructions.  */
 
-#include <ctype.h>
 #include <string.h>
 #define min(a, b)       ((a) < (b) ? (a) : (b))
 
 #include "as.h"
+#include "safe-ctype.h"
 #include "obstack.h"
 
-static void floating_constant PARAMS ((expressionS * expressionP));
-static valueT generic_bignum_to_int32 PARAMS ((void));
+static void floating_constant (expressionS * expressionP);
+static valueT generic_bignum_to_int32 (void);
 #ifdef BFD64
-static valueT generic_bignum_to_int64 PARAMS ((void));
+static valueT generic_bignum_to_int64 (void);
 #endif
-static void integer_constant PARAMS ((int radix, expressionS * expressionP));
-static void mri_char_constant PARAMS ((expressionS *));
-static void current_location PARAMS ((expressionS *));
-static void clean_up_expression PARAMS ((expressionS * expressionP));
-static segT operand PARAMS ((expressionS *));
-static operatorT operator PARAMS ((int *));
+static void integer_constant (int radix, expressionS * expressionP);
+static void mri_char_constant (expressionS *);
+static void current_location (expressionS *);
+static void clean_up_expression (expressionS * expressionP);
+static segT operand (expressionS *);
+static operatorT operator (int *);
 
 extern const char EXP_CHARS[], FLT_CHARS[];
 
@@ -63,11 +63,9 @@ static struct expr_symbol_line *expr_symbol_lines;
    into the fake section expr_section.  */
 
 symbolS *
-make_expr_symbol (expressionP)
-     expressionS *expressionP;
+make_expr_symbol (expressionS *expressionP)
 {
   expressionS zero;
-  const char *fake;
   symbolS *symbolP;
   struct expr_symbol_line *n;
 
@@ -78,12 +76,12 @@ make_expr_symbol (expressionP)
   if (expressionP->X_op == O_big)
     {
       /* This won't work, because the actual value is stored in
-         generic_floating_point_number or generic_bignum, and we are
-         going to lose it if we haven't already.  */
+        generic_floating_point_number or generic_bignum, and we are
+        going to lose it if we haven't already.  */
       if (expressionP->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"));
       zero.X_op = O_constant;
       zero.X_add_number = 0;
       zero.X_unsigned = 0;
@@ -91,13 +89,11 @@ make_expr_symbol (expressionP)
       expressionP = &zero;
     }
 
-  fake = FAKE_LABEL_NAME;
-
   /* Putting constant symbols in absolute_section rather than
      expr_section is convenient for the old a.out code, for which
      S_GET_SEGMENT does not always retrieve the value put in by
      S_SET_SEGMENT.  */
-  symbolP = symbol_create (fake,
+  symbolP = symbol_create (FAKE_LABEL_NAME,
                           (expressionP->X_op == O_constant
                            ? absolute_section
                            : expr_section),
@@ -121,10 +117,7 @@ make_expr_symbol (expressionP)
    the symbol.  */
 
 int
-expr_symbol_where (sym, pfile, pline)
-     symbolS *sym;
-     char **pfile;
-     unsigned int *pline;
+expr_symbol_where (symbolS *sym, char **pfile, unsigned int *pline)
 {
   register struct expr_symbol_line *l;
 
@@ -154,8 +147,7 @@ expr_symbol_where (sym, pfile, pline)
    but that seems more clumsy.  */
 
 symbolS *
-expr_build_uconstant (value)
-     offsetT value;
+expr_build_uconstant (offsetT value)
 {
   expressionS e;
 
@@ -168,9 +160,7 @@ expr_build_uconstant (value)
 /* Build an expression for OP s1.  */
 
 symbolS *
-expr_build_unary (op, s1)
-     operatorT op;
-     symbolS *s1;
+expr_build_unary (operatorT op, symbolS *s1)
 {
   expressionS e;
 
@@ -183,10 +173,7 @@ expr_build_unary (op, s1)
 /* Build an expression for s1 OP s2.  */
 
 symbolS *
-expr_build_binary (op, s1, s2)
-     operatorT op;
-     symbolS *s1;
-     symbolS *s2;
+expr_build_binary (operatorT op, symbolS *s1, symbolS *s2)
 {
   expressionS e;
 
@@ -200,7 +187,7 @@ expr_build_binary (op, s1, s2)
 /* Build an expression for the current location ('.').  */
 
 symbolS *
-expr_build_dot ()
+expr_build_dot (void)
 {
   expressionS e;
 
@@ -230,8 +217,7 @@ FLONUM_TYPE generic_floating_point_number = {
 int generic_floating_point_magic;
 \f
 static void
-floating_constant (expressionP)
-     expressionS *expressionP;
+floating_constant (expressionS *expressionP)
 {
   /* input_line_pointer -> floating-point constant.  */
   int error_code;
@@ -243,11 +229,12 @@ floating_constant (expressionP)
     {
       if (error_code == ERROR_EXPONENT_OVERFLOW)
        {
-         as_bad (_("bad floating-point constant: exponent overflow, probably assembling junk"));
+         as_bad (_("bad floating-point constant: exponent overflow"));
        }
       else
        {
-         as_bad (_("bad floating-point constant: unknown error code=%d."), error_code);
+         as_bad (_("bad floating-point constant: unknown error code=%d"),
+                 error_code);
        }
     }
   expressionP->X_op = O_big;
@@ -257,7 +244,7 @@ floating_constant (expressionP)
 }
 
 static valueT
-generic_bignum_to_int32 ()
+generic_bignum_to_int32 (void)
 {
   valueT number =
           ((generic_bignum[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS)
@@ -268,7 +255,7 @@ generic_bignum_to_int32 ()
 
 #ifdef BFD64
 static valueT
-generic_bignum_to_int64 ()
+generic_bignum_to_int64 (void)
 {
   valueT number =
     ((((((((valueT) generic_bignum[3] & LITTLENUM_MASK)
@@ -283,9 +270,7 @@ generic_bignum_to_int64 ()
 #endif
 
 static void
-integer_constant (radix, expressionP)
-     int radix;
-     expressionS *expressionP;
+integer_constant (int radix, expressionS *expressionP)
 {
   char *start;         /* Start of number.  */
   char *suffix = NULL;
@@ -328,11 +313,9 @@ integer_constant (radix, expressionP)
       int flt = 0;
 
       /* In MRI mode, the number may have a suffix indicating the
-         radix.  For that matter, it might actually be a floating
-         point constant.  */
-      for (suffix = input_line_pointer;
-          isalnum ((unsigned char) *suffix);
-          suffix++)
+        radix.  For that matter, it might actually be a floating
+        point constant.  */
+      for (suffix = input_line_pointer; ISALNUM (*suffix); suffix++)
        {
          if (*suffix == 'e' || *suffix == 'E')
            flt = 1;
@@ -346,8 +329,7 @@ integer_constant (radix, expressionP)
       else
        {
          c = *--suffix;
-         if (islower ((unsigned char) c))
-           c = toupper (c);
+         c = TOUPPER (c);
          if (c == 'B')
            radix = 2;
          else if (c == 'D')
@@ -403,7 +385,7 @@ integer_constant (radix, expressionP)
   if (radix == 16 && c == '_')
     {
       /* This is literal of the form 0x333_0_12345678_1.
-         This example is equivalent to 0x00000333000000001234567800000001.  */
+        This example is equivalent to 0x00000333000000001234567800000001.  */
 
       int num_little_digits = 0;
       int i;
@@ -427,7 +409,7 @@ integer_constant (radix, expressionP)
 
          /* Check for 8 digit per word max.  */
          if (ndigit > 8)
-           as_bad (_("A bignum with underscores may not have more than 8 hex digits in any word."));
+           as_bad (_("a bignum with underscores may not have more than 8 hex digits in any word"));
 
          /* Add this chunk to the bignum.
             Shift things down 2 little digits.  */
@@ -450,7 +432,7 @@ integer_constant (radix, expressionP)
       assert (num_little_digits >= 4);
 
       if (num_little_digits != 8)
-       as_bad (_("A bignum with underscores must have exactly 4 words."));
+       as_bad (_("a bignum with underscores must have exactly 4 words"));
 
       /* We might have some leading zeros.  These can be trimmed to give
         us a change to fit this constant into a small number.  */
@@ -573,7 +555,7 @@ integer_constant (radix, expressionP)
              /* Either not seen or not defined.  */
              /* @@ Should print out the original string instead of
                 the parsed number.  */
-             as_bad (_("backw. ref to unknown label \"%d:\", 0 assumed."),
+             as_bad (_("backward ref to unknown label \"%d:\""),
                      (int) number);
              expressionP->X_op = O_constant;
            }
@@ -647,8 +629,7 @@ integer_constant (radix, expressionP)
 /* Parse an MRI multi character constant.  */
 
 static void
-mri_char_constant (expressionP)
-     expressionS *expressionP;
+mri_char_constant (expressionS *expressionP)
 {
   int i;
 
@@ -683,8 +664,8 @@ mri_char_constant (expressionP)
       if (i < SIZE_OF_LARGE_NUMBER - 1)
        {
          /* If there is more than one littlenum, left justify the
-             last one to make it match the earlier ones.  If there is
-             only one, we can just use the value directly.  */
+            last one to make it match the earlier ones.  If there is
+            only one, we can just use the value directly.  */
          for (; j < CHARS_PER_LITTLENUM; j++)
            generic_bignum[i] <<= 8;
        }
@@ -696,7 +677,7 @@ mri_char_constant (expressionP)
 
   if (i < 0)
     {
-      as_bad (_("Character constant too large"));
+      as_bad (_("character constant too large"));
       i = 0;
     }
 
@@ -737,8 +718,7 @@ mri_char_constant (expressionP)
    handles the magic symbol `.'.  */
 
 static void
-current_location (expressionp)
-     expressionS *expressionp;
+current_location (expressionS *expressionp)
 {
   if (now_seg == absolute_section)
     {
@@ -747,13 +727,8 @@ current_location (expressionp)
     }
   else
     {
-      symbolS *symbolp;
-
-      symbolp = symbol_new (FAKE_LABEL_NAME, now_seg,
-                           (valueT) frag_now_fix (),
-                           frag_now);
       expressionp->X_op = O_symbol;
-      expressionp->X_add_symbol = symbolp;
+      expressionp->X_add_symbol = symbol_temp_new_now ();
       expressionp->X_add_number = 0;
     }
 }
@@ -761,13 +736,12 @@ current_location (expressionp)
 /* In: Input_line_pointer points to 1st char of operand, which may
        be a space.
 
-   Out:        A expressionS.
+   Out:        An expressionS.
        The operand may have been empty: in this case X_op == O_absent.
        Input_line_pointer->(next non-blank) char after operand.  */
 
 static segT
-operand (expressionP)
-     expressionS *expressionP;
+operand (expressionS *expressionP)
 {
   char c;
   symbolS *symbolP;    /* Points to symbol.  */
@@ -805,11 +779,14 @@ operand (expressionP)
 
       integer_constant ((NUMBERS_WITH_SUFFIX || flag_m68k_mri)
                        ? 0 : 10,
-                        expressionP);
+                       expressionP);
       break;
 
 #ifdef LITERAL_PREFIXDOLLAR_HEX
     case '$':
+      /* $L is the start of a local label, not a hex constant.  */
+      if (* input_line_pointer == 'L')
+      goto isname;
       integer_constant (16, expressionP);
       break;
 #endif
@@ -827,10 +804,10 @@ operand (expressionP)
        {
          char *s;
 
-         /* Check for a hex constant.  */
+         /* Check for a hex or float constant.  */
          for (s = input_line_pointer; hex_p (*s); s++)
            ;
-         if (*s == 'h' || *s == 'H')
+         if (*s == 'h' || *s == 'H' || *input_line_pointer == '.')
            {
              --input_line_pointer;
              integer_constant (0, expressionP);
@@ -858,8 +835,7 @@ operand (expressionP)
            {
              input_line_pointer++;
              floating_constant (expressionP);
-             expressionP->X_add_number =
-               - (isupper ((unsigned char) c) ? tolower (c) : c);
+             expressionP->X_add_number = - TOLOWER (c);
            }
          else
            {
@@ -981,8 +957,7 @@ operand (expressionP)
        case 'G':
          input_line_pointer++;
          floating_constant (expressionP);
-         expressionP->X_add_number =
-           - (isupper ((unsigned char) c) ? tolower (c) : c);
+         expressionP->X_add_number = - TOLOWER (c);
          break;
 
        case '$':
@@ -1010,7 +985,7 @@ operand (expressionP)
 #ifdef RELAX_PAREN_GROUPING
          if (c != '(')
 #endif
-           as_bad (_("Missing '%c' assumed"), c == '(' ? ')' : ']');
+           as_bad (_("missing '%c'"), c == '(' ? ')' : ']');
        }
       else
        input_line_pointer++;
@@ -1080,6 +1055,18 @@ operand (expressionP)
            else
              expressionP->X_add_number = ! expressionP->X_add_number;
          }
+       else if (expressionP->X_op == O_big
+                && expressionP->X_add_number <= 0
+                && c == '-'
+                && (generic_floating_point_number.sign == '+'
+                    || generic_floating_point_number.sign == 'P'))
+         {
+           /* Negative flonum (eg, -1.000e0).  */
+           if (generic_floating_point_number.sign == '+')
+             generic_floating_point_number.sign = '-';
+           else
+             generic_floating_point_number.sign = 'N';
+         }
        else if (expressionP->X_op != O_illegal
                 && expressionP->X_op != O_absent)
          {
@@ -1101,7 +1088,7 @@ operand (expressionP)
 #if defined (DOLLAR_DOT) || defined (TC_M68K)
     case '$':
       /* '$' is the program counter when in MRI mode, or when
-         DOLLAR_DOT is defined.  */
+        DOLLAR_DOT is defined.  */
 #ifndef DOLLAR_DOT
       if (! flag_m68k_mri)
        goto de_fault;
@@ -1109,7 +1096,7 @@ operand (expressionP)
       if (flag_m68k_mri && hex_p (*input_line_pointer))
        {
          /* In MRI mode, '$' is also used as the prefix for a
-             hexadecimal constant.  */
+            hexadecimal constant.  */
          integer_constant (16, expressionP);
          break;
        }
@@ -1200,7 +1187,7 @@ operand (expressionP)
        goto de_fault;
 
       /* In MRI mode, this is a floating point constant represented
-         using hexadecimal digits.  */
+        using hexadecimal digits.  */
 
       ++input_line_pointer;
       integer_constant (16, expressionP);
@@ -1228,9 +1215,9 @@ operand (expressionP)
 
 #ifdef md_parse_name
          /* This is a hook for the backend to parse certain names
-             specially in certain contexts.  If a name always has a
-             specific value, it can often be handled by simply
-             entering it in the symbol table.  */
+            specially in certain contexts.  If a name always has a
+            specific value, it can often be handled by simply
+            entering it in the symbol table.  */
          if (md_parse_name (name, expressionP, &c))
            {
              *input_line_pointer = c;
@@ -1312,7 +1299,7 @@ operand (expressionP)
          if (expressionP->X_op == O_absent)
            {
              ++input_line_pointer;
-             as_bad (_("Bad expression"));
+             as_bad (_("bad expression"));
              expressionP->X_op = O_constant;
              expressionP->X_add_number = 0;
            }
@@ -1343,18 +1330,15 @@ operand (expressionP)
 \f
 /* Internal.  Simplify a struct expression for use by expr ().  */
 
-/* In: address of a expressionS.
+/* In: address of an expressionS.
        The X_op field of the expressionS may only take certain values.
        Elsewise we waste time special-case testing. Sigh. Ditto SEG_ABSENT.
 
    Out:        expressionS may have been modified:
-       'foo-foo' symbol references cancelled to 0, which changes X_op
-       from O_subtract to O_constant.
        Unused fields zeroed to help expr ().  */
 
 static void
-clean_up_expression (expressionP)
-     expressionS *expressionP;
+clean_up_expression (expressionS *expressionP)
 {
   switch (expressionP->X_op)
     {
@@ -1372,23 +1356,6 @@ clean_up_expression (expressionP)
     case O_bit_not:
       expressionP->X_op_symbol = NULL;
       break;
-    case O_subtract:
-      if (expressionP->X_op_symbol == expressionP->X_add_symbol
-         || ((symbol_get_frag (expressionP->X_op_symbol)
-              == symbol_get_frag (expressionP->X_add_symbol))
-             && SEG_NORMAL (S_GET_SEGMENT (expressionP->X_add_symbol))
-             && (S_GET_VALUE (expressionP->X_op_symbol)
-                 == S_GET_VALUE (expressionP->X_add_symbol))))
-       {
-         addressT diff = (S_GET_VALUE (expressionP->X_add_symbol)
-                          - S_GET_VALUE (expressionP->X_op_symbol));
-
-         expressionP->X_op = O_constant;
-         expressionP->X_add_symbol = NULL;
-         expressionP->X_op_symbol = NULL;
-         expressionP->X_add_number += diff;
-       }
-      break;
     default:
       break;
     }
@@ -1400,7 +1367,7 @@ clean_up_expression (expressionP)
    Unary operators and parenthetical expressions are treated as operands.
    As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
 
-   We used to do a aho/ullman shift-reduce parser, but the logic got so
+   We used to do an aho/ullman shift-reduce parser, but the logic got so
    warped that I flushed it and wrote a recursive-descent parser instead.
    Now things are stable, would anybody like to write a fast parser?
    Most expressions are either register (which does not even reach here)
@@ -1522,7 +1489,7 @@ static operator_rankT op_rank[] = {
 #define MRI_MUL_PRECEDENCE 6
 
 void
-expr_set_precedence ()
+expr_set_precedence (void)
 {
   if (flag_m68k_mri)
     {
@@ -1541,7 +1508,7 @@ expr_set_precedence ()
 /* Initialize the expression parser.  */
 
 void
-expr_begin ()
+expr_begin (void)
 {
   expr_set_precedence ();
 
@@ -1558,8 +1525,7 @@ expr_begin ()
    Does not advance INPUT_LINE_POINTER.  */
 
 static inline operatorT
-operator (num_chars)
-     int *num_chars;
+operator (int *num_chars)
 {
   int c;
   operatorT ret;
@@ -1647,9 +1613,8 @@ operator (num_chars)
 /* Parse an expression.  */
 
 segT
-expr (rankarg, resultP)
-     int rankarg;      /* Larger # is higher rank.  */
-     expressionS *resultP;     /* Deliver result here.  */
+expr (int rankarg,             /* Larger # is higher rank.  */
+      expressionS *resultP     /* Deliver result here.  */)
 {
   operator_rankT rank = (operator_rankT) rankarg;
   segT retval;
@@ -1660,6 +1625,10 @@ expr (rankarg, resultP)
 
   know (rank >= 0);
 
+  /* Save the value of dot for the fixup code.  */
+  if (rank == 0)
+    dot_value = frag_now_fix ();
+
   retval = operand (resultP);
 
   /* operand () gobbles spaces.  */
@@ -1695,21 +1664,6 @@ expr (rankarg, resultP)
            }
        }
 
-      if (retval == undefined_section)
-       {
-         if (SEG_NORMAL (rightseg))
-           retval = rightseg;
-       }
-      else if (! SEG_NORMAL (retval))
-       retval = rightseg;
-      else if (SEG_NORMAL (rightseg)
-              && retval != rightseg
-#ifdef DIFF_EXPR_OK
-              && op_left != O_subtract
-#endif
-              )
-       as_bad (_("operation combines symbols in different segments"));
-
       op_right = operator (&op_chars);
 
       know (op_right == O_illegal
@@ -1765,8 +1719,8 @@ expr (rankarg, resultP)
               && resultP->X_op == O_symbol
               && (symbol_get_frag (right.X_add_symbol)
                   == symbol_get_frag (resultP->X_add_symbol))
-              && SEG_NORMAL (S_GET_SEGMENT (right.X_add_symbol)))
-
+              && (SEG_NORMAL (rightseg)
+                  || right.X_add_symbol == resultP->X_add_symbol))
        {
          resultP->X_add_number -= right.X_add_number;
          resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol)
@@ -1806,7 +1760,7 @@ expr (rankarg, resultP)
            case O_left_shift:          resultP->X_add_number <<= v; break;
            case O_right_shift:
              /* We always use unsigned shifts, to avoid relying on
-                 characteristics of the compiler used to compile gas.  */
+                characteristics of the compiler used to compile gas.  */
              resultP->X_add_number =
                (offsetT) ((valueT) resultP->X_add_number >> (valueT) v);
              break;
@@ -1861,7 +1815,14 @@ expr (rankarg, resultP)
          if (op_left == O_add)
            resultP->X_add_number += right.X_add_number;
          else if (op_left == O_subtract)
-           resultP->X_add_number -= right.X_add_number;
+           {
+             resultP->X_add_number -= right.X_add_number;
+             if (retval == rightseg && SEG_NORMAL (retval))
+               {
+                 retval = absolute_section;
+                 rightseg = absolute_section;
+               }
+           }
        }
       else
        {
@@ -1873,6 +1834,21 @@ expr (rankarg, resultP)
          resultP->X_unsigned = 1;
        }
 
+      if (retval != rightseg)
+       {
+         if (! SEG_NORMAL (retval))
+           {
+             if (retval != undefined_section || SEG_NORMAL (rightseg))
+               retval = rightseg;
+           }
+         else if (SEG_NORMAL (rightseg)
+#ifdef DIFF_EXPR_OK
+                  && op_left != O_subtract
+#endif
+                  )
+           as_bad (_("operation combines symbols in different segments"));
+       }
+
       op_left = op_right;
     }                          /* While next operator is >= this rank.  */
 
@@ -1896,7 +1872,7 @@ expr (rankarg, resultP)
    lines end in end-of-line.  */
 
 char
-get_symbol_end ()
+get_symbol_end (void)
 {
   char c;
 
@@ -1915,7 +1891,7 @@ get_symbol_end ()
 }
 
 unsigned int
-get_single_number ()
+get_single_number (void)
 {
   expressionS exp;
   operand (&exp);