]> Git Repo - binutils.git/blobdiff - gdb/ch-exp.c
* gdb/gdbserver/Makefile.in (docdir): Removed.
[binutils.git] / gdb / ch-exp.c
index 31c92b5e2478f766e18464edff8d900b06e6a9dc..db1188faac1eef82f37a3acdce92bbd32f9aee0a 100644 (file)
@@ -26,15 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
    during the process of parsing; the lower levels of the tree always
    come first in the result.
 
-   Note that malloc's and realloc's in this file are transformed to
-   xmalloc and xrealloc respectively by the same sed command in the
-   makefile that remaps any other malloc/realloc inserted by the parser
-   generator.  Doing this with #defines and trying to control the interaction
-   with include files (<malloc.h> and <stdlib.h> for example) just became
-   too messy, particularly when such includes can be inserted at random
-   times by the parser generator.
-
-   Also note that the language accepted by this parser is more liberal
+   Note that the language accepted by this parser is more liberal
    than the one accepted by an actual Chill compiler.  For example, the
    language rule that a simple name string can not be one of the reserved
    simple name strings is not enforced (e.g "case" is not treated as a
@@ -52,7 +44,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  */
 
 #include "defs.h"
-#include <string.h>
+#include "gdb_string.h"
 #include <ctype.h>
 #include "expression.h"
 #include "language.h"
@@ -83,6 +75,7 @@ typedef union
 enum ch_terminal {
   END_TOKEN = 0,
   /* '\001' ... '\xff' come first. */
+  OPEN_PAREN = '(',
   TOKEN_NOT_READ = 999,
   INTEGER_LITERAL,
   BOOLEAN_LITERAL,
@@ -145,6 +138,7 @@ static int parse_opt_untyped_expr ();
 static void parse_if_expression_body PARAMS((void));
 static void write_lower_upper_value PARAMS ((enum exp_opcode, struct type *));
 static enum ch_terminal ch_lex ();
+static void calculate_array_length PARAMS ((struct type *));
 
 #define MAX_LOOK_AHEAD 2
 static enum ch_terminal terminal_buffer[MAX_LOOK_AHEAD+1] = {
@@ -184,6 +178,8 @@ peek_token_ (i)
   return terminal_buffer[i];
 }
 
+#if 0
+
 static void
 pushback_token (code, node)
      enum ch_terminal code;
@@ -201,6 +197,8 @@ pushback_token (code, node)
   val_buffer[0] = node;
 }
 
+#endif
+
 static void
 forward_token_()
 {
@@ -579,6 +577,11 @@ parse_tuple (mode)
   write_exp_elt_opcode (OP_ARRAY);
   if (mode)
     {
+      struct type *type = check_typedef (mode);
+      if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+         && TYPE_CODE (type) != TYPE_CODE_STRUCT
+         && TYPE_CODE (type) != TYPE_CODE_SET)
+       error ("invalid tuple mode");
       write_exp_elt_opcode (UNOP_CAST);
       write_exp_elt_type (mode);
       write_exp_elt_opcode (UNOP_CAST);
@@ -642,6 +645,7 @@ parse_primval ()
       if (PEEK_TOKEN () != TYPENAME)
        error ("missing MODENAME after ARRAY()");
       type = PEEK_LVAL().tsym.type;
+      FORWARD_TOKEN ();
       expect ('(', NULL);
       parse_expr ();
       expect (')', "missing right parenthesis");
@@ -670,11 +674,20 @@ parse_primval ()
       break;
     case GENERAL_PROCEDURE_NAME:
     case LOCATION_NAME:
-      write_exp_elt_opcode (OP_VAR_VALUE);
-      write_exp_elt_block (NULL);
-      write_exp_elt_sym (PEEK_LVAL ().ssym.sym);
-      write_exp_elt_opcode (OP_VAR_VALUE);
-      FORWARD_TOKEN ();
+      {
+       struct type *type;
+
+       /* FIXME: look at calculate_array_length */
+       type = PEEK_LVAL().ssym.sym->type;
+       if (type && TYPE_CODE (type) == TYPE_CODE_ARRAY &&
+           TYPE_LENGTH (type) == 0)
+         calculate_array_length (type);
+       write_exp_elt_opcode (OP_VAR_VALUE);
+       write_exp_elt_block (NULL);
+       write_exp_elt_sym (PEEK_LVAL ().ssym.sym);
+       write_exp_elt_opcode (OP_VAR_VALUE);
+       FORWARD_TOKEN ();
+      }
       break;
     case GDB_VARIABLE: /* gdb specific */
       FORWARD_TOKEN ();
@@ -685,12 +698,21 @@ parse_primval ()
       write_exp_elt_type (builtin_type_int);
       write_exp_elt_opcode (UNOP_CAST);
       break;
+    case CARD:
+      parse_unary_call ();
+      write_exp_elt_opcode (UNOP_CARD);
+      break;
+    case MAX_TOKEN:
+      parse_unary_call ();
+      write_exp_elt_opcode (UNOP_CHMAX);
+      break;
+    case MIN_TOKEN:
+      parse_unary_call ();
+      write_exp_elt_opcode (UNOP_CHMIN);
+      break;
     case PRED:      op_name = "PRED"; goto unimplemented_unary_builtin;
     case SUCC:      op_name = "SUCC"; goto unimplemented_unary_builtin;
     case ABS:       op_name = "ABS";  goto unimplemented_unary_builtin;
-    case CARD:      op_name = "CARD"; goto unimplemented_unary_builtin;
-    case MAX_TOKEN: op_name = "MAX";  goto unimplemented_unary_builtin;
-    case MIN_TOKEN: op_name = "MIN";  goto unimplemented_unary_builtin;
     unimplemented_unary_builtin:
       parse_unary_call ();
       error ("not implemented:  %s builtin function", op_name);
@@ -771,7 +793,7 @@ parse_primval ()
            }
          write_exp_elt_opcode (UNOP_IND);
          continue;
-       case '(':
+       case OPEN_PAREN:
          parse_call ();
          continue;
        case CHARACTER_STRING_LITERAL:
@@ -783,6 +805,55 @@ parse_primval ()
          write_exp_elt_longcst (1);
          write_exp_elt_opcode (MULTI_SUBSCRIPT);
          continue;
+       case END_TOKEN:
+       case TOKEN_NOT_READ:
+       case INTEGER_LITERAL:
+       case BOOLEAN_LITERAL:
+       case FLOAT_LITERAL:
+       case GENERAL_PROCEDURE_NAME:
+       case LOCATION_NAME:
+       case EMPTINESS_LITERAL:
+       case TYPENAME:
+       case CASE:
+       case OF:
+       case ESAC:
+       case LOGIOR:
+       case ORIF:
+       case LOGXOR:
+       case LOGAND:
+       case ANDIF:
+       case NOTEQUAL:
+       case GEQ:
+       case LEQ:
+       case IN:
+       case SLASH_SLASH:
+       case MOD:
+       case REM:
+       case NOT:
+       case RECEIVE:
+       case UP:
+       case IF:
+       case THEN:
+       case ELSE:
+       case FI:
+       case ELSIF:
+       case ILLEGAL_TOKEN:
+       case NUM:
+       case PRED:
+       case SUCC:
+       case ABS:
+       case CARD:
+       case MAX_TOKEN:
+       case MIN_TOKEN:
+       case ADDR_TOKEN:
+       case SIZE:
+       case UPPER:
+       case LOWER:
+       case LENGTH:
+       case ARRAY:
+       case GDB_VARIABLE:
+       case GDB_ASSIGNMENT:
+         break;
        }
       break;
     }
