* breakpoint.c, breakpoint.h (breakpoint_init_inferior): New function
[deliverable/binutils-gdb.git] / gdb / c-exp.y
index 1129cf60f5959c6c33bf986cf61e9d57833f0c63..1ab991c14c205ba060400c68bc82fc8e8117ffa0 100644 (file)
@@ -43,9 +43,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "language.h"
 #include "c-lang.h"
 
-/* These MUST be included in any grammar file!!!! Please choose unique names!
-   Note that this are a combined list of variables that can be produced
-   by any one of bison, byacc, or yacc. */
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+   as well as gratuitiously global symbol names, so we can have multiple
+   yacc generated parsers in gdb.  Note that these are only the variables
+   produced by yacc.  If other parser generators (bison, byacc, etc) produce
+   additional global names that conflict at link time, then those parser
+   generators need to be fixed instead of adding those names to this list. */
+
 #define        yymaxdepth c_maxdepth
 #define        yyparse c_parse
 #define        yylex   c_lex
@@ -73,22 +77,22 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define        yy_yyv  c_yyv
 #define        yyval   c_val
 #define        yylloc  c_lloc
-#define yyss   c_yyss          /* byacc */
-#define        yyssp   c_yysp          /* byacc */
-#define        yyvs    c_yyvs          /* byacc */
-#define        yyvsp   c_yyvsp         /* byacc */
+#define yyreds c_reds          /* With YYDEBUG defined */
+#define yytoks c_toks          /* With YYDEBUG defined */
+
+#ifndef YYDEBUG
+#define        YYDEBUG 0               /* Default to no yydebug support */
+#endif
 
 int
 yyparse PARAMS ((void));
 
-int
+static int
 yylex PARAMS ((void));
 
 void
 yyerror PARAMS ((char *));
 
-/* #define     YYDEBUG 1 */
-
 %}
 
 /* Although the yacc "value" of an expression is not used,
@@ -98,7 +102,6 @@ yyerror PARAMS ((char *));
 %union
   {
     LONGEST lval;
-    unsigned LONGEST ulval;
     struct {
       LONGEST val;
       struct type *type;
@@ -124,7 +127,8 @@ static int
 parse_number PARAMS ((char *, int, int, YYSTYPE *));
 %}
 
-%type <voidval> exp exp1 type_exp start variable qualified_name
+%type <voidval> exp exp1 type_exp start variable qualified_name lcurly
+%type <lval> rcurly
 %type <tval> type typebase
 %type <tvec> nonempty_typelist
 /* %type <bval> block */
@@ -303,6 +307,10 @@ exp        :       exp '('
                          write_exp_elt_opcode (OP_FUNCALL); }
        ;
 
+lcurly :       '{'
+                       { start_arglist (); }
+       ;
+
 arglist        :
        ;
 
@@ -314,7 +322,17 @@ arglist    :       arglist ',' exp   %prec ABOVE_COMMA
                        { arglist_len++; }
        ;
 
-exp    :       '{' type '}' exp  %prec UNARY
+rcurly :       '}'
+                       { $$ = end_arglist () - 1; }
+       ;
+exp    :       lcurly arglist rcurly   %prec ARROW
+                       { write_exp_elt_opcode (OP_ARRAY);
+                         write_exp_elt_longcst ((LONGEST) 0);
+                         write_exp_elt_longcst ((LONGEST) $3);
+                         write_exp_elt_opcode (OP_ARRAY); }
+       ;
+
+exp    :       lcurly type rcurly exp  %prec UNARY
                        { write_exp_elt_opcode (UNOP_MEMVAL);
                          write_exp_elt_type ($2);
                          write_exp_elt_opcode (UNOP_MEMVAL); }
@@ -476,9 +494,27 @@ exp        :       SIZEOF '(' type ')'     %prec UNARY
        ;
 
 exp    :       STRING
-                       { write_exp_elt_opcode (OP_STRING);
-                         write_exp_string ($1);
-                         write_exp_elt_opcode (OP_STRING); }
+                       { /* C strings are converted into array constants with
+                            an explicit null byte added at the end.  Thus
+                            the array upper bound is the string length.
+                            There is no such thing in C as a completely empty
+                            string. */
+                         char *sp = $1.ptr; int count = $1.length;
+                         while (count-- > 0)
+                           {
+                             write_exp_elt_opcode (OP_LONG);
+                             write_exp_elt_type (builtin_type_char);
+                             write_exp_elt_longcst ((LONGEST)(*sp++));
+                             write_exp_elt_opcode (OP_LONG);
+                           }
+                         write_exp_elt_opcode (OP_LONG);
+                         write_exp_elt_type (builtin_type_char);
+                         write_exp_elt_longcst ((LONGEST)'\0');
+                         write_exp_elt_opcode (OP_LONG);
+                         write_exp_elt_opcode (OP_ARRAY);
+                         write_exp_elt_longcst ((LONGEST) 0);
+                         write_exp_elt_longcst ((LONGEST) ($1.length));
+                         write_exp_elt_opcode (OP_ARRAY); }
        ;
 
 /* C++.  */
