{
LONGEST lval;
unsigned LONGEST ulval;
+ struct {
+ LONGEST val;
+ struct type *type;
+ } typed_val;
double dval;
struct symbol *sym;
struct type *tval;
%type <tval> ptype
%type <lval> array_mod
-%token <lval> INT CHAR
-%token <ulval> UINT
+%token <typed_val> INT
%token <dval> FLOAT
/* Both NAME and TYPENAME tokens represent symbols in the input,
/* A NAME_OR_INT is a symbol which is not known in the symbol table,
but which would parse as a valid number in the current input radix.
E.g. "c" when input_radix==16. Depending on the parse, it will be
- turned into a name or into a number. NAME_OR_UINT ditto. */
+ turned into a name or into a number. */
-%token <ssym> NAME_OR_INT NAME_OR_UINT
+%token <ssym> NAME_OR_INT
%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
%token TEMPLATE
/* 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 <ivar> VARIABLE
exp : INT
{ write_exp_elt_opcode (OP_LONG);
- if ($1 == (int) $1 || $1 == (unsigned int) $1)
- write_exp_elt_type (builtin_type_int);
- else
- write_exp_elt_type (BUILTIN_TYPE_LONGEST);
- write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_longcst ((LONGEST)($1.val));
write_exp_elt_opcode (OP_LONG); }
;
{ YYSTYPE val;
parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
write_exp_elt_opcode (OP_LONG);
- if (val.lval == (int) val.lval ||
- val.lval == (unsigned int) val.lval)
- write_exp_elt_type (builtin_type_int);
- else
- write_exp_elt_type (BUILTIN_TYPE_LONGEST);
- write_exp_elt_longcst (val.lval);
- write_exp_elt_opcode (OP_LONG); }
- ;
-
-exp : UINT
- {
- write_exp_elt_opcode (OP_LONG);
- if ($1 == (unsigned int) $1)
- write_exp_elt_type (builtin_type_unsigned_int);
- else
- write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
- write_exp_elt_longcst ((LONGEST) $1);
- write_exp_elt_opcode (OP_LONG);
- }
- ;
-
-exp : NAME_OR_UINT
- { YYSTYPE val;
- parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
- write_exp_elt_opcode (OP_LONG);
- if (val.ulval == (unsigned int) val.ulval)
- write_exp_elt_type (builtin_type_unsigned_int);
- else
- write_exp_elt_type (BUILTIN_TYPE_UNSIGNED_LONGEST);
- write_exp_elt_longcst ((LONGEST)val.ulval);
+ write_exp_elt_type (val.typed_val.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val.val);
write_exp_elt_opcode (OP_LONG);
}
;
-exp : CHAR
- { write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type (builtin_type_char);
- write_exp_elt_longcst ((LONGEST) $1);
- write_exp_elt_opcode (OP_LONG); }
- ;
exp : FLOAT
{ write_exp_elt_opcode (OP_DOUBLE);
array_mod: '[' ']'
{ $$ = -1; }
| '[' INT ']'
- { $$ = $2; }
+ { $$ = $2.val; }
;
func_mod: '(' ')'
| BLOCKNAME { $$ = $1.stoken; }
| TYPENAME { $$ = $1.stoken; }
| NAME_OR_INT { $$ = $1.stoken; }
- | NAME_OR_UINT { $$ = $1.stoken; }
;
name_not_typename : NAME
=exp) or just an exp. If name_not_typename was ever used in an lvalue
context where only a name could occur, this might be useful.
| NAME_OR_INT
- | NAME_OR_UINT
*/
;
register int c;
register int base = input_radix;
int unsigned_p = 0;
+ int long_p = 0;
+ LONGEST high_bit;
+ struct type *signed_type;
+ struct type *unsigned_type;
if (parsed_float)
{
{
if (base > 10 && c >= 'a' && c <= 'f')
n += i = c - 'a' + 10;
- else if (len == 0 && c == 'l')
- ;
+ else if (len == 0 && c == 'l')
+ long_p = 1;
else if (len == 0 && c == 'u')
unsigned_p = 1;
else
}
if (i >= base)
return ERROR; /* Invalid digit in this base */
+
/* Portably test for overflow (only works for nonzero values, so make
a second check for zero). */
if((prevn >= n) && n != 0)
}
prevn=n;
}
+
+ /* 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 (unsigned_p)
- {
- putithere->ulval = n;
- return UINT;
- }
- else
- {
- putithere->lval = n;
- return INT;
- }
+ if ((TARGET_INT_BIT != TARGET_LONG_BIT && (n >> TARGET_INT_BIT)) || long_p)
+ {
+ high_bit = ((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);
+ unsigned_type = builtin_type_unsigned_int;
+ signed_type = builtin_type_int;
+ }
+
+ putithere->typed_val.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;
+ }
+ else
+ {
+ putithere->typed_val.type = signed_type;
+ }
+
+ return INT;
}
struct token
c = *lexptr++;
if (c == '\\')
c = parse_escape (&lexptr);
- yylval.lval = c;
+
+ yylval.typed_val.val = c;
+ yylval.typed_val.type = builtin_type_char;
+
c = *lexptr++;
if (c != '\'')
{
}
error ("Invalid character constant.");
}
- return CHAR;
+ return INT;
case '(':
paren_depth++;
yylval.ssym.is_a_field_of_this = is_a_field_of_this;
return NAME_OR_INT;
}
- if (hextype == UINT)
- {
- yylval.ssym.sym = sym;
- yylval.ssym.is_a_field_of_this = is_a_field_of_this;
- return NAME_OR_UINT;
- }
}
/* Any other kind of symbol */