Add self to MAINTAINERS.
[deliverable/binutils-gdb.git] / gdb / c-exp.y
index 4b40eb04e05057cdf9d5fa657cfe0eea601bb81c..ea5083646e0ef785a41e17281206659ad0d80f57 100644 (file)
@@ -1,5 +1,6 @@
 /* YACC parser for C expressions, for GDB.
-   Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1996, 1997
+   Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000
    Free Software Foundation, Inc.
 
 This file is part of GDB.
@@ -49,6 +50,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "symfile.h" /* Required by objfiles.h.  */
 #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
 
+/* Flag indicating we're dealing with HP-compiled objects */ 
+extern int hp_som_som_object_present;
+
 /* 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
@@ -96,17 +100,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #define yycheck         c_yycheck
 
 #ifndef YYDEBUG
-#define        YYDEBUG 0               /* Default to no yydebug support */
+#define        YYDEBUG 1               /* Default to yydebug support */
 #endif
 
-int
-yyparse PARAMS ((void));
+#define YYFPRINTF parser_fprintf
 
-static int
-yylex PARAMS ((void));
+int yyparse (void);
 
-void
-yyerror PARAMS ((char *));
+static int yylex (void);
+
+void yyerror (char *);
 
 %}
 
@@ -141,8 +144,7 @@ yyerror PARAMS ((char *));
 
 %{
 /* YYSTYPE gets defined by %union */
-static int
-parse_number PARAMS ((char *, int, int, YYSTYPE *));
+static int parse_number (char *, int, int, YYSTYPE *);
 %}
 
 %type <voidval> exp exp1 type_exp start variable qualified_name lcurly
@@ -195,6 +197,9 @@ parse_number PARAMS ((char *, int, int, YYSTYPE *));
 
 /* C++ */
 %token THIS
+%token TRUEKEYWORD
+%token FALSEKEYWORD
+
 
 %left ','
 %left ABOVE_COMMA
@@ -289,6 +294,7 @@ exp :       exp ARROW qualified_name
                          write_exp_elt_opcode (UNOP_ADDR);
                          write_exp_elt_opcode (STRUCTOP_MPTR); }
        ;
+
 exp    :       exp ARROW '*' exp
                        { write_exp_elt_opcode (STRUCTOP_MPTR); }
        ;
@@ -528,6 +534,20 @@ exp        :       THIS
                          write_exp_elt_opcode (OP_THIS); }
        ;
 
+exp     :       TRUEKEYWORD    
+                        { write_exp_elt_opcode (OP_LONG);
+                          write_exp_elt_type (builtin_type_bool);
+                          write_exp_elt_longcst ((LONGEST) 1);
+                          write_exp_elt_opcode (OP_LONG); }
+       ;
+
+exp     :       FALSEKEYWORD   
+                        { write_exp_elt_opcode (OP_LONG);
+                          write_exp_elt_type (builtin_type_bool);
+                          write_exp_elt_longcst ((LONGEST) 0);
+                          write_exp_elt_opcode (OP_LONG); }
+       ;
+
 /* end of C++.  */
 
 block  :       BLOCKNAME
@@ -700,21 +720,26 @@ variable: name_not_typename
                        }
        ;
 
+space_identifier : '@' NAME
+               { push_type_address_space (copy_name ($2.stoken));
+                 push_type (tp_space_identifier);
+               }
+       ;
 
