/* YACC parser for C expressions, for GDB.
- Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2003, 2004
+ Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2003, 2004, 2006, 2007, 2008
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Parse a C expression from text in a string,
and return the result as a struct expression pointer.
#include "charset.h"
#include "block.h"
#include "cp-support.h"
+#include "dfp.h"
/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
as well as gratuitiously global symbol names, so we can have multiple
DOUBLEST dval;
struct type *type;
} typed_val_float;
+ struct {
+ gdb_byte val[16];
+ struct type *type;
+ } typed_val_decfloat;
struct symbol *sym;
struct type *tval;
struct stoken sval;
%token <typed_val_int> INT
%token <typed_val_float> FLOAT
+%token <typed_val_decfloat> DECFLOAT
/* Both NAME and TYPENAME tokens represent symbols in the input,
and both convey their data as strings.
{ write_exp_elt_opcode (UNOP_NEG); }
;
+exp : '+' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_PLUS); }
+ ;
+
exp : '!' exp %prec UNARY
{ write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
;
write_exp_elt_opcode (OP_DOUBLE); }
;
+exp : DECFLOAT
+ { write_exp_elt_opcode (OP_DECFLOAT);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_decfloatcst ($1.val);
+ write_exp_elt_opcode (OP_DECFLOAT); }
+ ;
+
exp : variable
;
exp : SIZEOF '(' type ')' %prec UNARY
{ write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type (builtin_type_int);
+ write_exp_elt_type (builtin_type (current_gdbarch)->builtin_int);
CHECK_TYPEDEF ($3);
write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
write_exp_elt_opcode (OP_LONG); }
while (count-- > 0)
{
write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type (builtin_type_char);
+ write_exp_elt_type (builtin_type (current_gdbarch)->builtin_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_type (builtin_type (current_gdbarch)->builtin_char);
write_exp_elt_longcst ((LONGEST)'\0');
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (OP_ARRAY);
/* C++. */
exp : TRUEKEYWORD
{ write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type (builtin_type_bool);
+ write_exp_elt_type (builtin_type (current_gdbarch)->builtin_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_type (builtin_type (current_gdbarch)->builtin_bool);
write_exp_elt_longcst ((LONGEST) 0);
write_exp_elt_opcode (OP_LONG); }
;
if (msymbol != NULL)
{
write_exp_msymbol (msymbol,
- lookup_function_type (builtin_type_int),
- builtin_type_int);
+ lookup_function_type (builtin_type (current_gdbarch)->builtin_int),
+ builtin_type (current_gdbarch)->builtin_int);
}
else
if (!have_full_symbols () && !have_partial_symbols ())
if (msymbol != NULL)
{
write_exp_msymbol (msymbol,
- lookup_function_type (builtin_type_int),
- builtin_type_int);
+ lookup_function_type (builtin_type (current_gdbarch)->builtin_int),
+ builtin_type (current_gdbarch)->builtin_int);
}
else if (!have_full_symbols () && !have_partial_symbols ())
error ("No symbol table is loaded. Use the \"file\" command.");
{ free ($2); $$ = 0; }
;
-/* We used to try to recognize more pointer to member types here, but
+/* We used to try to recognize pointer to member types here, but
that didn't work (shift/reduce conflicts meant that these rules never
got executed). The problem is that
int (foo::bar::baz::bizzle)
is a pointer to member type. Stroustrup loses again! */
type : ptype
- | typebase COLONCOLON '*'
- { $$ = lookup_member_type (builtin_type_int, $1); }
;
typebase /* Implements (approximately): (type-qualifier)* type-specifier */
: TYPENAME
{ $$ = $1.type; }
| INT_KEYWORD
- { $$ = builtin_type_int; }
+ { $$ = builtin_type (current_gdbarch)->builtin_int; }
| LONG
- { $$ = builtin_type_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long; }
| SHORT
- { $$ = builtin_type_short; }
+ { $$ = builtin_type (current_gdbarch)->builtin_short; }
| LONG INT_KEYWORD
- { $$ = builtin_type_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long; }
| LONG SIGNED_KEYWORD INT_KEYWORD
- { $$ = builtin_type_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long; }
| LONG SIGNED_KEYWORD
- { $$ = builtin_type_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long; }
| SIGNED_KEYWORD LONG INT_KEYWORD
- { $$ = builtin_type_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long; }
| UNSIGNED LONG INT_KEYWORD
- { $$ = builtin_type_unsigned_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long; }
| LONG UNSIGNED INT_KEYWORD
- { $$ = builtin_type_unsigned_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long; }
| LONG UNSIGNED
- { $$ = builtin_type_unsigned_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long; }
| LONG LONG
- { $$ = builtin_type_long_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
| LONG LONG INT_KEYWORD
- { $$ = builtin_type_long_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
| LONG LONG SIGNED_KEYWORD INT_KEYWORD
- { $$ = builtin_type_long_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
| LONG LONG SIGNED_KEYWORD
- { $$ = builtin_type_long_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
| SIGNED_KEYWORD LONG LONG
- { $$ = builtin_type_long_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
| SIGNED_KEYWORD LONG LONG INT_KEYWORD
- { $$ = builtin_type_long_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long_long; }
| UNSIGNED LONG LONG
- { $$ = builtin_type_unsigned_long_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long_long; }
| UNSIGNED LONG LONG INT_KEYWORD
- { $$ = builtin_type_unsigned_long_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long_long; }
| LONG LONG UNSIGNED
- { $$ = builtin_type_unsigned_long_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long_long; }
| LONG LONG UNSIGNED INT_KEYWORD
- { $$ = builtin_type_unsigned_long_long; }
+ { $$ = builtin_type (current_gdbarch)->builtin_unsigned_long_long; }
| SHORT INT_KEYWORD
- { $$ = builtin_type_short; }
+ { $$ = builtin_type (current_gdbarch)->builtin_short; }
| SHORT SIGNED_KEYWORD INT_KEYWORD
- { $$ = builtin_type_short; }
+ { $$ = builtin_type (current_gdbarch)->builtin_short; }
| SHORT SIGNED_KEYWORD
- { $$ = builtin_type_short; }
+ { $$ = builtin_type (current_gdbarch)->builtin_short; }
| UNSIGNED SHORT INT_KEYWORD
- { $$ = builtin_type_unsigned_short; }
+ { $$ = builtin_type (current_gdbarch)->builtin_unsigned_short; }
| SHORT UNSIGNED
- { $$ = builtin_type_unsigned_short; }
+ { $$ = builtin_type (current_gdbarch)->builtin_unsigned_short; }
| SHORT UNSIGNED INT_KEYWORD
- { $$ = builtin_type_unsigned_short; }
+ { $$ = builtin_type (current_gdbarch)->builtin_unsigned_short; }
| DOUBLE_KEYWORD
- { $$ = builtin_type_double; }
+ { $$ = builtin_type (current_gdbarch)->builtin_double; }
| LONG DOUBLE_KEYWORD
- { $$ = builtin_type_long_double; }
+ { $$ = builtin_type (current_gdbarch)->builtin_long_double; }
| STRUCT name
{ $$ = lookup_struct (copy_name ($2),
expression_context_block); }
| UNSIGNED typename
{ $$ = lookup_unsigned_typename (TYPE_NAME($2.type)); }
| UNSIGNED
- { $$ = builtin_type_unsigned_int; }
+ { $$ = builtin_type (current_gdbarch)->builtin_unsigned_int; }
| SIGNED_KEYWORD typename
{ $$ = lookup_signed_typename (TYPE_NAME($2.type)); }
| SIGNED_KEYWORD
- { $$ = builtin_type_int; }
+ { $$ = builtin_type (current_gdbarch)->builtin_int; }
/* It appears that this rule for templates is never
reduced; template recognition happens by lookahead
in the token processing code in yylex. */
{
$$.stoken.ptr = "int";
$$.stoken.length = 3;
- $$.type = builtin_type_int;
+ $$.type = builtin_type (current_gdbarch)->builtin_int;
}
| LONG
{
$$.stoken.ptr = "long";
$$.stoken.length = 4;
- $$.type = builtin_type_long;
+ $$.type = builtin_type (current_gdbarch)->builtin_long;
}
| SHORT
{
$$.stoken.ptr = "short";
$$.stoken.length = 5;
- $$.type = builtin_type_short;
+ $$.type = builtin_type (current_gdbarch)->builtin_short;
}
;
if (parsed_float)
{
/* It's a float since it contains a point or an exponent. */
- char c;
+ char *s = malloc (len);
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
+
+ /* If it ends at "df", "dd" or "dl", take it as type of decimal floating
+ point. Return DECFLOAT. */
+
+ if (p[len - 2] == 'd' && p[len - 1] == 'f')
{
-#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 - 2] = '\0';
+ putithere->typed_val_decfloat.type
+ = builtin_type (current_gdbarch)->builtin_decfloat;
+ decimal_from_string (putithere->typed_val_decfloat.val, 4, p);
+ p[len] = saved_char;
+ return (DECFLOAT);
+ }
+
+ if (p[len - 2] == 'd' && p[len - 1] == 'd')
+ {
+ p[len - 2] = '\0';
+ putithere->typed_val_decfloat.type
+ = builtin_type (current_gdbarch)->builtin_decdouble;
+ decimal_from_string (putithere->typed_val_decfloat.val, 8, p);
+ p[len] = saved_char;
+ return (DECFLOAT);
}
+
+ if (p[len - 2] == 'd' && p[len - 1] == 'l')
+ {
+ p[len - 2] = '\0';
+ putithere->typed_val_decfloat.type
+ = builtin_type (current_gdbarch)->builtin_declong;
+ decimal_from_string (putithere->typed_val_decfloat.val, 16, p);
+ p[len] = saved_char;
+ return (DECFLOAT);
+ }
+
+ num = sscanf (p, "%" DOUBLEST_SCAN_FORMAT "%s",
+ &putithere->typed_val_float.dval, s);
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;
+ if (num == 1)
+ putithere->typed_val_float.type =
+ builtin_type (current_gdbarch)->builtin_double;
+
+ if (num == 2 )
+ {
+ /* See if it has any float suffix: 'f' for float, 'l' for long
+ double. */
+ if (!strcasecmp (s, "f"))
+ putithere->typed_val_float.type =
+ builtin_type (current_gdbarch)->builtin_float;
+ else if (!strcasecmp (s, "l"))
+ putithere->typed_val_float.type =
+ builtin_type (current_gdbarch)->builtin_long_double;
+ else
+ {
+ free (s);
+ return ERROR;
+ }
+ }
+
+ free (s);
return FLOAT;
}
shift it right and see whether anything remains. Note that we
can't shift sizeof (LONGEST) * HOST_CHAR_BIT bits or more in one
operation, because many compilers will warn about such a shift
- (which always produces a zero result). Sometimes TARGET_INT_BIT
- or TARGET_LONG_BIT will be that big, sometimes not. To deal with
+ (which always produces a zero result). Sometimes gdbarch_int_bit
+ or gdbarch_long_bit will be that big, sometimes not. To deal with
the case where it is we just always shift the value more than
once, with fewer bits each time. */
un = (ULONGEST)n >> 2;
if (long_p == 0
- && (un >> (TARGET_INT_BIT - 2)) == 0)
+ && (un >> (gdbarch_int_bit (current_gdbarch) - 2)) == 0)
{
- high_bit = ((ULONGEST)1) << (TARGET_INT_BIT-1);
+ high_bit = ((ULONGEST)1) << (gdbarch_int_bit (current_gdbarch) - 1);
/* A large decimal (not hex or octal) constant (between INT_MAX
and UINT_MAX) is a long or unsigned long, according to ANSI,
int. This probably should be fixed. GCC gives a warning on
such constants. */
- unsigned_type = builtin_type_unsigned_int;
- signed_type = builtin_type_int;
+ unsigned_type = builtin_type (current_gdbarch)->builtin_unsigned_int;
+ signed_type = builtin_type (current_gdbarch)->builtin_int;
}
else if (long_p <= 1
- && (un >> (TARGET_LONG_BIT - 2)) == 0)
+ && (un >> (gdbarch_long_bit (current_gdbarch) - 2)) == 0)
{
- high_bit = ((ULONGEST)1) << (TARGET_LONG_BIT-1);
- unsigned_type = builtin_type_unsigned_long;
- signed_type = builtin_type_long;
+ high_bit = ((ULONGEST)1) << (gdbarch_long_bit (current_gdbarch) - 1);
+ unsigned_type = builtin_type (current_gdbarch)->builtin_unsigned_long;
+ signed_type = builtin_type (current_gdbarch)->builtin_long;
}
else
{
int shift;
- if (sizeof (ULONGEST) * HOST_CHAR_BIT < TARGET_LONG_LONG_BIT)
+ if (sizeof (ULONGEST) * HOST_CHAR_BIT
+ < gdbarch_long_long_bit (current_gdbarch))
/* A long long does not fit in a LONGEST. */
shift = (sizeof (ULONGEST) * HOST_CHAR_BIT - 1);
else
- shift = (TARGET_LONG_LONG_BIT - 1);
+ shift = (gdbarch_long_long_bit (current_gdbarch) - 1);
high_bit = (ULONGEST) 1 << shift;
- unsigned_type = builtin_type_unsigned_long_long;
- signed_type = builtin_type_long_long;
+ unsigned_type = builtin_type (current_gdbarch)->builtin_unsigned_long_long;
+ signed_type = builtin_type (current_gdbarch)->builtin_long_long;
}
putithere->typed_val_int.val = n;
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:
}
prev_lexptr = lexptr;
- unquoted_expr = 1;
tokstart = lexptr;
/* See if it is a special token of length 3. */
}
yylval.typed_val_int.val = c;
- yylval.typed_val_int.type = builtin_type_char;
+ yylval.typed_val_int.type = builtin_type (current_gdbarch)->builtin_char;
c = *lexptr++;
if (c != '\'')
if (namelen > 2)
{
lexptr = tokstart + namelen;
- unquoted_expr = 0;
if (lexptr[-1] != '\'')
error ("Unmatched single quote.");
namelen -= 2;
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. */
-
- /* NOTE: carlton/2003-09-24: I don't entirely understand the
- HP-specific code, either here or in linespec. Having said that,
- I suspect that we're actually moving towards their model: we want
- symbols whose names are fully qualified, which matches the
- description above. */
- 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