Locale changes from Bruno Haible <haible@clisp.cons.org>.
[deliverable/binutils-gdb.git] / gas / expr.c
index 09f38b1bb7e07b75dc91c665420e4a6f3c5c3288..499f9a33fb438a31ea8a2f72f8749c6206b720dd 100644 (file)
@@ -1,5 +1,6 @@
 /* expr.c -operands, expressions-
-   Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+   Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001
    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));
@@ -41,15 +42,14 @@ 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 ((void));
+static operatorT operator PARAMS ((int *));
 
 extern const char EXP_CHARS[], FLT_CHARS[];
 
 /* We keep a mapping of expression symbols to file positions, so that
    we can provide better error messages.  */
 
-struct expr_symbol_line
-{
+struct expr_symbol_line {
   struct expr_symbol_line *next;
   symbolS *sym;
   char *file;
@@ -81,9 +81,9 @@ make_expr_symbol (expressionP)
          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;
@@ -105,7 +105,7 @@ make_expr_symbol (expressionP)
   symbol_set_value_expression (symbolP, expressionP);
 
   if (expressionP->X_op == O_constant)
-    resolve_symbol_value (symbolP, 1);
+    resolve_symbol_value (symbolP);
 
   n = (struct expr_symbol_line *) xmalloc (sizeof *n);
   n->sym = symbolP;
@@ -217,8 +217,8 @@ expr_build_dot ()
    and never write into the early words, thus they'll always be zero.
    I hate Dean's floating-point code.  Bleh.  */
 LITTLENUM_TYPE generic_bignum[SIZE_OF_LARGE_NUMBER + 6];
-FLONUM_TYPE generic_floating_point_number =
-{
+
+FLONUM_TYPE generic_floating_point_number = {
   &generic_bignum[6],          /* low.  (JF: Was 0)  */
   &generic_bignum[SIZE_OF_LARGE_NUMBER + 6 - 1], /* high.  JF: (added +6)  */
   0,                           /* leader.  */
@@ -243,11 +243,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;
@@ -330,9 +331,7 @@ integer_constant (radix, expressionP)
       /* 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++)
+      for (suffix = input_line_pointer; ISALNUM (*suffix); suffix++)
        {
          if (*suffix == 'e' || *suffix == 'E')
            flt = 1;
@@ -346,8 +345,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')
@@ -427,7 +425,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 +448,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 +571,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;
            }
@@ -696,7 +694,7 @@ mri_char_constant (expressionP)
 
   if (i < 0)
     {
-      as_bad (_("Character constant too large"));
+      as_bad (_("character constant too large"));
       i = 0;
     }
 
@@ -810,6 +808,9 @@ operand (expressionP)
 
 #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
@@ -858,8 +859,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 +981,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 +1009,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++;
@@ -1069,7 +1068,7 @@ operand (expressionP)
            /* input_line_pointer -> char after operand.  */
            if (c == '-')
              {
-               expressionP->X_add_number = -expressionP->X_add_number;
+               expressionP->X_add_number = - expressionP->X_add_number;
                /* Notice: '-' may overflow: no warning is given.
                   This is compatible with other people's
                   assemblers.  Sigh.  */
@@ -1231,7 +1230,7 @@ operand (expressionP)
              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))
+         if (md_parse_name (name, expressionP, &c))
            {
              *input_line_pointer = c;
              break;
@@ -1304,7 +1303,7 @@ operand (expressionP)
        {
          /* Let the target try to parse it.  Success is indicated by changing
             the X_op field to something other than O_absent and pointing
-            input_line_pointer passed the expression.  If it can't parse the
+            input_line_pointer past the expression.  If it can't parse the
             expression, X_op and input_line_pointer should be unchanged.  */
          expressionP->X_op = O_absent;
          --input_line_pointer;
@@ -1312,7 +1311,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;
            }
@@ -1418,9 +1417,8 @@ clean_up_expression (expressionP)
 #undef __
 #define __ O_illegal
 
-static const operatorT op_encoding[256] =
-{                              /* Maps ASCII -> operators.  */
-
+/* Maps ASCII -> operators.  */
+static const operatorT op_encoding[256] = {
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
 
@@ -1457,22 +1455,21 @@ static const operatorT op_encoding[256] =
    0   operand, (expression)
    1   ||
    2   &&
-   3   = <> < <= >= >
+   3   == <> < <= >= >
    4   + -
    5   used for * / % in MRI mode
    6   & ^ ! |
    7   * / % << >>
    8   unary - unary ~
 */
-static operator_rankT op_rank[] =
-{
+static operator_rankT op_rank[] = {
   0,   /* O_illegal */
   0,   /* O_absent */
   0,   /* O_constant */
   0,   /* O_symbol */
   0,   /* O_symbol_rva */
   0,   /* O_register */
-  0,   /* O_bit */
+  0,   /* O_big */
   9,   /* O_uminus */
   9,   /* O_bit_not */
   9,   /* O_logical_not */
@@ -1520,8 +1517,8 @@ static operator_rankT op_rank[] =
    mode.  Also, MRI uses a different bit_not operator, and this fixes
    that as well.  */
 
-#define STANDARD_MUL_PRECEDENCE (7)
-#define MRI_MUL_PRECEDENCE (5)
+#define STANDARD_MUL_PRECEDENCE 8
+#define MRI_MUL_PRECEDENCE 6
 
 void
 expr_set_precedence ()
@@ -1555,17 +1552,19 @@ expr_begin ()
   }
 }
 \f
-/* Return the encoding for the operator at INPUT_LINE_POINTER.
-   Advance INPUT_LINE_POINTER to the last character in the operator
-   (i.e., don't change it for a single character operator).  */
+/* Return the encoding for the operator at INPUT_LINE_POINTER, and
+   sets NUM_CHARS to the number of characters in the operator.
+   Does not advance INPUT_LINE_POINTER.  */
 
 static inline operatorT
-operator ()
+operator (num_chars)
+     int *num_chars;
 {
   int c;
   operatorT ret;
 
   c = *input_line_pointer & 0xff;
+  *num_chars = 1;
 
   if (is_end_of_line[c])
     return O_illegal;
@@ -1590,14 +1589,14 @@ operator ()
          ret = O_le;
          break;
        }
-      ++input_line_pointer;
+      *num_chars = 2;
       return ret;
 
     case '=':
       if (input_line_pointer[1] != '=')
        return op_encoding[c];
 
-      ++input_line_pointer;
+      *num_chars = 2;
       return O_eq;
 
     case '>':
@@ -1612,7 +1611,7 @@ operator ()
          ret = O_ge;
          break;
        }
-      ++input_line_pointer;
+      *num_chars = 2;
       return ret;
 
     case '!':
@@ -1623,21 +1622,21 @@ operator ()
            return O_bit_inclusive_or;
          return op_encoding[c];
        }
-      ++input_line_pointer;
+      *num_chars = 2;
       return O_bit_exclusive_or;
 
     case '|':
       if (input_line_pointer[1] != '|')
        return op_encoding[c];
 
-      ++input_line_pointer;
+      *num_chars = 2;
       return O_logical_or;
 
     case '&':
       if (input_line_pointer[1] != '&')
        return op_encoding[c];
 
-      ++input_line_pointer;
+      *num_chars = 2;
       return O_logical_and;
     }
 
@@ -1656,6 +1655,7 @@ expr (rankarg, resultP)
   expressionS right;
   operatorT op_left;
   operatorT op_right;
+  int op_chars;
 
   know (rank >= 0);
 
@@ -1664,12 +1664,12 @@ expr (rankarg, resultP)
   /* operand () gobbles spaces.  */
   know (*input_line_pointer != ' ');
 
-  op_left = operator ();
+  op_left = operator (&op_chars);
   while (op_left != O_illegal && op_rank[(int) op_left] > rank)
     {
       segT rightseg;
 
-      input_line_pointer++;    /* -> after 1st character of operator.  */
+      input_line_pointer += op_chars;  /* -> after operator.  */
 
       rightseg = expr (op_rank[(int) op_left], &right);
       if (right.X_op == O_absent)
@@ -1694,22 +1694,7 @@ 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_right = operator (&op_chars);
 
       know (op_right == O_illegal
            || op_rank[(int) op_right] <= op_rank[(int) op_left]);
@@ -1764,8 +1749,7 @@ 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))
        {
          resultP->X_add_number -= right.X_add_number;
          resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol)
@@ -1817,27 +1801,27 @@ expr (rankarg, resultP)
            case O_subtract:            resultP->X_add_number -= v; break;
            case O_eq:
              resultP->X_add_number =
-               resultP->X_add_number == v ? ~(offsetT) 0 : 0;
+               resultP->X_add_number == v ? ~ (offsetT) 0 : 0;
              break;
            case O_ne:
              resultP->X_add_number =
-               resultP->X_add_number != v ? ~(offsetT) 0 : 0;
+               resultP->X_add_number != v ? ~ (offsetT) 0 : 0;
              break;
            case O_lt:
              resultP->X_add_number =
-               resultP->X_add_number < v ? ~(offsetT) 0 : 0;
+               resultP->X_add_number <  v ? ~ (offsetT) 0 : 0;
              break;
            case O_le:
              resultP->X_add_number =
-               resultP->X_add_number <= v ? ~(offsetT) 0 : 0;
+               resultP->X_add_number <= v ? ~ (offsetT) 0 : 0;
              break;
            case O_ge:
              resultP->X_add_number =
-               resultP->X_add_number >= v ? ~(offsetT) 0 : 0;
+               resultP->X_add_number >= v ? ~ (offsetT) 0 : 0;
              break;
            case O_gt:
              resultP->X_add_number =
-               resultP->X_add_number > v ? ~(offsetT) 0 : 0;
+               resultP->X_add_number >  v ? ~ (offsetT) 0 : 0;
              break;
            case O_logical_and:
              resultP->X_add_number = resultP->X_add_number && v;
@@ -1860,7 +1844,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
        {
@@ -1872,6 +1863,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.  */
 
This page took 0.033492 seconds and 4 git commands to generate.