-ptype  :       typebase
-       /* "const" and "volatile" are curently ignored.  A type qualifier
-          before the type is currently handled in the typebase rule.
-          The reason for recognizing these here (shift/reduce conflicts)
-          might be obsolete now that some pointer to member rules have
-          been deleted.  */
-       |       typebase CONST_KEYWORD
-       |       typebase VOLATILE_KEYWORD
-       |       typebase abs_decl
-               { $$ = follow_types ($1); }
-       |       typebase CONST_KEYWORD abs_decl
-               { $$ = follow_types ($1); }
-       |       typebase VOLATILE_KEYWORD abs_decl
-               { $$ = follow_types ($1); }
+const_or_volatile: const_or_volatile_noopt
+       |
+       ;
+
+cv_with_space_id : const_or_volatile space_identifier const_or_volatile
+       ;
+
+const_or_volatile_or_space_identifier_noopt: cv_with_space_id
+       | const_or_volatile_noopt 
+       ;
+
+const_or_volatile_or_space_identifier: 
+               const_or_volatile_or_space_identifier_noopt
+       |
        ;
 
 abs_decl:      '*'
@@ -784,20 +809,52 @@ typebase  /* Implements (approximately): (type-qualifier)* type-specifier */
                        { $$ = builtin_type_short; }
        |       LONG INT_KEYWORD
                        { $$ = builtin_type_long; }
+       |       LONG SIGNED_KEYWORD INT_KEYWORD
+                       { $$ = builtin_type_long; }
+       |       LONG SIGNED_KEYWORD
+                       { $$ = builtin_type_long; }
+       |       SIGNED_KEYWORD LONG INT_KEYWORD
+                       { $$ = builtin_type_long; }
        |       UNSIGNED LONG INT_KEYWORD
                        { $$ = builtin_type_unsigned_long; }
+       |       LONG UNSIGNED INT_KEYWORD
+                       { $$ = builtin_type_unsigned_long; }
+       |       LONG UNSIGNED
+                       { $$ = builtin_type_unsigned_long; }
        |       LONG LONG
                        { $$ = builtin_type_long_long; }
        |       LONG LONG INT_KEYWORD
                        { $$ = builtin_type_long_long; }
+       |       LONG LONG SIGNED_KEYWORD INT_KEYWORD
+                       { $$ = builtin_type_long_long; }
+       |       LONG LONG SIGNED_KEYWORD
+                       { $$ = builtin_type_long_long; }
+       |       SIGNED_KEYWORD LONG LONG
+                       { $$ = builtin_type_long_long; }
        |       UNSIGNED LONG LONG
                        { $$ = builtin_type_unsigned_long_long; }
        |       UNSIGNED LONG LONG INT_KEYWORD
                        { $$ = builtin_type_unsigned_long_long; }
+       |       LONG LONG UNSIGNED
+                       { $$ = builtin_type_unsigned_long_long; }
+       |       LONG LONG UNSIGNED INT_KEYWORD
+                       { $$ = builtin_type_unsigned_long_long; }
+       |       SIGNED_KEYWORD LONG LONG
+                       { $$ = lookup_signed_typename ("long long"); }
+       |       SIGNED_KEYWORD LONG LONG INT_KEYWORD
+                       { $$ = lookup_signed_typename ("long long"); }
        |       SHORT INT_KEYWORD
                        { $$ = builtin_type_short; }
+       |       SHORT SIGNED_KEYWORD INT_KEYWORD
+                       { $$ = builtin_type_short; }
+       |       SHORT SIGNED_KEYWORD
+                       { $$ = builtin_type_short; }
        |       UNSIGNED SHORT INT_KEYWORD
                        { $$ = builtin_type_unsigned_short; }
+       |       SHORT UNSIGNED 
+                       { $$ = builtin_type_unsigned_short; }
+       |       SHORT UNSIGNED INT_KEYWORD
+                       { $$ = builtin_type_unsigned_short; }
        |       DOUBLE_KEYWORD
                        { $$ = builtin_type_double; }
        |       LONG DOUBLE_KEYWORD
@@ -822,15 +879,17 @@ typebase  /* Implements (approximately): (type-qualifier)* type-specifier */
                        { $$ = lookup_signed_typename (TYPE_NAME($2.type)); }
        |       SIGNED_KEYWORD
                        { $$ = builtin_type_int; }