@@ -1088,11 +1159,11 @@ growbuf_by_size (count)
   tempbufsize += growby;
   if (tempbuf == NULL)
     {
-      tempbuf = (char *) malloc (tempbufsize);
+      tempbuf = (char *) xmalloc (tempbufsize);
     }
   else
     {
-      tempbuf = (char *) realloc (tempbuf, tempbufsize);
+      tempbuf = (char *) xrealloc (tempbuf, tempbufsize);
     }
 }
 
@@ -1406,23 +1477,67 @@ static enum ch_terminal
 match_string_literal ()
 {
   char *tokptr = lexptr;
+  int in_ctrlseq = 0;
+  LONGEST ival;
 
   for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
     {
       CHECKBUF (1);
-      if (*tokptr == *lexptr)
+    tryagain: ;
+      if (in_ctrlseq)
        {
-         if (*(tokptr + 1) == *lexptr)
+         /* skip possible whitespaces */
+         while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
+           tokptr++;
+         if (*tokptr == ')')
            {
+             in_ctrlseq = 0;
              tokptr++;
+             goto tryagain;
+           }
+         else if (*tokptr != ',')
+           error ("Invalid control sequence");
+         tokptr++;
+         /* skip possible whitespaces */
+         while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
+           tokptr++;
+         if (!decode_integer_literal (&ival, &tokptr))
+           error ("Invalid control sequence");
+         tokptr--;
+       }
+      else if (*tokptr == *lexptr)
+       {
+         if (*(tokptr + 1) == *lexptr)
+           {
+             ival = *tokptr++;
            }
          else
            {
              break;
            }
        }
-      tempbuf[tempbufindex++] = *tokptr;
+      else if (*tokptr == '^')
+       {
+         if (*(tokptr + 1) == '(')
+           {
+             in_ctrlseq = 1;
+             tokptr += 2;
+             if (!decode_integer_literal (&ival, &tokptr))
+               error ("Invalid control sequence");
+             tokptr--;
+           }
+         else if (*(tokptr + 1) == '^')
+           ival = *tokptr++;
+         else
+           error ("Invalid control sequence");
+       }
+      else
+       ival = *tokptr;
+      tempbuf[tempbufindex++] = ival;
     }
+  if (in_ctrlseq)
+    error ("Invalid control sequence");
+
   if (*tokptr == '\0'                                  /* no terminator */
       || (tempbufindex == 1 && *tokptr == '\''))       /* char literal */
     {
@@ -1451,12 +1566,6 @@ match_string_literal ()
    Note that more than a single character, enclosed in single quotes, is
    a string literal.
 
-   Also note that the control sequence form is not in GNU Chill since it
-   is ambiguous with the string literal form using single quotes.  I.E.
-   is '^(7)' a character literal or a string literal.  In theory it it
-   possible to tell by context, but GNU Chill doesn't accept the control
-   sequence form, so neither do we (for now the code is disabled).
-
    Returns CHARACTER_LITERAL if a match is found.
    */
 
@@ -1485,28 +1594,39 @@ match_character_literal ()
       /* Determine which form we have, either a control sequence or the
         single character form. */
       
-      if ((*tokptr == '^') && (*(tokptr + 1) == '('))
+      if (*tokptr == '^')
        {
-#if 0     /* Disable, see note above. -fnf */
-         /* Match and decode a control sequence.  Return zero if we don't
-            find a valid integer literal, or if the next unconsumed character
-            after the integer literal is not the trailing ')'.
-            FIXME:  We currently don't handle the multiple integer literal
-            form. */
-         tokptr += 2;
-         if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')'))
+         if (*(tokptr + 1) == '(')
+           {
+             /* Match and decode a control sequence.  Return zero if we don't
+                find a valid integer literal, or if the next unconsumed character
+                after the integer literal is not the trailing ')'. */
+             tokptr += 2;
+             if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')'))
+               {
+                 return (0);
+               }
+           }
+         else if (*(tokptr + 1) == '^')
            {
-             return (0);
+             ival = *tokptr;
+             tokptr += 2;
            }
