#include "parser-defs.h"
#include "value.h"
#include "language.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
-/* These MUST be included in any grammar file!!!!
- Please choose unique names! */
+/* 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. */
#define yymaxdepth c_maxdepth
#define yyparse c_parse
#define yylex c_lex
#define yy_yyv c_yyv
#define yyval c_val
#define yylloc c_lloc
-
-static void
-__yy_bcopy PARAMS ((char *, char *, int));
+#define yyss c_yyss /* byacc */
+#define yyssp c_yysp /* byacc */
+#define yyvs c_yyvs /* byacc */
+#define yyvsp c_yyvsp /* byacc */
int
yyparse PARAMS ((void));
parse_number PARAMS ((char *, int, int, YYSTYPE *));
%}
-%type <voidval> exp exp1 type_exp start variable
+%type <voidval> exp exp1 type_exp start variable qualified_name
%type <tval> type typebase
%type <tvec> nonempty_typelist
/* %type <bval> block */
%token <ssym> NAME_OR_INT NAME_OR_UINT
-%token STRUCT UNION ENUM SIZEOF UNSIGNED COLONCOLON
+%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
%token TEMPLATE
%token ERROR
/* Special type cases, put in to allow the parser to distinguish different
legal basetypes. */
-%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD
+%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD
%token <lval> LAST REGNAME
%token <ssym> BLOCKNAME
%type <bval> block
%left COLONCOLON
+
+%{
+/* Ensure that if the generated parser contains any calls to malloc/realloc,
+ that they get mapped to xmalloc/xrealloc. We have to do this here
+ rather than earlier in the file because this is the first point after
+ the place where the SVR4 yacc includes <malloc.h>, and if we do it
+ before that, then the remapped declarations in <malloc.h> will collide
+ with the ones in "defs.h". */
+
+#define malloc xmalloc
+#define realloc xrealloc
+%}
+
\f
%%
write_exp_elt_opcode (STRUCTOP_PTR); }
;
+exp : exp ARROW qualified_name
+ { /* exp->type::name becomes exp->*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ write_exp_elt_opcode (UNOP_ADDR);
+ write_exp_elt_opcode (STRUCTOP_MPTR); }
+ ;
exp : exp ARROW '*' exp
{ write_exp_elt_opcode (STRUCTOP_MPTR); }
;
write_exp_elt_opcode (STRUCTOP_STRUCT); }
;
+exp : exp '.' qualified_name
+ { /* exp.type::name becomes exp.*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ write_exp_elt_opcode (UNOP_ADDR);
+ write_exp_elt_opcode (STRUCTOP_MEMBER); }
+ ;
+
exp : exp '.' '*' exp
{ write_exp_elt_opcode (STRUCTOP_MEMBER); }
;
write_exp_elt_opcode (OP_VAR_VALUE); }
;
-variable: typebase COLONCOLON name
+qualified_name: typebase COLONCOLON name
{
struct type *type = $1;
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
| typebase COLONCOLON '~' name
{
struct type *type = $1;
+ struct stoken tmp_token;
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
&& TYPE_CODE (type) != TYPE_CODE_UNION)
error ("`%s' is not defined as an aggregate type.",
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;
write_exp_elt_opcode (OP_SCOPE);
write_exp_elt_type (type);
- write_exp_string ($4);
+ write_exp_string (tmp_token);
write_exp_elt_opcode (OP_SCOPE);
- write_exp_elt_opcode (UNOP_LOGNOT);
}
+ ;
+
+variable: qualified_name
| COLONCOLON name
{
char *name = copy_name ($2);
func_mod: '(' ')'
{ $$ = 0; }
| '(' nonempty_typelist ')'
- { free ($2); $$ = 0; }
+ { free ((PTR)$2); $$ = 0; }
;
type : ptype
| type '(' typebase COLONCOLON '*' ')' '(' nonempty_typelist ')'
{ $$ = lookup_member_type
(lookup_function_type ($1), $3);
- free ($8); }
+ free ((PTR)$8); }
+ /* "const" and "volatile" are curently ignored. */
+ | CONST_KEYWORD type { $$ = $2; }
+ | VOLATILE_KEYWORD type { $$ = $2; }
;
typebase
| STRUCT name
{ $$ = lookup_struct (copy_name ($2),
expression_context_block); }
+ | CLASS name
+ { $$ = lookup_struct (copy_name ($2),
+ expression_context_block); }
| UNION name
{ $$ = lookup_union (copy_name ($2),
expression_context_block); }
| UNSIGNED
{ $$ = builtin_type_unsigned_int; }
| SIGNED_KEYWORD typename
- { $$ = $2.type; }
+ { $$ = lookup_signed_typename (TYPE_NAME($2.type)); }
| SIGNED_KEYWORD
{ $$ = builtin_type_int; }
| TEMPLATE name '<' type '>'
nonempty_typelist
: type
- { $$ = (struct type **)xmalloc (sizeof (struct type *) * 2);
- $$[0] = (struct type *)0;
+ { $$ = (struct type **) xmalloc (sizeof (struct type *) * 2);
+ $<ivec>$[0] = 1; /* Number of types in vector */
$$[1] = $1;
}
| nonempty_typelist ',' type
- { int len = sizeof (struct type *) * ++($<ivec>1[0]);
- $$ = (struct type **)xrealloc ((char *) $1, len);
+ { int len = sizeof (struct type *) * (++($<ivec>1[0]) + 1);
+ $$ = (struct type **) xrealloc ((char *) $1, len);
$$[$<ivec>$[0]] = $3;
}
;
goto retry;
case '\'':
+ /* We either have a character constant ('0' or '\177' for example)
+ or we have a quoted symbol reference ('foo(int,int)' in C++
+ for example). */
lexptr++;
c = *lexptr++;
if (c == '\\')
yylval.lval = c;
c = *lexptr++;
if (c != '\'')
- error ("Invalid character constant.");
+ {
+ namelen = skip_quoted (tokstart) - tokstart;
+ if (namelen > 2)
+ {
+ lexptr = tokstart + namelen;
+ namelen -= 2;
+ tokstart++;
+ goto tryname;
+ }
+ error ("Invalid character constant.");
+ }
return CHAR;
case '(':
{
char *err_copy = (char *) alloca (p - tokstart + 1);
- bcopy (tokstart, err_copy, p - tokstart);
+ memcpy (err_copy, tokstart, p - tokstart);
err_copy[p - tokstart] = 0;
error ("Invalid number \"%s\".", err_copy);
}
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;
if (current_language->la_language == language_cplus
&& !strncmp (tokstart, "template", 8))
return TEMPLATE;
+ if (!strncmp (tokstart, "volatile", 8))
+ return VOLATILE_KEYWORD;
break;
case 6:
if (!strncmp (tokstart, "struct", 6))
return SIZEOF;
break;
case 5:
+ if (current_language->la_language == language_cplus
+ && !strncmp (tokstart, "class", 5))
+ return CLASS;
if (!strncmp (tokstart, "union", 5))
return UNION;
if (!strncmp (tokstart, "short", 5))
return SHORT;
+ if (!strncmp (tokstart, "const", 5))
+ return CONST_KEYWORD;
break;
case 4:
if (!strncmp (tokstart, "enum", 4))
struct type *builtin_type_int;
struct type *builtin_type_long;
struct type *builtin_type_long_long;
+struct type *builtin_type_signed_char;
struct type *builtin_type_unsigned_char;
struct type *builtin_type_unsigned_short;
struct type *builtin_type_unsigned_int;
&builtin_type_double,
&builtin_type_void,
&builtin_type_long_long,
+ &builtin_type_signed_char,
&builtin_type_unsigned_char,
&builtin_type_unsigned_short,
&builtin_type_unsigned_int,
init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
0,
"char", (struct objfile *) NULL);
+ builtin_type_signed_char =
+ init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_SIGNED,
+ "signed char", (struct objfile *) NULL);
builtin_type_unsigned_char =
init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
TYPE_FLAG_UNSIGNED,