/* YACC parser for C expressions, for GDB.
- Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994
+ Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000
Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Parse a C expression from text in a string,
and return the result as a struct expression pointer.
%{
#include "defs.h"
-#include <string.h>
+#include "gdb_string.h"
+#include <ctype.h>
#include "expression.h"
#include "value.h"
#include "parser-defs.h"
#include "bfd.h" /* Required by objfiles.h. */
#include "symfile.h" /* Required by objfiles.h. */
#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+#include "charset.h"
+#include "block.h"
+
+/* 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
#define yylloc c_lloc
#define yyreds c_reds /* With YYDEBUG defined */
#define yytoks c_toks /* With YYDEBUG defined */
+#define yyname c_name /* With YYDEBUG defined */
+#define yyrule c_rule /* With YYDEBUG defined */
#define yylhs c_yylhs
#define yylen c_yylen
#define yydefred c_yydefred
#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 *);
%}
struct {
LONGEST val;
struct type *type;
- } typed_val;
- double dval;
+ } typed_val_int;
+ struct {
+ DOUBLEST dval;
+ struct type *type;
+ } typed_val_float;
struct symbol *sym;
struct type *tval;
struct stoken sval;
%{
/* 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
%type <tval> ptype
%type <lval> array_mod
-%token <typed_val> INT
-%token <dval> FLOAT
+%token <typed_val_int> INT
+%token <typed_val_float> FLOAT
/* Both NAME and TYPENAME tokens represent symbols in the input,
and both convey their data as strings.
/* Special type cases, put in to allow the parser to distinguish different
legal basetypes. */
-%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD
-%token <lval> LAST REGNAME
+%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD
-%token <ivar> VARIABLE
+%token <voidval> VARIABLE
%token <opcode> ASSIGN_MODIFY
/* C++ */
-%token THIS
+%token TRUEKEYWORD
+%token FALSEKEYWORD
+
%left ','
%left ABOVE_COMMA
%right UNARY INCREMENT DECREMENT
%right ARROW '.' '[' '('
%token <ssym> BLOCKNAME
+%token <bval> FILENAME
%type <bval> block
%left COLONCOLON
/* Expressions, not including the comma operator. */
exp : '*' exp %prec UNARY
{ write_exp_elt_opcode (UNOP_IND); }
+ ;
exp : '&' exp %prec UNARY
{ write_exp_elt_opcode (UNOP_ADDR); }
+ ;
exp : '-' exp %prec UNARY
{ write_exp_elt_opcode (UNOP_NEG); }
write_exp_elt_opcode (UNOP_ADDR);
write_exp_elt_opcode (STRUCTOP_MPTR); }
;
+
exp : exp ARROW '*' exp
{ write_exp_elt_opcode (STRUCTOP_MPTR); }
;
{ YYSTYPE val;
parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type (val.typed_val.type);
- write_exp_elt_longcst ((LONGEST)val.typed_val.val);
+ write_exp_elt_type (val.typed_val_int.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
write_exp_elt_opcode (OP_LONG);
}
;
exp : FLOAT
{ write_exp_elt_opcode (OP_DOUBLE);
- write_exp_elt_type (builtin_type_double);
- write_exp_elt_dblcst ($1);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_dblcst ($1.dval);
write_exp_elt_opcode (OP_DOUBLE); }
;
exp : variable
;
-exp : LAST
- { write_exp_elt_opcode (OP_LAST);
- write_exp_elt_longcst ((LONGEST) $1);
- write_exp_elt_opcode (OP_LAST); }
- ;
-
-exp : REGNAME
- { write_exp_elt_opcode (OP_REGISTER);
- write_exp_elt_longcst ((LONGEST) $1);
- write_exp_elt_opcode (OP_REGISTER); }
- ;
-
exp : VARIABLE
- { write_exp_elt_opcode (OP_INTERNALVAR);
- write_exp_elt_intern ($1);
- write_exp_elt_opcode (OP_INTERNALVAR); }
+ /* Already written by write_dollar_variable. */
;
exp : SIZEOF '(' type ')' %prec UNARY
{ write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
+ CHECK_TYPEDEF ($3);
write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
write_exp_elt_opcode (OP_LONG); }
;
;
/* C++. */
-exp : THIS
- { write_exp_elt_opcode (OP_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
{
- if ($1.sym != 0)
- $$ = SYMBOL_BLOCK_VALUE ($1.sym);
+ if ($1.sym)
+ $$ = SYMBOL_BLOCK_VALUE ($1.sym);
else
- {
- struct symtab *tem =
- lookup_symtab (copy_name ($1.stoken));
- if (tem)
- $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), STATIC_BLOCK);
- else
- error ("No file or function \"%s\".",
- copy_name ($1.stoken));
- }
+ error ("No file or function \"%s\".",
+ copy_name ($1.stoken));
+ }
+ | FILENAME
+ {
+ $$ = $1;
}
;
error ("`%s' is not defined as an aggregate type.",
TYPE_NAME (type));
- if (!STREQ (type_name_no_tag (type), $4.ptr))
- error ("invalid destructor `%s::~%s'",
- type_name_no_tag (type), $4.ptr);
-
tmp_token.ptr = (char*) alloca ($4.length + 2);
tmp_token.length = $4.length + 1;
tmp_token.ptr[0] = '~';
memcpy (tmp_token.ptr+1, $4.ptr, $4.length);
tmp_token.ptr[tmp_token.length] = 0;
+
+ /* Check for valid destructor name. */
+ destructor_name_p (tmp_token.ptr, type);
write_exp_elt_opcode (OP_SCOPE);
write_exp_elt_type (type);
write_exp_string (tmp_token);
}
;
+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: '*'
func_mod: '(' ')'
{ $$ = 0; }
| '(' nonempty_typelist ')'
- { free ((PTR)$2); $$ = 0; }
+ { free ($2); $$ = 0; }
;
/* We used to try to recognize more pointer to member types here, but
{ $$ = 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
+ { $$ = builtin_type_long_double; }
| STRUCT name
{ $$ = lookup_struct (copy_name ($2),
expression_context_block); }
{ $$ = 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
}
;
+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; }
here, and we do kind of silly things like cast to unsigned. */
register LONGEST n = 0;
register LONGEST prevn = 0;
- unsigned LONGEST un;
+ ULONGEST un;
register int i = 0;
register int c;
/* We have found a "L" or "U" suffix. */
int found_suffix = 0;
- unsigned LONGEST high_bit;
+ ULONGEST high_bit;
struct type *signed_type;
struct type *unsigned_type;
if (parsed_float)
{
/* It's a float since it contains a point or an exponent. */
- putithere->dval = atof (p);
+ char c;
+ int num = 0; /* number of tokens scanned by scanf */
+ char saved_char = p[len];
+
+ p[len] = 0; /* null-terminate the token */
+ if (sizeof (putithere->typed_val_float.dval) <= sizeof (float))
+ num = sscanf (p, "%g%c", (float *) &putithere->typed_val_float.dval,&c);
+ else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double))
+ num = sscanf (p, "%lg%c", (double *) &putithere->typed_val_float.dval,&c);
+ else
+ {
+#ifdef SCANF_HAS_LONG_DOUBLE
+ num = sscanf (p, "%Lg%c", &putithere->typed_val_float.dval,&c);
+#else
+ /* Scan it into a double, then assign it to the long double.
+ This at least wins with values representable in the range
+ of doubles. */
+ double temp;
+ num = sscanf (p, "%lg%c", &temp,&c);
+ putithere->typed_val_float.dval = temp;
+#endif
+ }
+ p[len] = saved_char; /* restore the input stream */
+ if (num != 1) /* check scanf found ONLY a float ... */
+ return ERROR;
+ /* See if it has `f' or `l' suffix (float or long double). */
+
+ c = tolower (p[len - 1]);
+
+ if (c == 'f')
+ putithere->typed_val_float.type = builtin_type_float;
+ else if (c == 'l')
+ putithere->typed_val_float.type = builtin_type_long_double;
+ else if (isdigit (c) || c == '.')
+ putithere->typed_val_float.type = builtin_type_double;
+ else
+ return ERROR;
+
return FLOAT;
}
on 0x123456789 when LONGEST is 32 bits. */
if (c != 'l' && c != 'u' && n != 0)
{
- if ((unsigned_p && (unsigned LONGEST) prevn >= (unsigned LONGEST) n))
+ if ((unsigned_p && (ULONGEST) prevn >= (ULONGEST) n))
error ("Numeric constant too large.");
}
prevn = n;
the case where it is we just always shift the value more than
once, with fewer bits each time. */
- un = (unsigned LONGEST)n >> 2;
+ un = (ULONGEST)n >> 2;
if (long_p == 0
&& (un >> (TARGET_INT_BIT - 2)) == 0)
{
- high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
+ high_bit = ((ULONGEST)1) << (TARGET_INT_BIT-1);
/* A large decimal (not hex or octal) constant (between INT_MAX
and UINT_MAX) is a long or unsigned long, according to ANSI,
else if (long_p <= 1
&& (un >> (TARGET_LONG_BIT - 2)) == 0)
{
- high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
+ high_bit = ((ULONGEST)1) << (TARGET_LONG_BIT-1);
unsigned_type = builtin_type_unsigned_long;
signed_type = builtin_type_long;
}
else
{
- high_bit = (((unsigned LONGEST)1)
- << (TARGET_LONG_LONG_BIT - 32 - 1)
- << 16
- << 16);
- if (high_bit == 0)
+ int shift;
+ if (sizeof (ULONGEST) * HOST_CHAR_BIT < TARGET_LONG_LONG_BIT)
/* A long long does not fit in a LONGEST. */
- high_bit =
- (unsigned LONGEST)1 << (sizeof (LONGEST) * HOST_CHAR_BIT - 1);
+ shift = (sizeof (ULONGEST) * HOST_CHAR_BIT - 1);
+ else
+ shift = (TARGET_LONG_LONG_BIT - 1);
+ high_bit = (ULONGEST) 1 << shift;
unsigned_type = builtin_type_unsigned_long_long;
signed_type = builtin_type_long_long;
}
- putithere->typed_val.val = n;
+ putithere->typed_val_int.val = n;
/* If the high bit of the worked out type is set then this number
has to be unsigned. */
if (unsigned_p || (n & high_bit))
{
- putithere->typed_val.type = unsigned_type;
+ putithere->typed_val_int.type = unsigned_type;
}
else
{
- putithere->typed_val.type = signed_type;
+ putithere->typed_val_int.type = signed_type;
}
return INT;
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++)
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':
c = *lexptr++;
if (c == '\\')
c = parse_escape (&lexptr);
+ else if (c == '\'')
+ error ("Empty character constant.");
+ else if (! host_char_to_target (c, &c))
+ {
+ int toklen = lexptr - tokstart + 1;
+ char *tok = alloca (toklen + 1);
+ memcpy (tok, tokstart, toklen);
+ tok[toklen] = '\0';
+ error ("There is no character corresponding to %s in the target "
+ "character set `%s'.", tok, target_charset ());
+ }
- yylval.typed_val.val = c;
- yylval.typed_val.type = builtin_type_char;
+ yylval.typed_val_int.val = c;
+ yylval.typed_val_int.type = builtin_type_char;
c = *lexptr++;
if (c != '\'')
if (namelen > 2)
{
lexptr = tokstart + namelen;
+ unquoted_expr = 0;
if (lexptr[-1] != '\'')
error ("Unmatched single quote.");
namelen -= 2;
return c;
case ',':
- if (comma_terminates && paren_depth == 0)
+ if (comma_terminates
+ && paren_depth == 0
+ && ! scanning_macro_expansion ())
return 0;
lexptr++;
return c;
tempbufindex = 0;
do {
+ char *char_start_pos = tokptr;
+
/* Grow the static temp buffer if necessary, including allocating
the first one on demand. */
if (tempbufindex + 1 >= tempbufsize)
tempbuf[tempbufindex++] = c;
break;
default:
- tempbuf[tempbufindex++] = *tokptr++;
+ c = *tokptr++;
+ if (! host_char_to_target (c, &c))
+ {
+ int len = tokptr - char_start_pos;
+ char *copy = alloca (len + 1);
+ memcpy (copy, char_start_pos, len);
+ copy[len] = '\0';
+
+ error ("There is no character corresponding to `%s' "
+ "in the target character set `%s'.",
+ copy, target_charset ());
+ }
+ tempbuf[tempbufindex++] = c;
break;
}
} while ((*tokptr != '"') && (*tokptr != '\0'));
(c == '_' || c == '$' || (c >= '0' && c <= '9')
|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');)
{
- if (c == '<')
- {
- int i = namelen;
- while (tokstart[++i] && tokstart[i] != '>');
- if (tokstart[i] == '>')
- namelen = i;
- }
- c = tokstart[++namelen];
- }
+ /* Template parameter lists are part of the name.
+ FIXME: This mishandles `print $a<4&&$a>3'. */
+
+ if (c == '<')
+ {
+ /* 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;
}
lexptr += namelen;
- /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
- and $$digits (equivalent to $<-digits> if you could type that).
- Make token type LAST, and put the number (the digits) in yylval. */
-
tryname:
- if (*tokstart == '$')
- {
- register int negate = 0;
- c = 1;
- /* Double dollar means negate the number and add -1 as well.
- Thus $$ alone means -1. */
- if (namelen >= 2 && tokstart[1] == '$')
- {
- negate = 1;
- c = 2;
- }
- if (c == namelen)
- {
- /* Just dollars (one or two) */
- yylval.lval = - negate;
- return LAST;
- }
- /* Is the rest of the token digits? */
- for (; c < namelen; c++)
- if (!(tokstart[c] >= '0' && tokstart[c] <= '9'))
- break;
- if (c == namelen)
- {
- yylval.lval = atoi (tokstart + 1 + negate);
- if (negate)
- yylval.lval = - yylval.lval;
- return LAST;
- }
- }
- /* Handle tokens that refer to machine registers:
- $ followed by a register name. */
-
- if (*tokstart == '$') {
- for (c = 0; c < NUM_REGS; c++)
- if (namelen - 1 == strlen (reg_names[c])
- && 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)
- && STREQN (tokstart + 1, std_regs[c].name, namelen - 1))
- {
- yylval.lval = std_regs[c].regnum;
- return REGNAME;
- }
- }
/* Catch specific keywords. Should be done with a data structure. */
switch (namelen)
{
return SIGNED_KEYWORD;
if (STREQN (tokstart, "sizeof", 6))
return SIZEOF;
+ if (STREQN (tokstart, "double", 6))
+ 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))
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;
+ }
break;
case 3:
if (STREQN (tokstart, "int", 3))
yylval.sval.ptr = tokstart;
yylval.sval.length = namelen;
- /* Any other names starting in $ are debugger internal variables. */
-
if (*tokstart == '$')
{
- yylval.ivar = lookup_internalvar (copy_name (yylval.sval) + 1);
+ 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
/* Call lookup_symtab, not lookup_partial_symtab, in case there are
no psymtabs (coff, xcoff, or some future change to blow away the
psymtabs once once symbols are read). */
- if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ||
- lookup_symtab (tmp))
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
{
yylval.ssym.sym = sym;
yylval.ssym.is_a_field_of_this = is_a_field_of_this;
return BLOCKNAME;
}
+ else if (!sym)
+ { /* See if it's a file name. */
+ struct symtab *symtab;
+
+ symtab = lookup_symtab (tmp);
+
+ if (symtab)
+ {
+ yylval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
+ return FILENAME;
+ }
+ }
+
if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
{
#if 1
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
yyerror (msg)
char *msg;
{
+ if (prev_lexptr)
+ lexptr = prev_lexptr;
+
error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
}