@@ -510,7 +546,8 @@ block       :       BLOCKNAME
 block  :       block COLONCOLON name
                        { struct symbol *tem
                            = lookup_symbol (copy_name ($3), $1,
-                                            VAR_NAMESPACE, 0, NULL);
+                                            VAR_NAMESPACE, (int *) NULL,
+                                            (struct symtab **) NULL);
                          if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
                            error ("No function \"%s\" in specified context.",
                                   copy_name ($3));
@@ -520,12 +557,15 @@ block     :       block COLONCOLON name
 variable:      block COLONCOLON name
                        { struct symbol *sym;
                          sym = lookup_symbol (copy_name ($3), $1,
-                                              VAR_NAMESPACE, 0, NULL);
+                                              VAR_NAMESPACE, (int *) NULL,
+                                              (struct symtab **) NULL);
                          if (sym == 0)
                            error ("No symbol \"%s\" in specified context.",
                                   copy_name ($3));
 
                          write_exp_elt_opcode (OP_VAR_VALUE);
+                         /* block_found is set by lookup_symbol.  */
+                         write_exp_elt_block (block_found);
                          write_exp_elt_sym (sym);
                          write_exp_elt_opcode (OP_VAR_VALUE); }
        ;
@@ -576,10 +616,13 @@ variable: qualified_name
                          struct minimal_symbol *msymbol;
 
                          sym =