+                /* It appears that this rule for templates is never
+                   reduced; template recognition happens by lookahead
+                   in the token processing code in yylex. */         
        |       TEMPLATE name '<' type '>'
                        { $$ = lookup_template_type(copy_name($2), $4,
                                                    expression_context_block);
                        }
-       /* "const" and "volatile" are curently ignored.  A type qualifier
-          after the type is handled in the ptype rule.  I think these could
-          be too.  */
-       |       CONST_KEYWORD typebase { $$ = $2; }
-       |       VOLATILE_KEYWORD typebase { $$ = $2; }
+       | const_or_volatile_or_space_identifier_noopt typebase 
+                       { $$ = follow_types ($2); }
+       | typebase const_or_volatile_or_space_identifier_noopt 
+                       { $$ = follow_types ($1); }
        ;
 
 typename:      TYPENAME
@@ -867,6 +926,25 @@ nonempty_typelist
                }
        ;
 
+ptype  :       typebase
+       |       ptype const_or_volatile_or_space_identifier abs_decl const_or_volatile_or_space_identifier
+               { $$ = follow_types ($1); }
+       ;
+
+const_and_volatile:    CONST_KEYWORD VOLATILE_KEYWORD
+       |               VOLATILE_KEYWORD CONST_KEYWORD
+       ;
+
+const_or_volatile_noopt:       const_and_volatile 
+                       { push_type (tp_const);
+                         push_type (tp_volatile); 
+                       }
+       |               CONST_KEYWORD
+                       { push_type (tp_const); }
+       |               VOLATILE_KEYWORD
+                       { push_type (tp_volatile); }
+       ;
+
 name   :       NAME { $$ = $1.stoken; }
        |       BLOCKNAME { $$ = $1.stoken; }
        |       TYPENAME { $$ = $1.stoken; }
@@ -1163,9 +1241,27 @@ yylex ()
   int tempbufindex;
   static char *tempbuf;
   static int tempbufsize;
-  
+  struct symbol * sym_class = NULL;
+  char * token_string = NULL;
+  int class_prefix = 0;
+  int unquoted_expr;
+   
  retry:
 
+  /* Check if this is a macro invocation that we need to expand.  */
+  if (! scanning_macro_expansion ())
+    {
+      char *expanded = macro_expand_next (&lexptr,
+                                          expression_macro_lookup_func,
+                                          expression_macro_lookup_baton);
+
+      if (expanded)
+        scan_macro_expansion (expanded);
+    }
+
+  prev_lexptr = lexptr;
+  unquoted_expr = 1;
+
   tokstart = lexptr;
   /* See if it is a special token of length 3.  */
   for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
