#include <stdio.h>
#include <string.h>
#include "defs.h"
-#include "param.h"
#include "symtab.h"
+#include "gdbtypes.h"
#include "frame.h"
#include "expression.h"
#include "parser-defs.h"
#include "value.h"
#include "language.h"
-
-/* These MUST be included in any grammar file!!!!
- Please choose unique names! */
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+/* 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 yyerror c_error
#define yyexca c_exca
#define yyerrflag c_errflag
#define yynerrs c_nerrs
+#define yyps c_ps
+#define yypv c_pv
+#define yys c_s
+#define yy_yys c_yys
+#define yystate c_state
+#define yytmp c_tmp
+#define yyv c_v
+#define yy_yyv c_yyv
+#define yyval c_val
+#define yylloc c_lloc
+#define yyss c_yyss /* byacc */
+#define yyssp c_yysp /* byacc */
+#define yyvs c_yyvs /* byacc */
+#define yyvsp c_yyvsp /* byacc */
+
+int
+yyparse PARAMS ((void));
-/* Forward decls */
-void yyerror ();
-static int parse_number ();
-int yyparse ();
+int
+yylex PARAMS ((void));
+
+void
+yyerror PARAMS ((char *));
/* #define YYDEBUG 1 */
int *ivec;
}
-%type <voidval> exp exp1 type_exp start variable
+%{
+/* YYSTYPE gets defined by %union */
+static int
+parse_number PARAMS ((char *, int, int, YYSTYPE *));
+%}
+
+%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 LONG SHORT INT_KEYWORD
+%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD
%token <lval> LAST REGNAME
%left ABOVE_COMMA
%right '=' ASSIGN_MODIFY
%right '?'
-%left OR
-%left AND
+%left OROR
+%left ANDAND
%left '|'
%left '^'
%left '&'
%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 (BINOP_LOGIOR); }
;
-exp : exp AND exp
+exp : exp ANDAND exp
{ write_exp_elt_opcode (BINOP_AND); }
;
-exp : exp OR exp
+exp : exp OROR exp
{ write_exp_elt_opcode (BINOP_OR); }
;
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);
struct symbol *sym;
- int i;
+ struct minimal_symbol *msymbol;
sym =
lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
write_exp_elt_opcode (OP_VAR_VALUE);
break;
}
- for (i = 0; i < misc_function_count; i++)
- if (!strcmp (misc_function_vector[i].name, name))
- break;
- if (i < misc_function_count)
+ msymbol = lookup_minimal_symbol (name,
+ (struct objfile *) NULL);
+ if (msymbol != NULL)
{
- enum misc_function_type mft =
- misc_function_vector[i].type;
-
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
- write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+ write_exp_elt_longcst ((LONGEST) msymbol -> address);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (UNOP_MEMVAL);
- if (mft == mf_data || mft == mf_bss)
+ if (msymbol -> type == mst_data ||
+ msymbol -> type == mst_bss)
write_exp_elt_type (builtin_type_int);
- else if (mft == mf_text)
+ else if (msymbol -> type == mst_text)
write_exp_elt_type (lookup_function_type (builtin_type_int));
else
write_exp_elt_type (builtin_type_char);
write_exp_elt_opcode (UNOP_MEMVAL);
}
else
- if (symtab_list == 0
- && partial_symtab_list == 0)
+ if (!have_full_symbols () && !have_partial_symbols ())
error ("No symbol table is loaded. Use the \"file\" command.");
else
error ("No symbol \"%s\" in current context.", name);
if (sym)
{
- switch (sym->class)
+ switch (SYMBOL_CLASS (sym))
{
case LOC_REGISTER:
case LOC_ARG:
}
else
{
- register int i;
+ struct minimal_symbol *msymbol;
register char *arg = copy_name ($1.stoken);
- /* FIXME, this search is linear! At least
- optimize the strcmp with a 1-char cmp... */
- for (i = 0; i < misc_function_count; i++)
- if (!strcmp (misc_function_vector[i].name, arg))
- break;
-
- if (i < misc_function_count)
+ msymbol = lookup_minimal_symbol (arg,
+ (struct objfile *) NULL);
+ if (msymbol != NULL)
{
- enum misc_function_type mft =
- misc_function_vector[i].type;
-
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (builtin_type_int);
- write_exp_elt_longcst ((LONGEST) misc_function_vector[i].address);
+ write_exp_elt_longcst ((LONGEST) msymbol -> address);
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (UNOP_MEMVAL);
- if (mft == mf_data || mft == mf_bss)
+ if (msymbol -> type == mst_data ||
+ msymbol -> type == mst_bss)
write_exp_elt_type (builtin_type_int);
- else if (mft == mf_text)
+ else if (msymbol -> type == mst_text)
write_exp_elt_type (lookup_function_type (builtin_type_int));
else
write_exp_elt_type (builtin_type_char);
write_exp_elt_opcode (UNOP_MEMVAL);
}
- else if (symtab_list == 0
- && partial_symtab_list == 0)
+ else if (!have_full_symbols () && !have_partial_symbols ())
error ("No symbol table is loaded. Use the \"file\" command.");
else
error ("No symbol \"%s\" in current context.",
func_mod: '(' ')'
{ $$ = 0; }
+ | '(' nonempty_typelist ')'
+ { 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); }
{ $$ = lookup_unsigned_typename (TYPE_NAME($2.type)); }
| UNSIGNED
{ $$ = builtin_type_unsigned_int; }
- | SIGNED typename
- { $$ = $2.type; }
- | SIGNED
+ | SIGNED_KEYWORD typename
+ { $$ = lookup_signed_typename (TYPE_NAME($2.type)); }
+ | SIGNED_KEYWORD
{ $$ = builtin_type_int; }
+ | TEMPLATE name '<' type '>'
+ { $$ = lookup_template_type(copy_name($2), $4,
+ expression_context_block);
+ }
;
typename: TYPENAME
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 ($1, len);
+ { int len = sizeof (struct type *) * (++($<ivec>1[0]) + 1);
+ $$ = (struct type **) xrealloc ((char *) $1, len);
$$[$<ivec>$[0]] = $3;
}
;
register int base = input_radix;
int unsigned_p = 0;
- extern double atof ();
-
if (parsed_float)
{
/* It's a float since it contains a point or an exponent. */
}
if (i >= base)
return ERROR; /* Invalid digit in this base */
- if(!unsigned_p && (prevn >= n))
+ /* Portably test for overflow (only works for nonzero values, so make
+ a second check for zero). */
+ if((prevn >= n) && n != 0)
unsigned_p=1; /* Try something unsigned */
- /* Don't do the range check if n==i and i==0, since that special
- case will give an overflow error. */
+ /* If range checking enabled, portably test for unsigned overflow. */
if(RANGE_CHECK && n!=0)
{
if((unsigned_p && (unsigned)prevn >= (unsigned)n))
{"++", INCREMENT, BINOP_END},
{"--", DECREMENT, BINOP_END},
{"->", ARROW, BINOP_END},
- {"&&", AND, BINOP_END},
- {"||", OR, BINOP_END},
+ {"&&", ANDAND, BINOP_END},
+ {"||", OROR, BINOP_END},
{"::", COLONCOLON, BINOP_END},
{"<<", LSH, BINOP_END},
{">>", RSH, BINOP_END},
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;
case 8:
if (!strncmp (tokstart, "unsigned", 8))
return UNSIGNED;
+ 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 STRUCT;
if (!strncmp (tokstart, "signed", 6))
- return SIGNED;
+ return SIGNED_KEYWORD;
if (!strncmp (tokstart, "sizeof", 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))
return ENUM;
if (!strncmp (tokstart, "long", 4))
return LONG;
- if (!strncmp (tokstart, "this", 4))
+ if (current_language->la_language == language_cplus
+ && !strncmp (tokstart, "this", 4))
{
static const char this_name[] =
{ CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
int hextype;
sym = lookup_symbol (tmp, expression_context_block,
- VAR_NAMESPACE, &is_a_field_of_this, NULL);
+ VAR_NAMESPACE,
+ current_language->la_language == language_cplus
+ ? &is_a_field_of_this : NULL,
+ NULL);
if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ||
lookup_partial_symtab (tmp))
{
yyerror (msg)
char *msg;
{
- error ("Invalid syntax in expression.");
+ error (msg ? msg : "Invalid syntax in expression.");
}
\f
/* Table mapping opcodes into strings for printing operators
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;
struct type *builtin_type_unsigned_long_long;
struct type *builtin_type_float;
struct type *builtin_type_double;
+struct type *builtin_type_long_double;
+struct type *builtin_type_complex;
+struct type *builtin_type_double_complex;
struct type ** const (c_builtin_types[]) =
{
&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,
&builtin_type_unsigned_long,
&builtin_type_unsigned_long_long,
+ &builtin_type_long_double,
+ &builtin_type_complex,
+ &builtin_type_double_complex,
0
};
-/* FIXME: Eventually do a separate defintion for C++. */
-
const struct language_defn c_language_defn = {
"c", /* Language name */
language_c,
c_error,
&BUILTIN_TYPE_LONGEST, /* longest signed integral type */
&BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */
- &builtin_type_double, /* longest floating point type */
+ &builtin_type_double, /* longest floating point type */ /*FIXME*/
+ "0x%x", "0x%", "x", /* Hex format, prefix, suffix */
+ "0%o", "0%", "o", /* Octal format, prefix, suffix */
+ c_op_print_tab, /* expression operators for printing */
+ LANG_MAGIC
+};
+
+const struct language_defn cplus_language_defn = {
+ "c++", /* Language name */
+ language_cplus,
+ c_builtin_types,
+ range_check_off,
+ type_check_off,
+ c_parse,
+ c_error,
+ &BUILTIN_TYPE_LONGEST, /* longest signed integral type */
+ &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */
+ &builtin_type_double, /* longest floating point type */ /*FIXME*/
"0x%x", "0x%", "x", /* Hex format, prefix, suffix */
"0%o", "0%", "o", /* Octal format, prefix, suffix */
c_op_print_tab, /* expression operators for printing */
void
_initialize_c_exp ()
{
- /* FIXME: The code below assumes that the sizes of the basic data
- types are the same on the host and target machines!!! */
-
- builtin_type_void = init_type (TYPE_CODE_VOID, 1, 0, "void");
-
- builtin_type_float = init_type (TYPE_CODE_FLT, sizeof (float), 0, "float");
- builtin_type_double = init_type (TYPE_CODE_FLT, sizeof (double), 0, "double");
-
- builtin_type_char = init_type (TYPE_CODE_INT, sizeof (char), 0, "char");
- builtin_type_short = init_type (TYPE_CODE_INT, sizeof (short), 0, "short");
- builtin_type_long = init_type (TYPE_CODE_INT, sizeof (long), 0, "long");
- builtin_type_int = init_type (TYPE_CODE_INT, sizeof (int), 0, "int");
-
- builtin_type_unsigned_char = init_type (TYPE_CODE_INT, sizeof (char), 1, "unsigned char");
- builtin_type_unsigned_short = init_type (TYPE_CODE_INT, sizeof (short), 1, "unsigned short");
- builtin_type_unsigned_long = init_type (TYPE_CODE_INT, sizeof (long), 1, "unsigned long");
- builtin_type_unsigned_int = init_type (TYPE_CODE_INT, sizeof (int), 1, "unsigned int");
-
+ builtin_type_void =
+ init_type (TYPE_CODE_VOID, 1,
+ 0,
+ "void", (struct objfile *) NULL);
+ builtin_type_char =
+ 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,
+ "unsigned char", (struct objfile *) NULL);
+ builtin_type_short =
+ init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "short", (struct objfile *) NULL);
+ builtin_type_unsigned_short =
+ init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned short", (struct objfile *) NULL);
+ builtin_type_int =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "int", (struct objfile *) NULL);
+ builtin_type_unsigned_int =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned int", (struct objfile *) NULL);
+ builtin_type_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0,
+ "long", (struct objfile *) NULL);
+ builtin_type_unsigned_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long", (struct objfile *) NULL);
builtin_type_long_long =
init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
- 0, "long long");
+ 0,
+ "long long", (struct objfile *) NULL);
builtin_type_unsigned_long_long =
init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
- 1, "unsigned long long");
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long long", (struct objfile *) NULL);
+ builtin_type_float =
+ init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "float", (struct objfile *) NULL);
+ builtin_type_double =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double", (struct objfile *) NULL);
+ builtin_type_long_double =
+ init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "long double", (struct objfile *) NULL);
+ builtin_type_complex =
+ init_type (TYPE_CODE_FLT, TARGET_COMPLEX_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex", (struct objfile *) NULL);
+ builtin_type_double_complex =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_COMPLEX_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double complex", (struct objfile *) NULL);
add_language (&c_language_defn);
- set_language (language_c); /* Make C the default language */
+ add_language (&cplus_language_defn);
}