-                           lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
+                           lookup_symbol (name, (const struct block *) NULL,
+                                          VAR_NAMESPACE, (int *) NULL,
+                                          (struct symtab **) NULL);
                          if (sym)
                            {
                              write_exp_elt_opcode (OP_VAR_VALUE);
+                             write_exp_elt_block (NULL);
                              write_exp_elt_sym (sym);
                              write_exp_elt_opcode (OP_VAR_VALUE);
                              break;
@@ -590,7 +633,7 @@ variable:   qualified_name
                          if (msymbol != NULL)
                            {
                              write_exp_elt_opcode (OP_LONG);
-                             write_exp_elt_type (builtin_type_int);
+                             write_exp_elt_type (builtin_type_long);
                              write_exp_elt_longcst ((LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
                              write_exp_elt_opcode (OP_LONG);
                              write_exp_elt_opcode (UNOP_MEMVAL);
@@ -622,8 +665,11 @@ variable:  name_not_typename
                                case LOC_ARG:
                                case LOC_REF_ARG:
                                case LOC_REGPARM:
+                               case LOC_REGPARM_ADDR:
                                case LOC_LOCAL:
                                case LOC_LOCAL_ARG:
+                               case LOC_BASEREG:
+                               case LOC_BASEREG_ARG:
                                  if (innermost_block == 0 ||
                                      contained_in (block_found, 
                                                    innermost_block))
@@ -635,6 +681,7 @@ variable:   name_not_typename
                                case LOC_LABEL:
                                case LOC_BLOCK:
                                case LOC_CONST_BYTES:
+                               case LOC_OPTIMIZED_OUT:
 
                                  /* In this case the expression can
                                     be evaluated regardless of what
@@ -648,6 +695,10 @@ variable:  name_not_typename
                                  break;
                                }
                              write_exp_elt_opcode (OP_VAR_VALUE);
+                             /* We want to use the selected frame, not
+                                another more inner frame which happens to
+                                be in the same block.  */
+                             write_exp_elt_block (NULL);
                              write_exp_elt_sym (sym);
                              write_exp_elt_opcode (OP_VAR_VALUE);
                            }
@@ -675,7 +726,7 @@ variable:   name_not_typename
                              if (msymbol != NULL)
                                {
                                  write_exp_elt_opcode (OP_LONG);
-                                 write_exp_elt_type (builtin_type_int);
+                                 write_exp_elt_type (builtin_type_long);
                                  write_exp_elt_longcst ((LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
                                  write_exp_elt_opcode (OP_LONG);
                                  write_exp_elt_opcode (UNOP_MEMVAL);
@@ -920,12 +971,12 @@ parse_number (p, len, parsed_float, putithere)
 {
   register LONGEST n = 0;
   register LONGEST prevn = 0;
-  register int i;
+  register int i = 0;
   register int c;
   register int base = input_radix;
   int unsigned_p = 0;
   int long_p = 0;
-  LONGEST high_bit;
+  unsigned LONGEST high_bit;
   struct type *signed_type;
   struct type *unsigned_type;
 
@@ -1006,17 +1057,26 @@ parse_number (p, len, parsed_float, putithere)
      /* If the number is too big to be an int, or it's got an l suffix
        then it's a long.  Work out if this has to be a long by
        shifting right and and seeing if anything remains, and the
-       target int size is different to the target long size. */
-
-    if ((TARGET_INT_BIT != TARGET_LONG_BIT && (n >> TARGET_INT_BIT)) || long_p)
+       target int size is different to the target long size.
+
+       In the expression below, we could have tested
+               (n >> TARGET_INT_BIT)
+       to see if it was zero,
+       but too many compilers warn about that, when ints and longs
+       are the same size.  So we shift it twice, with fewer bits
+       each time, for the same result.  */
+
+    if (   (TARGET_INT_BIT != TARGET_LONG_BIT 
+            && ((n >> 2) >> (TARGET_INT_BIT-2)))   /* Avoid shift warning */
+        || long_p)
       {
-         high_bit = ((LONGEST)1) << (TARGET_LONG_BIT-1);
+         high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
         unsigned_type = builtin_type_unsigned_long;
         signed_type = builtin_type_long;
       }
     else 
       {
-        high_bit = ((LONGEST)1) << (TARGET_INT_BIT-1);
+        high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
         unsigned_type = builtin_type_unsigned_int;
         signed_type = builtin_type_int;
       }    
@@ -1077,7 +1137,7 @@ static const struct token tokentab2[] =
 
 /* Read one token, getting characters through lexptr.  */
 
-int
+static int
 yylex ()
 {
   int c;
@@ -1094,7 +1154,7 @@ yylex ()
   tokstart = lexptr;
   /* See if it is a special token of length 3.  */
   for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
-    if (!strncmp (tokstart, tokentab3[i].operator, 3))
+    if (STREQN (tokstart, tokentab3[i].operator, 3))
       {
        lexptr += 3;
        yylval.opcode = tokentab3[i].opcode;
@@ -1103,7 +1163,7 @@ yylex ()
 
   /* See if it is a special token of length 2.  */
   for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
-    if (!strncmp (tokstart, tokentab2[i].operator, 2))
+    if (STREQN (tokstart, tokentab2[i].operator, 2))
       {
        lexptr += 2;
        yylval.opcode = tokentab2[i].opcode;
@@ -1140,6 +1200,8 @@ yylex ()
          if (namelen > 2)
            {
              lexptr = tokstart + namelen;
+             if (lexptr[-1] != '\'')
+               error ("Unmatched single quote.");
              namelen -= 2;
              tokstart++;
              goto tryname;
@@ -1201,9 +1263,14 @@ yylex ()
 
        for (;; ++p)
          {
+           /* This test includes !hex because 'e' is a valid hex digit
+              and thus does not indicate a floating point number when
+              the radix is hex.  */
            if (!hex && !got_e && (*p == 'e' || *p == 'E'))
              got_dot = got_e = 1;
-           else if (!hex && !got_dot && *p == '.')
+           /* This test does not include !hex, because a '.' always indicates
+              a decimal floating point number regardless of the radix.  */
+           else if (!got_dot && *p == '.')
              got_dot = 1;
            else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
                     && (*p == '-' || *p == '+'))
@@ -1369,14 +1436,14 @@ yylex ()
   if (*tokstart == '$') {
     for (c = 0; c < NUM_REGS; c++)
       if (namelen - 1 == strlen (reg_names[c])
-         && !strncmp (tokstart + 1, reg_names[c], namelen - 1))
+         && STREQN (tokstart + 1, reg_names[c], namelen - 1))
        {
          yylval.lval = c;
          return REGNAME;
        }
     for (c = 0; c < num_std_regs; c++)
      if (namelen - 1 == strlen (std_regs[c].name)
-        && !strncmp (tokstart + 1, std_regs[c].name, namelen - 1))
+        && STREQN (tokstart + 1, std_regs[c].name, namelen - 1))
        {
         yylval.lval = std_regs[c].regnum;
         return REGNAME;
@@ -1386,51 +1453,52 @@ yylex ()
   switch (namelen)
     {
     case 8:
-      if (!strncmp (tokstart, "unsigned", 8))
+      if (STREQN (tokstart, "unsigned", 8))
        return UNSIGNED;
       if (current_language->la_language == language_cplus
-         && !strncmp (tokstart, "template", 8))
+         && STREQN (tokstart, "template", 8))
        return TEMPLATE;
-      if (!strncmp (tokstart, "volatile", 8))
+      if (STREQN (tokstart, "volatile", 8))
        return VOLATILE_KEYWORD;
       break;
     case 6:
-      if (!strncmp (tokstart, "struct", 6))
+      if (STREQN (tokstart, "struct", 6))
        return STRUCT;
-      if (!strncmp (tokstart, "signed", 6))
+      if (STREQN (tokstart, "signed", 6))
        return SIGNED_KEYWORD;
-      if (!strncmp (tokstart, "sizeof", 6))      
+      if (STREQN (tokstart, "sizeof", 6))      
        return SIZEOF;
       break;
     case 5:
       if (current_language->la_language == language_cplus
-         && !strncmp (tokstart, "class", 5))
+         && STREQN (tokstart, "class", 5))
        return CLASS;
-      if (!strncmp (tokstart, "union", 5))
+      if (STREQN (tokstart, "union", 5))
        return UNION;
-      if (!strncmp (tokstart, "short", 5))
+      if (STREQN (tokstart, "short", 5))
        return SHORT;
-      if (!strncmp (tokstart, "const", 5))
+      if (STREQN (tokstart, "const", 5))
        return CONST_KEYWORD;
       break;
     case 4:
-      if (!strncmp (tokstart, "enum", 4))
+      if (STREQN (tokstart, "enum", 4))
        return ENUM;
-      if (!strncmp (tokstart, "long", 4))
+      if (STREQN (tokstart, "long", 4))
        return LONG;
       if (current_language->la_language == language_cplus
-         && !strncmp (tokstart, "this", 4))
+         && STREQN (tokstart, "this", 4))
        {
          static const char this_name[] =
                                 { CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
 
          if (lookup_symbol (this_name, expression_context_block,
-                            VAR_NAMESPACE, 0, NULL))
+                            VAR_NAMESPACE, (int *) NULL,
+                            (struct symtab **) NULL))
            return THIS;
        }
       break;
     case 3:
-      if (!strncmp (tokstart, "int", 3))
+      if (STREQN (tokstart, "int", 3))
        return INT_KEYWORD;
       break;
     default:
@@ -1462,8 +1530,8 @@ yylex ()
     sym = lookup_symbol (tmp, expression_context_block,
                         VAR_NAMESPACE,
                         current_language->la_language == language_cplus
-                        ? &is_a_field_of_this : NULL,
-                        NULL);
+                        ? &is_a_field_of_this : (int *) NULL,
+                        (struct symtab **) NULL);
     if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ||
         lookup_partial_symtab (tmp))
       {
@@ -1473,7 +1541,73 @@ yylex ()
       }
     if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
         {
-         yylval.tsym.type = SYMBOL_TYPE (sym);
+         char *p;
+         char *namestart;
+         struct symbol *best_sym;
+
+         /* Look ahead to detect nested types.  This probably should be
+            done in the grammar, but trying seemed to introduce a lot
+            of shift/reduce and reduce/reduce conflicts.  It's possible
+            that it could be done, though.  Or perhaps a non-grammar, but
+            less ad hoc, approach would work well.  */
+
+         /* Since we do not currently have any way of distinguishing
+            a nested type from a non-nested one (the stabs don't tell
+            us whether a type is nested), we just ignore the
+            containing type.  */
+
+         p = lexptr;
+         best_sym = sym;
+         while (1)
+           {
+             /* Skip whitespace.  */
+             while (*p == ' ' || *p == '\t' || *p == '\n')
+               ++p;
+             if (*p == ':' && p[1] == ':')
+               {
+                 /* Skip the `::'.  */
+                 p += 2;
+                 /* Skip whitespace.  */
+                 while (*p == ' ' || *p == '\t' || *p == '\n')
+                   ++p;
+                 namestart = p;
+                 while (*p == '_' || *p == '$' || (*p >= '0' && *p <= '9')
+                        || (*p >= 'a' && *p <= 'z')
+                        || (*p >= 'A' && *p <= 'Z'))
+                   ++p;
+                 if (p != namestart)
+                   {
+                     struct symbol *cur_sym;
+                     /* As big as the whole rest of the expression, which is
+                        at least big enough.  */
+                     char *tmp = alloca (strlen (namestart));
+
+                     memcpy (tmp, namestart, p - namestart);
+                     tmp[p - namestart] = '\0';
+                     cur_sym = lookup_symbol (tmp, expression_context_block,
+                                              VAR_NAMESPACE, (int *) NULL,
+                                              (struct symtab **) NULL);
+                     if (cur_sym)
+                       {
+                         if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF)
+                           {
+                             best_sym = cur_sym;
+                             lexptr = p;
+                           }
+                         else
+                           break;
+                       }
+                     else
+                       break;
+                   }
+                 else
+                   break;
+               }
+             else
+               break;
+           }
+
+         yylval.tsym.type = SYMBOL_TYPE (best_sym);
          return TYPENAME;
         }
     if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
This page took 0.029051 seconds and 4 git commands to generate.