@@ -1188,7 +1284,17 @@ yylex ()
   switch (c = *tokstart)
     {
     case 0:
-      return 0;
+      /* If we were just scanning the result of a macro expansion,
+         then we need to resume scanning the original text.
+         Otherwise, we were already scanning the original text, and
+         we're really done.  */
+      if (scanning_macro_expansion ())
+        {
+          finished_macro_expansion ();
+          goto retry;
+        }
+      else
+        return 0;
 
     case ' ':
     case '\t':
@@ -1217,6 +1323,7 @@ yylex ()
          if (namelen > 2)
            {
              lexptr = tokstart + namelen;
+              unquoted_expr = 0;
              if (lexptr[-1] != '\'')
                error ("Unmatched single quote.");
              namelen -= 2;
@@ -1240,7 +1347,9 @@ yylex ()
       return c;
 
     case ',':
-      if (comma_terminates && paren_depth == 0)
+      if (comma_terminates
+          && paren_depth == 0
+          && ! scanning_macro_expansion ())
        return 0;
       lexptr++;
       return c;
@@ -1405,30 +1514,27 @@ yylex ()
         FIXME: This mishandles `print $a<4&&$a>3'.  */
 
       if (c == '<')
-       {
-         int i = namelen;
-         int nesting_level = 1;
-         while (tokstart[++i])
-           {
-             if (tokstart[i] == '<')
-               nesting_level++;
-             else if (tokstart[i] == '>')
-               {
-                 if (--nesting_level == 0)
-                   break;
-               }
-           }
-         if (tokstart[i] == '>')
-           namelen = i;
-         else
-           break;
+       { 
+               /* Scan ahead to get rest of the template specification.  Note
+                  that we look ahead only when the '<' adjoins non-whitespace
+                  characters; for comparison expressions, e.g. "a < b > c",
+                  there must be spaces before the '<', etc. */
+               
+               char * p = find_template_name_end (tokstart + namelen);
+               if (p)
+                 namelen = p - tokstart;
+               break;
        }
       c = tokstart[++namelen];
     }
 
-  /* The token "if" terminates the expression and is NOT 
-     removed from the input stream.  */
-  if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+  /* The token "if" terminates the expression and is NOT removed from
+     the input stream.  It doesn't count if it appears in the
+     expansion of a macro.  */
+  if (namelen == 2
+      && tokstart[0] == 'i'
+      && tokstart[1] == 'f'
+      && ! scanning_macro_expansion ())
     {
       return 0;
     }
@@ -1460,9 +1566,13 @@ yylex ()
        return DOUBLE_KEYWORD;
       break;
     case 5:
-      if (current_language->la_language == language_cplus
-         && STREQN (tokstart, "class", 5))
-       return CLASS;
+      if (current_language->la_language == language_cplus)
+        {
+          if (STREQN (tokstart, "false", 5))
+            return FALSEKEYWORD;
+          if (STREQN (tokstart, "class", 5))
+            return CLASS;
+        }
       if (STREQN (tokstart, "union", 5))
        return UNION;
       if (STREQN (tokstart, "short", 5))
@@ -1475,17 +1585,22 @@ yylex ()
        return ENUM;
       if (STREQN (tokstart, "long", 4))
        return LONG;
-      if (current_language->la_language == language_cplus
-         && 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, (int *) NULL,
-                            (struct symtab **) NULL))
-           return THIS;
-       }
+      if (current_language->la_language == language_cplus)
+          {
+            if (STREQN (tokstart, "true", 4))
+              return TRUEKEYWORD;
+
+            if (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, (int *) NULL,
+                                   (struct symtab **) NULL))
+                  return THIS;
+              }
+          }
       break;
     case 3:
       if (STREQN (tokstart, "int", 3))
@@ -1503,7 +1618,25 @@ yylex ()
       write_dollar_variable (yylval.sval);
       return VARIABLE;
     }
-
+  
+  /* Look ahead and see if we can consume more of the input
+     string to get a reasonable class/namespace spec or a
+     fully-qualified name.  This is a kludge to get around the
+     HP aCC compiler's generation of symbol names with embedded
+     colons for namespace and nested classes. */ 
+  if (unquoted_expr)
+    {
+      /* Only do it if not inside single quotes */ 
+      sym_class = parse_nested_classes_for_hpacc (yylval.sval.ptr, yylval.sval.length,
+                                                  &token_string, &class_prefix, &lexptr);
+      if (sym_class)
+        {
+          /* Replace the current token with the bigger one we found */ 
+          yylval.sval.ptr = token_string;
+          yylval.sval.length = strlen (token_string);
+        }
+    }
+  
   /* Use token-type BLOCKNAME for symbols that happen to be defined as
      functions or symtabs.  If this is not so, then ...
      Use token-type TYPENAME for symbols that happen to be defined
@@ -1633,7 +1766,7 @@ yylex ()
          return TYPENAME;
         }
     if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
-       return TYPENAME;
+      return TYPENAME;
 
     /* Input names that aren't symbols but ARE valid hex numbers,
        when the input radix permits them, can be names or numbers
@@ -1663,5 +1796,8 @@ void
 yyerror (msg)
      char *msg;
 {
+  if (prev_lexptr)
+    lexptr = prev_lexptr;
+
   error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
 }
This page took 0.079531 seconds and 4 git commands to generate.