* listing.c (listing_print): Close the listing file if it is not
[deliverable/binutils-gdb.git] / gas / expr.c
index b73066785118ed55fa0d26ab679e7d76bf469e41..132649e212be241d8579f7cc2897b7c2d7df8f3b 100644 (file)
@@ -34,6 +34,7 @@
 static void floating_constant PARAMS ((expressionS * expressionP));
 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));
 
 extern const char EXP_CHARS[], FLT_CHARS[];
@@ -491,6 +492,31 @@ mri_char_constant (expressionP)
   ++input_line_pointer;
 }
 
+/* Return an expression representing the current location.  This
+   handles the magic symbol `.'.  */
+
+static void
+current_location (expressionp)
+     expressionS *expressionp;
+{
+  if (now_seg == absolute_section)
+    {
+      expressionp->X_op = O_constant;
+      expressionp->X_add_number = abs_section_offset;
+    }
+  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_number = 0;
+    }
+}
+
 /*
  * Summary of operand().
  *
@@ -561,6 +587,14 @@ operand (expressionP)
       c = *input_line_pointer;
       switch (c)
        {
+       case '8':
+       case '9':
+         if (flag_mri)
+           {
+             integer_constant (0, expressionP);
+             break;
+           }
+         /* Fall through.  */
        default:
        default_case:
          if (c && strchr (FLT_CHARS, c))
@@ -802,23 +836,60 @@ operand (expressionP)
          integer_constant (16, expressionP);
          break;
        }
-      /* Fall through.  */
+
+      if (is_part_of_name (*input_line_pointer))
+       goto isname;
+
+      current_location (expressionP);
+      break;
+
     case '.':
       if (!is_part_of_name (*input_line_pointer))
        {
-         const char *fake;
+         current_location (expressionP);
+         break;
+       }
+      else if ((strncasecmp (input_line_pointer, "startof.", 8) == 0
+               && ! is_part_of_name (input_line_pointer[8]))
+              || (strncasecmp (input_line_pointer, "sizeof.", 7) == 0
+                  && ! is_part_of_name (input_line_pointer[7])))
+       {
+         int start;
+
+         start = (input_line_pointer[1] == 't'
+                  || input_line_pointer[1] == 'T');
+         input_line_pointer += start ? 8 : 7;
+         SKIP_WHITESPACE ();
+         if (*input_line_pointer != '(')
+           as_bad ("syntax error in .startof. or .sizeof.");
+         else
+           {
+             char *buf;
 
-         /* JF: '.' is pseudo symbol with value of current location
-            in current segment.  */
-         fake = FAKE_LABEL_NAME;
-         symbolP = symbol_new (fake,
-                               now_seg,
-                               (valueT) frag_now_fix (),
-                               frag_now);
+             ++input_line_pointer;
+             SKIP_WHITESPACE ();
+             name = input_line_pointer;
+             c = get_symbol_end ();
+
+             buf = (char *) xmalloc (strlen (name) + 10);
+             if (start)
+               sprintf (buf, ".startof.%s", name);
+             else
+               sprintf (buf, ".sizeof.%s", name);
+             symbolP = symbol_make (buf);
+             free (buf);
 
-         expressionP->X_op = O_symbol;
-         expressionP->X_add_symbol = symbolP;
-         expressionP->X_add_number = 0;
+             expressionP->X_op = O_symbol;
+             expressionP->X_add_symbol = symbolP;
+             expressionP->X_add_number = 0;
+
+             *input_line_pointer = c;
+             SKIP_WHITESPACE ();
+             if (*input_line_pointer != ')')
+               as_bad ("syntax error in .startof. or .sizeof.");
+             else
+               ++input_line_pointer;
+           }
          break;
        }
       else
@@ -857,6 +928,13 @@ operand (expressionP)
       integer_constant (16, expressionP);
       break;
 
+    case '*':
+      if (! flag_mri || is_part_of_name (*input_line_pointer))
+       goto de_fault;
+
+      current_location (expressionP);
+      break;
+
     default:
     de_fault:
       if (is_end_of_line[(unsigned char) c])
@@ -1016,13 +1094,13 @@ clean_up_expression (expressionP)
 #undef __
 #define __ O_illegal
 
-static const operatorT op_encoding[256] =
+static operatorT op_encoding[256] =
 {                              /* maps ASCII->operators */
 
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
   __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
 
-  __, O_bit_or_not, O_bit_not, __, __, O_modulus, O_bit_and, __,
+  __, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,
   __, __, O_multiply, O_add, __, O_subtract, __, O_divide,
   __, __, __, __, __, __, __, __,
   __, __, __, __, O_lt, __, O_gt, __,
@@ -1097,6 +1175,7 @@ expr_begin ()
       op_rank[O_multiply] = 3;
       op_rank[O_divide] = 3;
       op_rank[O_modulus] = 3;
+      op_encoding['"'] = O_bit_not;
     }
 }
 \f
@@ -1220,7 +1299,7 @@ expr (rank, resultP)
       op_right = operator ();
 
       know (op_right == O_illegal || op_rank[(int) op_right] <= op_rank[(int) op_left]);
-      know ((int) op_left >= (int) O_multiply && (int) op_left <= (int) O_subtract);
+      know ((int) op_left >= (int) O_multiply && (int) op_left <= (int) O_gt);
 
       /* input_line_pointer->after right-hand quantity. */
       /* left-hand quantity in resultP */
@@ -1385,7 +1464,10 @@ get_symbol_end ()
 {
   char c;
 
-  while (is_part_of_name (c = *input_line_pointer++))
+  /* We accept \001 in a name in case this is being called with a
+     constructed string.  */
+  while (is_part_of_name (c = *input_line_pointer++)
+        || c == '\001')
     ;
   *--input_line_pointer = 0;
   return (c);
This page took 0.024799 seconds and 4 git commands to generate.