-#else
-         return (0);
-#endif
+         else
+           /* fail */
+           error ("Invalid control sequence");
+       }
+      else if (*tokptr == '\'')
+       {
+         /* this must be duplicated */
+         ival = *tokptr;
+         tokptr += 2;
        }
       else
        {
          ival = *tokptr++;
        }
-      
+
       /* The trailing quote has not yet been consumed.  If we don't find
         it, then we have no match. */
       
@@ -1620,7 +1740,8 @@ match_bitstring_literal ()
            digit += 10;
            break;
          default:
-           error ("Invalid character in bitstring or integer.");
+           /* this is not a bitstring literal, probably an integer */
+           return 0;
        }
       if (digit >= 1 << bits_per_char)
        {
@@ -1914,12 +2035,16 @@ ch_lex ()
                break;
              case LOC_TYPEDEF:
                yylval.tsym.type = SYMBOL_TYPE (sym);
+               calculate_array_length (yylval.tsym.type);
                return TYPENAME;
              case LOC_UNDEF:
              case LOC_CONST_BYTES:
              case LOC_OPTIMIZED_OUT:
                error ("Symbol \"%s\" names no location.", inputname);
                break;
+             case LOC_UNRESOLVED:
+               error ("unhandled SYMBOL_CLASS in ch_lex()");
+               break;
              }
          }
        else if (!have_full_symbols () && !have_partial_symbols ())
@@ -1968,6 +2093,49 @@ write_lower_upper_value (opcode, type)
     }
 }
 
+/* In certain cases it could happen, that an array type doesn't
+   have a length (this have to do with seizing). The reason is
+   shown in the following stabs:
+
+   .stabs "m_x:Tt81=s36i:1,0,32;ar:82=ar80;0;1;83=xsm_struct:,32,256;;",128,0,25,0
+  
+   .stabs "m_struct:Tt83=s16f1:9,0,16;f2:85=*84,32,32;f3:84,64,64;;",128,0,10,0
+
+   When processing t81, the array ar80 doesn't have a length, cause
+   struct m_struct is specified extern at thse moment. Afterwards m_struct
+   gets specified and updated, but not the surrounding type.
+
+   So we walk through array's till we find a type with a length and
+   calculate the array length.
+
+   FIXME: Where may this happen too ?
+   */
+
+static void
+calculate_array_length (type)
+     struct type *type;
+{
+  struct type *target_type;
+  struct type *range_type;
+  LONGEST lower_bound, upper_bound;
+
+  if (TYPE_CODE (type) != TYPE_CODE_ARRAY)
+    /* not an array, stop processing */
+    return;
+
+  target_type = TYPE_TARGET_TYPE (type);
+  range_type = TYPE_FIELD_TYPE (type, 0);
+  lower_bound = TYPE_FIELD_BITPOS (range_type, 0);
+  upper_bound = TYPE_FIELD_BITPOS (range_type, 1);
+
+  if (TYPE_LENGTH (target_type) == 0 &&
+      TYPE_CODE (target_type) == TYPE_CODE_ARRAY)
+    /* we've got another array */
+    calculate_array_length (target_type);
+
+  TYPE_LENGTH (type) = (upper_bound - lower_bound + 1) * TYPE_LENGTH (target_type);
+}
+
 void
 chill_error (msg)
      char *msg;
This page took 0.036679 seconds and 4 git commands to generate.