* This code is derived from software copyrighted by the Free Software
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
static char sccsid
[] = "@(#)cplus-lex.c 6.4 (Berkeley) 5/8/91";
/* Separate lexical analyzer for GNU C++.
Copyright (C) 1987 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@mcc.com)
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* This file is the lexical analyzer for GNU C++. */
#define _IOFBF 2 /* Missing from GNU's stdio.h */
extern int errno
; /* needed for VAX. */
#define NULL_FILE "nla0:"
#define NULL_FILE "/dev/null"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
/* If you don't have strrchr, but instead have rindex,
add your machine to this list, and send mail to
tiemann@wheaties.ai.mit.edu. */
#if defined(sequent) || defined(convex)
/* This obstack is needed to hold text. It is not safe to use
TOKEN_BUFFER because `check_newline' calls `yylex'. */
static struct obstack inline_text_obstack
;
static char *inline_text_firstobj
;
/* Holds translations from TREE_CODEs to operator name strings,
i.e., opname_tab[PLUS_EXPR] == "+". */
int yychar
; /* the lookahead symbol */
YYSTYPE yylval
; /* the semantic value of the */
YYLTYPE yylloc
; /* location data for the lookahead */
/* the declaration found for the last IDENTIFIER token read in.
yylex must look this up to detect typedefs, which get token type TYPENAME,
so it is left around in case the identifier is not a typedef but is
used in a context which makes it a reference to a variable. */
tree ridpointers
[]; /* need this up here */
/* We may keep statistics about how long which files took to compile. */
static int header_time
, body_time
;
static tree
get_time_identifier ();
static tree filename_times
;
static tree this_filename_time
;
/* For implementing #pragma unit. */
tree current_unit_language
;
/* Array for holding counts of the numbers of tokens seen. */
/* Return something to represent absolute declarators containing a *.
TARGET is the absolute declarator that the * contains.
TYPE_QUALS is a list of modifiers such as const or volatile
to apply to the pointer type, represented as identifiers.
We return an INDIRECT_REF whose "contents" are TARGET
and whose type is the modifier list. */
make_pointer_declarator (type_quals
, target
)
if (target
&& TREE_CODE (target
) == IDENTIFIER_NODE
&& ANON_AGGRNAME_P (target
))
error ("type name expected before `*'");
return build1 (INDIRECT_REF
, type_quals
, target
);
/* Return something to represent absolute declarators containing a &.
TARGET is the absolute declarator that the & contains.
TYPE_QUALS is a list of modifiers such as const or volatile
to apply to the reference type, represented as identifiers.
We return an ADDR_EXPR whose "contents" are TARGET
and whose type is the modifier list. */
make_reference_declarator (type_quals
, target
)
if (TREE_CODE (target
) == ADDR_EXPR
)
error ("cannot declare references to references");
if (TREE_CODE (target
) == INDIRECT_REF
)
error ("cannot declare pointers to references");
if (TREE_CODE (target
) == IDENTIFIER_NODE
&& ANON_AGGRNAME_P (target
))
error ("type name expected before `&'");
return build1 (ADDR_EXPR
, type_quals
, target
);
/* Given a chain of STRING_CST nodes,
concatenate them into one STRING_CST
and give it a suitable array-of-chars data type. */
combine_strings (strings
)
if (TREE_CHAIN (strings
))
/* More than one in the chain, so concatenate. */
/* Don't include the \0 at the end of each substring,
Count wide strings and ordinary strings separately. */
for (t
= strings
; t
; t
= TREE_CHAIN (t
))
if (TREE_TYPE (t
) == int_array_type_node
)
wide_length
+= (TREE_STRING_LENGTH (t
) - 1);
length
+= (TREE_STRING_LENGTH (t
) - 1);
/* If anything is wide, the non-wides will be converted,
which makes them take more space. */
length
= length
* UNITS_PER_WORD
+ wide_length
;
p
= (char *) savealloc (length
);
/* Copy the individual strings into the new combined string.
If the combined string is wide, convert the chars to ints
for any individual strings that are not wide. */
for (t
= strings
; t
; t
= TREE_CHAIN (t
))
int len
= TREE_STRING_LENGTH (t
) - 1;
if ((TREE_TYPE (t
) == int_array_type_node
) == wide_flag
)
bcopy (TREE_STRING_POINTER (t
), q
, len
);
for (i
= 0; i
< len
; i
++)
((int *) q
)[i
] = TREE_STRING_POINTER (t
)[i
];
q
+= len
* UNITS_PER_WORD
;
value
= make_node (STRING_CST
);
TREE_STRING_POINTER (value
) = p
;
TREE_STRING_LENGTH (value
) = length
;
TREE_LITERAL (value
) = 1;
length
= TREE_STRING_LENGTH (value
);
if (TREE_TYPE (value
) == int_array_type_node
)
/* Create the array type for the string constant.
-Wwrite-strings says make the string constant an array of const char
so that copying it to a non-const pointer will get a warning. */
= build_type_variant (wide_flag
? integer_type_node
: char_type_node
,
= build_array_type (elements
,
build_index_type (build_int_2 (length
- 1, 0)));
= build_array_type (wide_flag
? integer_type_node
: char_type_node
,
build_index_type (build_int_2 (length
- 1, 0)));
TREE_LITERAL (value
) = 1;
/* Build names and nodes for overloaded operators. */
/* Memoized table for operator names. */
build_opid (code1
, code2
)
enum tree_code code1
, code2
;
register tree t
= make_node (OP_IDENTIFIER
);
extern struct obstack
*expression_obstack
, permanent_obstack
;
struct obstack
*ambient_obstack
= expression_obstack
;
expression_obstack
= &permanent_obstack
;
if ((tmp
= node_table
[(int)code1
]) == 0)
node_table
[(int)code1
] = tmp
= make_node (code1
);
if ((tmp
= node_table
[(int)code2
]) == 0)
node_table
[(int)code2
] = tmp
= make_node (code2
);
expression_obstack
= ambient_obstack
;
#define DEFTREECODE(SYM, NAME, TYPE, LEN) sizeof (NAME),
#define DEFTREECODE(SYM, NAME, TYPE, LEN) -1,
static short opname_end
[] = {
7, /* sizeof ("@@dummy"), */
#include "cplus-tree.def"
/* Given a TOKEN and its estimated tree code CODE, produce a name which
can be recognized by lookup_name. Based on the number of PARMS,
build an appropriate operator fnname. This function is needed because
until we know how many parameters we have, we cannot reliably tell
what function indeed we are trying to declare.
NPARMS is the number of additional parameters that this operator
will ultimately have. If NPARMS == -1, then we are just building
a name, and should not complain.
This would be a good candidate for memoizing. */
build_operator_fnname (declp
, parms
, nparms
)
char **opname_table
, *opname
;
if (parms
== void_list_node
)
type
= TREE_VALUE (parms
);
if (TREE_CODE (type
) == REFERENCE_TYPE
)
if (TREE_CODE (type
) == POINTER_TYPE
)
parms
= TREE_CHAIN (parms
);
if (TREE_CODE (decl
) == TYPE_EXPR
)
/* @@ may need to perform type instantiation here. */
error ("wrong number of arguments to type conversion operator");
/* The grammar will swallow an "()" if one was given.
We attempt to correct for this lossage here. */
if (TREE_OPERAND (decl
, 0)
&& TREE_CODE (TREE_OPERAND (decl
, 0)) == CALL_EXPR
)
rval
= build_typename_overload (groktypename (build_tree_list (TREE_TYPE (decl
), NULL_TREE
)));
rval
= build_typename_overload (groktypename (build_tree_list (TREE_TYPE (decl
), TREE_OPERAND (decl
, 0))));
if (TREE_CODE (TREE_PURPOSE (decl
)) == MODIFY_EXPR
)
opname_table
= assignop_tab
;
opname_table
= opname_tab
;
code
= TREE_CODE (TREE_VALUE (decl
));
opname
= opname_table
[(int) code
];
if (nparms
== 1 || nparms
> 2)
error ("wrong number of parameters op `operator %s'", opname
);
rval
= get_identifier ("<invalid operator>");
TREE_OVERLOADED (rval
) = 1;
if (nparms
== 1 || nparms
< 0)
error ("wrong number of parameters to `operator ->()'");
error ("too few arguments to `operator ->()(...)'");
/* 4 happens when we pass in the canonical number
error ("too many arguments to `operator ->()(...)'");
/* The two following entrys are for two different ways of
encoding `operator ='. */
if (nparms
!= 2 && nparms
>= 0)
if (nparms
!= 2 && nparms
>= 0)
return get_identifier (OPERATOR_NEW_FORMAT
);
return get_identifier ("__builtin_new");
error ("too many parameters to `operator ::delete'");
return get_identifier ("__builtin_delete");
/* Whatever it was, we know its arity. Just check that it
has the right number of parameters defined. */
/* These are the only operators which do not need
to have a class-type associated with them. */
if (code
== PREDECREMENT_EXPR
|| code
== POSTINCREMENT_EXPR
|| code
== COMPONENT_REF
)
|| code
== METHOD_CALL_EXPR
)
else if (nparms
!= tree_code_length
[(int) code
])
error ("wrong number of parameters to `operator %s'", opname
);
else if (erred
== 0 && code
!= TREE_CODE (TREE_VALUE (decl
)))
enum tree_code assign_code
= ERROR_MARK
;
assign_code
= TREE_CODE (TREE_PURPOSE (decl
));
decl
= build_opid (assign_code
, code
);
error ("`operator %s' must have at least one class type", opname
);
sprintf (buf
, OPERATOR_ASSIGN_FORMAT
, tree_code_name
[(int) code
]);
buf
[opname_end
[(int) code
] + sizeof (OPERATOR_ASSIGN_FORMAT
) - 3] = '\0';
sprintf (buf
, OPERATOR_FORMAT
, tree_code_name
[(int) code
]);
buf
[opname_end
[(int) code
] + sizeof (OPERATOR_FORMAT
) - 3] = '\0';
rval
= get_identifier (buf
);
TREE_OVERLOADED (rval
) = 1;
operator_name_string (name
)
char *opname
= IDENTIFIER_POINTER (name
)
+ sizeof (OPERATOR_FORMAT
) - sizeof ("%s");
/* Works for builtin and user defined types. */
if (IDENTIFIER_GLOBAL_VALUE (name
)
&& TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name
)) == TYPE_DECL
)
return IDENTIFIER_POINTER (name
);
if (! strncmp (opname
, "assign", 6))
for (i
= 0; i
< LAST_CPLUS_TREE_CODE
; i
++)
if (! strncmp (opname
, tree_code_name
[i
], opname_end
[i
]))
assert (i
!= LAST_CPLUS_TREE_CODE
);
int lineno
; /* current line number in file being read */
FILE *finput
; /* input file.
Normally a pipe from the preprocessor. */
static FILE *finput1
; /* Real input files: 1 is main input file */
static FILE *finput2
; /* 2 is input file for inline functions */
int interface_only
; /* whether or not current file is only for
interface definitions. */
int interface_unknown
; /* whether or not we know this class
to behave according to #pragma interface. */
static int maxtoken
; /* Current nominal length of token buffer. */
char *token_buffer
; /* Pointer to token buffer.
Actual allocated length is maxtoken + 2. */
static int max_wide
; /* Current nominal length of wide_buffer. */
static int *wide_buffer
; /* Pointer to wide-string buffer.
Actual allocated length is max_wide + 1. */
/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$ gplus.gperf */
struct resword
{ char *name
; short token
; enum rid rid
;};
#define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 13
#define MAX_HASH_VALUE 147
144 is the maximum key range
register int unsigned len
;
static unsigned char hash_table
[] =
147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
147, 147, 147, 147, 147, 0, 147, 19, 6, 27,
37, 0, 12, 1, 15, 63, 147, 4, 0, 56,
20, 15, 42, 147, 31, 5, 26, 39, 32, 10,
147, 40, 147, 147, 147, 147, 147, 147,
register int hval
= len
;
hval
+= hash_table
[str
[3]];
hval
+= hash_table
[str
[0]];
return hval
+ hash_table
[str
[len
- 1]] ;
is_reserved_word (str
, len
)
register unsigned int len
;
static struct resword wordlist
[] =
{"",}, {"",}, {"",}, {"",},
{"long", TYPESPEC
, RID_LONG
,},
{"",}, {"",}, {"",}, {"",},
{"__alignof__", ALIGNOF
, NORID
},
{"while", WHILE
, NORID
,},
{"",}, {"",}, {"",}, {"",}, {"",},
{"__alignof", ALIGNOF
, NORID
},
{"all", ALL
, NORID
/* Extension */,},
{"sizeof", SIZEOF
, NORID
,},
{"__const__", TYPE_QUAL
, RID_CONST
},
{"__volatile", TYPE_QUAL
, RID_VOLATILE
},
{"extern", SCSPEC
, RID_EXTERN
,},
{"__volatile__", TYPE_QUAL
, RID_VOLATILE
},
{"__inline", SCSPEC
, RID_INLINE
},
{"exception", AGGR
, RID_EXCEPTION
/* Extension */,},
{"__inline__", SCSPEC
, RID_INLINE
},
{"except", EXCEPT
, NORID
/* Extension */,},
{"break", BREAK
, NORID
,},
{"__attribute", ATTRIBUTE
, NORID
},
{"__attribute__", ATTRIBUTE
, NORID
},
{"raise", RAISE
, NORID
/* Extension */,},
{"class", AGGR
, RID_CLASS
,},
{"delete", DELETE
, NORID
,},
{"typeof", TYPEOF
, NORID
,},
{"typedef", SCSPEC
, RID_TYPEDEF
,},
{"raises", RAISES
, NORID
/* Extension */,},
{"__const", TYPE_QUAL
, RID_CONST
},
{"double", TYPESPEC
, RID_DOUBLE
,},
{"__typeof__", TYPEOF
, NORID
},
{"switch", SWITCH
, NORID
,},
{"auto", SCSPEC
, RID_AUTO
,},
{"friend", SCSPEC
, RID_FRIEND
,},
{"reraise", RERAISE
, NORID
/* Extension */,},
{"volatile", TYPE_QUAL
, RID_VOLATILE
,},
{"__typeof", TYPEOF
, NORID
},
{"continue", CONTINUE
, NORID
,},
{"float", TYPESPEC
, RID_FLOAT
,},
{"const", TYPE_QUAL
, RID_CONST
,},
{"static", SCSPEC
, RID_STATIC
,},
{"virtual", SCSPEC
, RID_VIRTUAL
,},
{"short", TYPESPEC
, RID_SHORT
,},
{"signed", TYPESPEC
, RID_SIGNED
,},
{"try", TRY
, NORID
/* Extension */,},
{"__signed__", TYPESPEC
, RID_SIGNED
},
{"catch", CATCH
, NORID
,},
{"public", PUBLIC
, NORID
,},
{"struct", AGGR
, RID_RECORD
,},
{"union", AGGR
, RID_UNION
,},
{"private", PRIVATE
, NORID
,},
{"operator", OPERATOR
, NORID
,},
{"default", DEFAULT
, NORID
,},
{"dynamic", DYNAMIC
, NORID
,},
{"overload", OVERLOAD
, NORID
,},
{"int", TYPESPEC
, RID_INT
,},
{"char", TYPESPEC
, RID_CHAR
,},
{"return", RETURN
, NORID
,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"__signed", TYPESPEC
, RID_SIGNED
},
{"void", TYPESPEC
, RID_VOID
,},
{"protected", PROTECTED
, NORID
,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"inline", SCSPEC
, RID_INLINE
,},
{"register", SCSPEC
, RID_REGISTER
,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",},
{"unsigned", TYPESPEC
, RID_UNSIGNED
,},
if (len
<= MAX_WORD_LENGTH
&& len
>= MIN_WORD_LENGTH
)
register int key
= hash (str
, len
);
if (key
<= MAX_HASH_VALUE
&& key
>= MIN_HASH_VALUE
)
register char *s
= wordlist
[key
].name
;
if (*s
== *str
&& !strcmp (str
+ 1, s
+ 1))
/* The elements of `ridpointers' are identifier nodes
for the reserved type names and storage classes.
It is indexed by a RID_... value. */
tree ridpointers
[(int) RID_MAX
];
static int skip_white_space ();
get_time_identifier (name
)
char *buf
= (char *)alloca (len
+ 6);
bcopy (name
, buf
+5, len
);
time_identifier
= get_identifier (buf
);
if (IDENTIFIER_LOCAL_VALUE (time_identifier
) == NULL_TREE
)
int temp
= allocation_temporary_p ();
end_temporary_allocation ();
IDENTIFIER_LOCAL_VALUE (time_identifier
) = build_int_2 (0, 0);
IDENTIFIER_CLASS_VALUE (time_identifier
) = build_int_2 (0, 1);
IDENTIFIER_GLOBAL_VALUE (time_identifier
) = filename_times
;
filename_times
= time_identifier
;
resume_temporary_allocation ();
int old_quiet_flag
= quiet_flag
;
quiet_flag
= old_quiet_flag
;
/* Table indexed by tree code giving a string containing a character
classifying the tree code. Possibilities are
t, d, s, c, r and e. See cplus-tree.def for details. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
char *cplus_tree_code_type
[] = {
#include "cplus-tree.def"
/* Table indexed by tree code giving number of expression
operands beyond the fixed part of the node structure.
Not used for types or decls. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
int cplus_tree_code_length
[] = {
#include "cplus-tree.def"
/* Names of tree components.
Used for printing out the tree and error messages. */
#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
char *cplus_tree_code_name
[] = {
#include "cplus-tree.def"
this_filename_time
= get_time_identifier ("<top level>");
if (flag_detailed_statistics
)
body_time
= my_gettime ();
TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time
)) = body_time
;
/* Use 4.4 BSD fropen() stdio function to fake re-reads of inline functions.
We just decrement the buffer count until it reaches zero. */
static unsigned next_inline_count
= 0;
read_next_inline(unused_cookie
, unused_buf
, count
)
count
= count
> next_inline_count
? next_inline_count
: count
;
next_inline_count
-= count
;
/* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989.
Stuck this hack in to get the files open correctly; this is called
in place of init_lex if we are an unexec'd binary. */
finput2
= fropen ((void *) 0, read_next_inline
);
extern int *init_parse ();
extern char *(*decl_printable_name
) ();
extern char *lang_printable_name ();
extern struct rtx_def
*(*lang_expand_expr
) ();
extern struct rtx_def
*cplus_expand_expr ();
/* Make identifier nodes long enough for the language-specific slots. */
set_identifier_size (sizeof (struct lang_identifier
));
decl_printable_name
= lang_printable_name
;
lang_expand_expr
= cplus_expand_expr
;
= (char **) realloc (tree_code_type
,
sizeof (char *) * LAST_CPLUS_TREE_CODE
);
= (int *) realloc (tree_code_length
,
sizeof (int) * LAST_CPLUS_TREE_CODE
);
= (char **) realloc (tree_code_name
,
sizeof (char *) * LAST_CPLUS_TREE_CODE
);
bcopy (cplus_tree_code_type
,
tree_code_type
+ LAST_AND_UNUSED_TREE_CODE
,
(LAST_CPLUS_TREE_CODE
- LAST_AND_UNUSED_TREE_CODE
) * sizeof (char *));
bcopy (cplus_tree_code_length
,
tree_code_length
+ LAST_AND_UNUSED_TREE_CODE
,
(LAST_CPLUS_TREE_CODE
- LAST_AND_UNUSED_TREE_CODE
) * sizeof (int));
bcopy (cplus_tree_code_name
,
tree_code_name
+ LAST_AND_UNUSED_TREE_CODE
,
(LAST_CPLUS_TREE_CODE
- LAST_AND_UNUSED_TREE_CODE
) * sizeof (char *));
node_table
= (tree
*)oballoc (LAST_CPLUS_TREE_CODE
* sizeof (tree
));
opname_tab
= (char **)oballoc (LAST_CPLUS_TREE_CODE
* sizeof (char *));
assignop_tab
= (char **)oballoc (LAST_CPLUS_TREE_CODE
* sizeof (char *));
for (i
= 0; i
< LAST_CPLUS_TREE_CODE
; i
++)
/* Our only interest is _ref and _expr. */
if (tree_code_type
[i
][0] == 'r' || tree_code_type
[i
][0] == 'e')
char *end
= (char *)strrchr (tree_code_name
[i
], '_');
opname_end
[i
] = end
- tree_code_name
[i
];
opname_end
[i
] = strlen (tree_code_name
[i
]);
opname_end
[i
] = strlen (tree_code_name
[i
]);
obstack_init (&inline_text_obstack
);
inline_text_firstobj
= (char *) obstack_alloc (&inline_text_obstack
, 0);
/* Start it at 0, because check_newline is called at the very beginning
and will increment it to 1. */
finput2
= fropen ((void *) 0, read_next_inline
);
current_function_decl
= NULL
;
token_buffer
= (char *) xmalloc (maxtoken
+ 2);
wide_buffer
= (int *) xmalloc (max_wide
+ 1);
ridpointers
[(int) RID_INT
] = get_identifier ("int");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_INT
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_INT
]));
ridpointers
[(int) RID_CHAR
] = get_identifier ("char");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_CHAR
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_CHAR
]));
ridpointers
[(int) RID_VOID
] = get_identifier ("void");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_VOID
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_VOID
]));
ridpointers
[(int) RID_FLOAT
] = get_identifier ("float");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_FLOAT
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_FLOAT
]));
ridpointers
[(int) RID_DOUBLE
] = get_identifier ("double");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_DOUBLE
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_DOUBLE
]));
ridpointers
[(int) RID_SHORT
] = get_identifier ("short");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_SHORT
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_SHORT
]));
ridpointers
[(int) RID_LONG
] = get_identifier ("long");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_LONG
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_LONG
]));
ridpointers
[(int) RID_UNSIGNED
] = get_identifier ("unsigned");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_UNSIGNED
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_UNSIGNED
]));
ridpointers
[(int) RID_SIGNED
] = get_identifier ("signed");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_SIGNED
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_SIGNED
]));
ridpointers
[(int) RID_INLINE
] = get_identifier ("inline");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_INLINE
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_INLINE
]));
ridpointers
[(int) RID_CONST
] = get_identifier ("const");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_CONST
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_CONST
]));
ridpointers
[(int) RID_VOLATILE
] = get_identifier ("volatile");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_VOLATILE
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_VOLATILE
]));
ridpointers
[(int) RID_AUTO
] = get_identifier ("auto");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_AUTO
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_AUTO
]));
ridpointers
[(int) RID_STATIC
] = get_identifier ("static");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_STATIC
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_STATIC
]));
ridpointers
[(int) RID_EXTERN
] = get_identifier ("extern");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_EXTERN
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_EXTERN
]));
ridpointers
[(int) RID_TYPEDEF
] = get_identifier ("typedef");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_TYPEDEF
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_TYPEDEF
]));
ridpointers
[(int) RID_REGISTER
] = get_identifier ("register");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_REGISTER
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_REGISTER
]));
/* C++ extensions. These are probably not correctly named. */
class_type_node
= build_int_2 (class_type
, 0);
TREE_TYPE (class_type_node
) = class_type_node
;
ridpointers
[(int) RID_CLASS
] = class_type_node
;
record_type_node
= build_int_2 (record_type
, 0);
TREE_TYPE (record_type_node
) = record_type_node
;
ridpointers
[(int) RID_RECORD
] = record_type_node
;
union_type_node
= build_int_2 (union_type
, 0);
TREE_TYPE (union_type_node
) = union_type_node
;
ridpointers
[(int) RID_UNION
] = union_type_node
;
enum_type_node
= build_int_2 (enum_type
, 0);
TREE_TYPE (enum_type_node
) = enum_type_node
;
ridpointers
[(int) RID_ENUM
] = enum_type_node
;
ridpointers
[(int) RID_VIRTUAL
] = get_identifier ("virtual");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_VIRTUAL
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_VIRTUAL
]));
ridpointers
[(int) RID_FRIEND
] = get_identifier ("friend");
SET_IDENTIFIER_AS_LIST (ridpointers
[(int) RID_FRIEND
],
build_tree_list (NULL_TREE
, ridpointers
[(int) RID_FRIEND
]));
/* Exception handling extensions. */
exception_type_node
= build_int_2 (exception_type
, 0);
TREE_TYPE (exception_type_node
) = exception_type_node
;
ridpointers
[(int) RID_EXCEPTION
] = exception_type_node
;
opname_tab
[(int) COMPONENT_REF
] = "->";
opname_tab
[(int) METHOD_CALL_EXPR
] = "->()";
opname_tab
[(int) INDIRECT_REF
] = "(unary *)";
opname_tab
[(int) ARRAY_REF
] = "[]";
opname_tab
[(int) MODIFY_EXPR
] = "=";
opname_tab
[(int) NEW_EXPR
] = "new";
opname_tab
[(int) DELETE_EXPR
] = "delete";
opname_tab
[(int) COND_EXPR
] = "... ? ... : ...";
opname_tab
[(int) CALL_EXPR
] = "()";
opname_tab
[(int) PLUS_EXPR
] = "+";
opname_tab
[(int) MINUS_EXPR
] = "-";
opname_tab
[(int) MULT_EXPR
] = "*";
opname_tab
[(int) TRUNC_DIV_EXPR
] = "/";
opname_tab
[(int) CEIL_DIV_EXPR
] = "(ceiling /)";
opname_tab
[(int) FLOOR_DIV_EXPR
] = "(floor /)";
opname_tab
[(int) ROUND_DIV_EXPR
] = "(round /)";
opname_tab
[(int) TRUNC_MOD_EXPR
] = "%";
opname_tab
[(int) CEIL_MOD_EXPR
] = "(ceiling %)";
opname_tab
[(int) FLOOR_MOD_EXPR
] = "(floor %)";
opname_tab
[(int) ROUND_MOD_EXPR
] = "(round %)";
opname_tab
[(int) NEGATE_EXPR
] = "-";
opname_tab
[(int) MIN_EXPR
] = "<?";
opname_tab
[(int) MAX_EXPR
] = ">?";
opname_tab
[(int) ABS_EXPR
] = "abs";
opname_tab
[(int) FFS_EXPR
] = "ffs";
opname_tab
[(int) LSHIFT_EXPR
] = "<<";
opname_tab
[(int) RSHIFT_EXPR
] = ">>";
opname_tab
[(int) BIT_IOR_EXPR
] = "|";
opname_tab
[(int) BIT_XOR_EXPR
] = "^";
opname_tab
[(int) BIT_AND_EXPR
] = "&";
opname_tab
[(int) BIT_ANDTC_EXPR
] = "&~";
opname_tab
[(int) BIT_NOT_EXPR
] = "~";
opname_tab
[(int) TRUTH_ANDIF_EXPR
] = "&&";
opname_tab
[(int) TRUTH_ORIF_EXPR
] = "||";
opname_tab
[(int) TRUTH_AND_EXPR
] = "strict &&";
opname_tab
[(int) TRUTH_OR_EXPR
] = "strict ||";
opname_tab
[(int) TRUTH_NOT_EXPR
] = "!";
opname_tab
[(int) LT_EXPR
] = "<";
opname_tab
[(int) LE_EXPR
] = "<=";
opname_tab
[(int) GT_EXPR
] = ">";
opname_tab
[(int) GE_EXPR
] = ">=";
opname_tab
[(int) EQ_EXPR
] = "==";
opname_tab
[(int) NE_EXPR
] = "!=";
opname_tab
[(int) IN_EXPR
] = "in";
opname_tab
[(int) SET_LE_EXPR
] = "subset";
opname_tab
[(int) CARD_EXPR
] = "#";
opname_tab
[(int) RANGE_EXPR
] = "..";
opname_tab
[(int) CONVERT_EXPR
] = "(unary +)";
opname_tab
[(int) ADDR_EXPR
] = "(unary &)";
opname_tab
[(int) PREDECREMENT_EXPR
] = "--";
opname_tab
[(int) PREINCREMENT_EXPR
] = "++";
opname_tab
[(int) POSTDECREMENT_EXPR
] = "--";
opname_tab
[(int) POSTINCREMENT_EXPR
] = "++";
opname_tab
[(int) COMPOUND_EXPR
] = ",";
assignop_tab
[(int) NOP_EXPR
] = "=";
assignop_tab
[(int) PLUS_EXPR
] = "+=";
assignop_tab
[(int) MINUS_EXPR
] = "-=";
assignop_tab
[(int) MULT_EXPR
] = "*=";
assignop_tab
[(int) TRUNC_DIV_EXPR
] = "/=";
assignop_tab
[(int) CEIL_DIV_EXPR
] = "(ceiling /=)";
assignop_tab
[(int) FLOOR_DIV_EXPR
] = "(floor /=)";
assignop_tab
[(int) ROUND_DIV_EXPR
] = "(round /=)";
assignop_tab
[(int) TRUNC_MOD_EXPR
] = "%=";
assignop_tab
[(int) CEIL_MOD_EXPR
] = "(ceiling %=)";
assignop_tab
[(int) FLOOR_MOD_EXPR
] = "(floor %=)";
assignop_tab
[(int) ROUND_MOD_EXPR
] = "(round %=)";
assignop_tab
[(int) MIN_EXPR
] = "<?=";
assignop_tab
[(int) MAX_EXPR
] = ">?=";
assignop_tab
[(int) LSHIFT_EXPR
] = "<<=";
assignop_tab
[(int) RSHIFT_EXPR
] = ">>=";
assignop_tab
[(int) BIT_IOR_EXPR
] = "|=";
assignop_tab
[(int) BIT_XOR_EXPR
] = "^=";
assignop_tab
[(int) BIT_AND_EXPR
] = "&=";
#define UNSET_RESERVED_WORD(STRING) \
do { is_reserved_word (STRING, sizeof (STRING) - 1)->name = ""; } while (0)
if (! flag_handle_exceptions
)
/* Easiest way to not reconize exception
UNSET_RESERVED_WORD ("all");
UNSET_RESERVED_WORD ("except");
UNSET_RESERVED_WORD ("exception");
UNSET_RESERVED_WORD ("raise");
UNSET_RESERVED_WORD ("raises");
UNSET_RESERVED_WORD ("reraise");
UNSET_RESERVED_WORD ("try");
UNSET_RESERVED_WORD ("asm");
if (flag_no_asm
|| flag_traditional
)
UNSET_RESERVED_WORD ("typeof");
token_count
= init_parse ();
reinit_parse_for_function ()
current_base_init_list
= NULL_TREE
;
current_member_init_list
= NULL_TREE
;
/* Functions and data structures for #pragma interface.
`#pragma implementation' means that the main file being compiled
is considered to implement (provide) the classes that appear in
its main body. I.e., if this is file "foo.cc", and class `bar'
is defined in "foo.cc", then we say that "foo.cc implements bar".
All main input files "implement" themselves automagically.
`#pragma interface' means that unless this file (of the form "foo.h"
is not presently being included by file "foo.cc", the
CLASSTYPE_INTERFACE_ONLY bit gets set. The effect is that none
of the vtables nor any of the inline functions defined in foo.h
There are cases when we want to link files such as "defs.h" and
"main.cc". In this case, we give "defs.h" a `#pragma interface',
and "main.cc" has `#pragma implementation "defs.h"'. */
static struct impl_files
*impl_file_chain
;
/* Helper function to load global variables with interface
extract_interface_info ()
tree fileinfo
= get_time_identifier (input_filename
);
fileinfo
= IDENTIFIER_CLASS_VALUE (fileinfo
);
interface_only
= TREE_INT_CST_LOW (fileinfo
);
interface_unknown
= TREE_INT_CST_HIGH (fileinfo
);
/* Return nonzero if S and T are not considered part of an
INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */
/* Set the interface/implementation bits for this scope. */
struct impl_files
*ifiles
;
char *s1
= strrchr (s
, '/');
for (ifiles
= impl_file_chain
; ifiles
; ifiles
= ifiles
->next
)
char *t1
= ifiles
->filename
;
if (*s1
!= *t1
|| *s1
== 0)
while (*s1
== *t1
&& *s1
!= 0)
/* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc. */
if (*s1
== '\0' || s1
[-1] != '.' || t1
[-1] != '.')
set_typedecl_interface_info (prev
, vars
)
tree id
= get_time_identifier (DECL_SOURCE_FILE (vars
));
tree fileinfo
= IDENTIFIER_CLASS_VALUE (id
);
tree type
= TREE_TYPE (vars
);
CLASSTYPE_INTERFACE_ONLY (type
) = TREE_INT_CST_LOW (fileinfo
)
= interface_strcmp (DECL_SOURCE_FILE (vars
));
set_vardecl_interface_info (prev
, vars
)
tree type
= DECL_VPARENT (vars
);
tree type
= DECL_CONTEXT (vars
);
if (CLASSTYPE_INTERFACE_UNKNOWN (type
) == 0)
if (CLASSTYPE_INTERFACE_ONLY (type
))
set_typedecl_interface_info (prev
, TYPE_NAME (type
));
TREE_EXTERNAL (vars
) = CLASSTYPE_INTERFACE_ONLY (type
);
TREE_PUBLIC (vars
) = ! CLASSTYPE_INTERFACE_ONLY (type
);
CLASSTYPE_VTABLE_NEEDS_WRITING (type
) |= TREE_PUBLIC (vars
);
/* Called from the top level: if there are any pending inlines to
do, set up to process them now. */
struct pending_inline
*prev
= 0, *tail
;
struct pending_inline
*t
=
(struct pending_inline
*) obstack_alloc (&inline_text_obstack
,
sizeof (struct pending_inline
));
/* Record state we were in when we decided to process
inline functions instead. */
t
->next
= pending_inlines
;
t
->filename
= input_filename
;
t
->token_value
= yylval
.itype
;
/* Reverse the pending inline functions, since
they were cons'd instead of appended. */
/* Now start processing the first inline function. */
pending_inlines
= pending_inlines
->next
;
setvbuf (finput2
, t
->buf
, _IOFBF
, t
->len
- 1);
next_inline_count
= t
->len
- 1;
input_filename
= t
->filename
;
yychar
= PRE_PARSED_FUNCTION_DECL
;
yylval
.ttype
= t
->fndecl
;
TREE_INLINE (t
->fndecl
) = 1;
/* Since inline methods can refer to text which has not yet been seen,
we store the text of the method in a structure which is placed in the
DECL_PENDING_INLINE_INFO field of the FUNCTION_DECL.
After parsing the body of the class definition, the FUNCTION_DECL's are
scanned to see which ones have this field set. Those are then digested
This function's FUNCTION_DECL will have a bit set in its common so
that we know to watch out for it. */
consume_string (this_obstack
)
register struct obstack
*this_obstack
;
obstack_1grow (this_obstack
, c
);
obstack_1grow (this_obstack
, c
);
warning ("ANSI C forbids newline in string constant");
obstack_1grow (this_obstack
, c
);
static int nextchar
= -1;
static int nextyychar
= -1;
static YYSTYPE nextyylval
;
static tree nextlastiddecl
;
/* Get input from stream. When compiling under Cadillac,
the bytes must be coaxed out via their read protocol.
Otherwise, they come easily via standard input interface. */
register int ch
= getc (finput
);
/* Return next non-whitespace input character, which may come
from `finput', or from `nextchar'. */
return skip_white_space (c
);
/* Unget character CH from the input stream.
If RESCAN is non-zero, then we want to `see' this
character as the next input token. */
/* Unget a characater from the input stream. */
if (yychar
== YYEMPTY
|| rescan
== 0)
reinit_parse_for_method (yychar
, decl
)
int starting_lineno
= lineno
;
char *starting_filename
= input_filename
;
if (yychar
!= ':' && yychar
!= RETURN
)
yyerror ("parse error in method specification");
obstack_1grow (&inline_text_obstack
, yychar
);
int this_lineno
= lineno
;
/* Don't lose our cool if there are lots of comments. */
if (lineno
- this_lineno
)
if (lineno
- this_lineno
== 1)
obstack_1grow (&inline_text_obstack
, '\n');
sprintf (buf
, "\n# %d \"", lineno
);
obstack_grow (&inline_text_obstack
, buf
, len
);
len
= strlen (input_filename
);
obstack_grow (&inline_text_obstack
, input_filename
, len
);
obstack_1grow (&inline_text_obstack
, '\"');
obstack_1grow (&inline_text_obstack
, '\n');
/* strings must be read differently than text. */
obstack_1grow (&inline_text_obstack
, c
);
consume_string (&inline_text_obstack
);
while (c
> ' ') /* ASCII dependent! */
obstack_1grow (&inline_text_obstack
, c
);
if (c
== '{') goto main_loop
;
consume_string (&inline_text_obstack
);
error ("function body for constructor missing");
obstack_1grow (&inline_text_obstack
, '{');
obstack_1grow (&inline_text_obstack
, '}');
obstack_1grow (&inline_text_obstack
, c
);
error_with_file_and_line (starting_filename
,
"parse error in method specification");
else obstack_1grow (&inline_text_obstack
, '{');
int this_lineno
= lineno
;
c
= skip_white_space (getc (finput
));
/* Don't lose our cool if there are lots of comments. */
if (lineno
- this_lineno
)
if (lineno
- this_lineno
== 1)
obstack_1grow (&inline_text_obstack
, '\n');
sprintf (buf
, "\n# %d \"", lineno
);
obstack_grow (&inline_text_obstack
, buf
, len
);
len
= strlen (input_filename
);
obstack_grow (&inline_text_obstack
, input_filename
, len
);
obstack_1grow (&inline_text_obstack
, '\"');
obstack_1grow (&inline_text_obstack
, '\n');
obstack_1grow (&inline_text_obstack
, c
);
consume_string (&inline_text_obstack
);
obstack_1grow (&inline_text_obstack
, c
);
current_base_init_list
= NULL_TREE
;
current_member_init_list
= NULL_TREE
;
len
= obstack_object_size (&inline_text_obstack
);
/* If the buffer given to setvbuf is shorter than eight bytes long,
setvbuf will (in violation of its man page) ignore the buffer
and call malloc to get a bigger one. */
obstack_1grow (&inline_text_obstack
, ' ');
obstack_1grow (&inline_text_obstack
, '\0');
len
= obstack_object_size (&inline_text_obstack
);
if (fndecl
== void_type_node
)
/* Happens when we get two declarations of the same
function in the same scope. */
char *buf
= obstack_base (&inline_text_obstack
);
obstack_free (&inline_text_obstack
, buf
);
struct pending_inline
*t
;
char *buf
= obstack_base (&inline_text_obstack
);
obstack_finish (&inline_text_obstack
);
t
= (struct pending_inline
*) obstack_alloc (&inline_text_obstack
,
sizeof (struct pending_inline
));
t
->lineno
= starting_lineno
;
t
->filename
= starting_filename
;
DECL_PENDING_INLINE_INFO (fndecl
) = t
;
/* Build a default function named NAME for type TYPE.
KIND says what to build. Currently only two kinds of default functions
When KIND == 0, build default X(X&) constructor.
When KIND == 1, build default destructor. */
cons_up_default_function (type
, name
, kind
)
extern tree void_list_node
;
name
= build_parse_node (BIT_NOT_EXPR
, name
);
/* Default constructor. */
type
= build_type_variant (type
, 1, 0);
argtype
= build_reference_type (type
);
args
= tree_cons (NULL_TREE
,
build_tree_list (hash_tree_chain (argtype
, NULL_TREE
),
fn
= start_method (NULL_TREE
,
build_parse_node (CALL_EXPR
, name
, args
, NULL_TREE
),
if (fn
== void_type_node
)
obstack_1grow (&inline_text_obstack
, '{');
obstack_1grow (&inline_text_obstack
, '}');
obstack_1grow (&inline_text_obstack
, ' ');
obstack_1grow (&inline_text_obstack
, '\0');
current_base_init_list
= NULL_TREE
;
current_member_init_list
= NULL_TREE
;
len
= obstack_object_size (&inline_text_obstack
);
struct pending_inline
*t
;
char *buf
= obstack_base (&inline_text_obstack
);
obstack_finish (&inline_text_obstack
);
t
= (struct pending_inline
*) obstack_alloc (&inline_text_obstack
,
sizeof (struct pending_inline
));
t
->filename
= input_filename
;
DECL_PENDING_INLINE_INFO (fn
) = t
;
/* We make this declaration private (static in the C sense). */
DECL_COMPILER_GENERATED_P (fn
) = 1;
/* Heuristic to tell whether the user is missing a semicolon
after a struct or enum declaration. Emit an error message
if we know the user has blown it. */
check_for_missing_semicolon (type
)
if (ANON_AGGRNAME_P (DECL_NAME (TYPE_NAME (type
))))
error ("semicolon missing after %s declaration",
TREE_CODE (type
) == ENUMERAL_TYPE
? "enum" : "struct");
error ("semicolon missing after declaration of `%s'",
TYPE_NAME_STRING (type
));
shadow_tag (build_tree_list (0, type
));
/* Could probably also hack cases where class { ... } f (); appears. */
note_got_semicolon (type
)
CLASSTYPE_GOT_SEMICOLON (type
) = 1;
/* If C is not whitespace, return C.
Otherwise skip whitespace and return first nonwhite char read. */
/* Don't recognize comments in cc1: all comments are removed by cpp,
and cpp output can include / and * consecutively as operators. */
if (c
!= '*' && c
!= '/')
error ("unterminated comment");
error ("unterminated comment");
while (c
== ' ' || c
== '\t');
error ("stray '\\' in program");
/* Make the token buffer longer, preserving the data in it.
P should point to just beyond the last valid character in the old buffer.
The value we return is a pointer to the new buffer
at a place corresponding to P. */
int offset
= p
- token_buffer
;
maxtoken
= maxtoken
* 2 + 10;
token_buffer
= (char *) xrealloc (token_buffer
, maxtoken
+ 2);
return token_buffer
+ offset
;
/* This includes code from write_segment, stolen from unexec.c */
register caddr_t ptr
, end
;
register int i
, nwrite
, ret
;
extern int been_here_before
, just_done_unexec
, my_edata
;
extern char *dump_source_name
;
extern char *asm_file_name
, previous_asm_file_name
[];
char dump_file_name
[256]; /* Fixed-sized buffer -- sigh. */
caddr_t end_of_data
, end_of_heap
;
bzero (zeros
, sizeof zeros
);
/* Here we have just seen `#pragma dump '.
The name to dump to, a string constant, may follow. */
while (c
== ' ' || c
== '\t');
/* If no argument, default to something like "dumped-cc1plus". */
strcpy (dump_file_name
, "dumped-");
if (tmp
= strrchr (dump_source_name
, '/'))
dump_source_name
= tmp
+ 1;
strcat (dump_file_name
, dump_source_name
);
|| TREE_CODE (yylval
.ttype
) != STRING_CST
)
error ("invalid #pragma dump");
strcpy (dump_file_name
, TREE_STRING_POINTER (yylval
.ttype
));
been_here_before
= 1; /* Raise the flag! */
strcpy(previous_asm_file_name
, asm_file_name
);
printf("\nDumping %s to %s...\n", dump_source_name
, dump_file_name
);
end_of_heap
= (caddr_t
)sbrk(0);
end_of_data
= (caddr_t
)((int)(&my_edata
)&~(getpagesize()-1));
data_size
= (int)(end_of_heap
-end_of_data
);
printf("Data size = %d\n", data_size
);
new = creat (dump_file_name
, 0666);
/* distance to next multiple of 128. */
nwrite
= (((int) ptr
+ 128) & -128) - (int) ptr
;
/* But not beyond specified end. */
if (nwrite
> end
- ptr
) nwrite
= end
- ptr
;
ret
= write (new, ptr
, nwrite
);
/* If write gets a page fault, it means we reached
a gap between the old text segment and the old data segment.
This gap has probably been remapped into part of the text segment.
So write zeros for it. */
if (ret
== -1 && errno
== EFAULT
)
write (new, zeros
, nwrite
);
"unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d",
ptr
, new, nwrite
, ret
, errno
);
just_done_unexec
= 1; /* Tell toplev not to output ending. */
get_last_nonwhite_on_line ()
/* Is this the last nonwhite stuff on the line? */
c
= nextchar
, nextchar
= -1;
while (c
== ' ' || c
== '\t')
/* At the beginning of a line, increment the line number
and process any #-directive on this line.
If the line is a #-directive, read the entire line and return a newline.
Otherwise, return the line's first non-whitespace character. */
/* Read first nonwhite char on the line. */
while (c
== ' ' || c
== '\t');
/* If not #, return it so caller will use it. */
/* Read first nonwhite char after the `#'. */
while (c
== ' ' || c
== '\t');
/* If a letter follows, then if the word here is `line', skip
it and ignore it; otherwise, ignore the line, with an error
if the word isn't `pragma'. */
if ((c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z'))
/* Change by Bryan Boreham, Kewill, Sun Jul 23 15:53:24 1989.
This whole section added to support dumping of
compilations in the middle. */
/* Read first nonwhite char after the `#pragma'. */
while (c
== ' ' || c
== '\t');
/* See if it is "dump" */
&& ((c
= getch ()) == ' ' || c
== '\t' || c
== '\n'))
&& ((c
= getch ()) == ' ' || c
== '\t' || c
== '\n'))
extern tree pending_vtables
;
/* More follows: it must be a string constant (class name). */
if (token
!= STRING
|| TREE_CODE (yylval
.ttype
) != STRING_CST
)
error ("invalid #pragma vtable");
warning ("use `+e2' option to enable #pragma vtable");
pending_vtables
= perm_tree_cons (NULL_TREE
, get_identifier (TREE_STRING_POINTER (yylval
.ttype
)), pending_vtables
);
warning ("trailing characters ignored");
&& ((c
= getch ()) == ' ' || c
== '\t' || c
== '\n'))
/* More follows: it must be a string constant (unit name). */
if (token
!= STRING
|| TREE_CODE (yylval
.ttype
) != STRING_CST
)
error ("invalid #pragma unit");
current_unit_name
= get_identifier (TREE_STRING_POINTER (yylval
.ttype
));
current_unit_language
= current_lang_name
;
warning ("trailing characters ignored");
tree fileinfo
= IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename
));
&& ((c
= getch ()) == ' ' || c
== '\t' || c
== '\n'))
if (impl_file_chain
== 0)
/* If this is zero at this point, then we are
if (main_input_filename
== 0)
main_input_filename
= input_filename
;
filename
= strrchr (main_input_filename
, '/');
filename
= main_input_filename
;
fi
= get_time_identifier (filename
);
fi
= IDENTIFIER_CLASS_VALUE (fi
);
TREE_INT_CST_LOW (fi
) = 0;
TREE_INT_CST_LOW (fi
) = 0;
impl_file_chain
= (struct impl_files
*)permalloc (sizeof (struct impl_files
));
impl_file_chain
->filename
= filename
;
impl_file_chain
->next
= 0;
interface_only
= interface_strcmp (input_filename
);
TREE_INT_CST_LOW (fileinfo
) = interface_only
;
TREE_INT_CST_HIGH (fileinfo
) = interface_unknown
;
&& ((c
= getch ()) == ' ' || c
== '\t' || c
== '\n'))
char *main_filename
= main_input_filename
? main_input_filename
: input_filename
;
while (c
== ' ' || c
== '\t')
|| TREE_CODE (yylval
.ttype
) != STRING_CST
)
error ("invalid `#pragma implementation'");
main_filename
= TREE_STRING_POINTER (yylval
.ttype
);
tmp
= strrchr (main_filename
, '/');
struct impl_files
*ifiles
= impl_file_chain
;
if (! strcmp (ifiles
->filename
, main_filename
))
ifiles
= (struct impl_files
*) permalloc (sizeof (struct impl_files
));
ifiles
->filename
= main_filename
;
ifiles
->next
= impl_file_chain
;
impl_file_chain
= ifiles
;
else if (main_input_filename
== input_filename
|| ! strcmp (input_filename
, main_filename
))
if (impl_file_chain
== 0)
impl_file_chain
= (struct impl_files
*) permalloc (sizeof (struct impl_files
));
impl_file_chain
->filename
= main_filename
;
impl_file_chain
->next
= 0;
error ("`#pragma implementation' can only appear at top-level");
TREE_INT_CST_LOW (fileinfo
) = interface_only
;
TREE_INT_CST_HIGH (fileinfo
) = interface_unknown
;
&& ((c
= getch ()) == ' ' || c
== '\t'))
&& ((c
= getch ()) == ' ' || c
== '\t'))
/* Conditionally used. */
extern FILE *asm_out_file
;
error ("ANSI C does not allow #ident");
/* Here we have just seen `#ident '.
A string constant should follow. */
while (c
== ' ' || c
== '\t')
/* If no argument, ignore the line. */
|| TREE_CODE (yylval
.ttype
) != STRING_CST
)
error ("invalid #ident");
ASM_OUTPUT_IDENT (asm_out_file
, TREE_STRING_POINTER (yylval
.ttype
));
/* Skip the rest of this line. */
&& ((c
= getch ()) == ' ' || c
== '\t'))
/* Used to test incremental compilation. */
sorry ("#pragma newworld");
error ("undefined or invalid # directive");
/* Here we have either `#line' or `# <nonletter>'.
In either case, it should be a line number; a digit should follow. */
while (c
== ' ' || c
== '\t')
/* If the # is the only nonwhite char on the line,
just ignore it. Check the new newline. */
/* Something follows the #; read a token. */
&& TREE_CODE (yylval
.ttype
) == INTEGER_CST
)
/* subtract one, because it is the following line that
gets the specified number */
int l
= TREE_INT_CST_LOW (yylval
.ttype
) - 1;
c
= get_last_nonwhite_on_line ();
/* No more: store the line number and check following line. */
/* More follows: it must be a string constant (filename). */
if (token
!= STRING
|| TREE_CODE (yylval
.ttype
) != STRING_CST
)
/* Changing files again. This means currently collected time
is charged against header time, and body time starts back
if (flag_detailed_statistics
)
int this_time
= my_gettime ();
tree time_identifier
= get_time_identifier (TREE_STRING_POINTER (yylval
.ttype
));
header_time
+= this_time
- body_time
;
TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time
))
+= this_time
- body_time
;
this_filename_time
= time_identifier
;
= (char *) permalloc (TREE_STRING_LENGTH (yylval
.ttype
) + 1);
strcpy (input_filename
, TREE_STRING_POINTER (yylval
.ttype
));
FIELD_xref_file(input_filename
);
if (main_input_filename
== 0)
extern int been_here_before
;
struct impl_files
*ifiles
= impl_file_chain
;
ifiles
->filename
= (char *)strrchr (input_filename
, '/');
if (ifiles
->filename
++ == 0)
ifiles
->filename
= input_filename
;
main_input_filename
= input_filename
;
walk_vtables (set_typedecl_interface_info
, set_vardecl_interface_info
);
extract_interface_info ();
c
= get_last_nonwhite_on_line ();
cadillac_switch_source (-1);
/* `1' after file name means entering new file.
`2' after file name means just left a file. */
&& TREE_CODE (yylval
.ttype
) == INTEGER_CST
)
if (TREE_INT_CST_LOW (yylval
.ttype
) == 1)
= (struct file_stack
*) xmalloc (sizeof (struct file_stack
));
input_file_stack
->line
= old_lineno
;
p
->next
= input_file_stack
;
p
->name
= input_filename
;
else if (input_file_stack
->next
)
struct file_stack
*p
= input_file_stack
;
input_file_stack
= p
->next
;
error ("#-lines for entering and leaving files don't match");
cadillac_switch_source (-1);
/* If NEXTCHAR is not end of line, we don't care what it is. */
error ("invalid #-line");
/* skip the rest of this line. */
while ((c
= getch ()) != EOF
&& c
!= '\n');
#define isalnum(char) (char >= 'a' ? char <= 'z' : char >= '0' ? char <= '9' || (char >= 'A' && char <= 'Z') : 0)
#define isdigit(char) (char >= '0' && char <= '9')
#define ENDFILE -1 /* token that represents end-of-file */
register int c
= getc (finput
);
register int count
, code
;
if (c
>= 'a' && c
<= 'f')
if (c
>= 'A' && c
<= 'F')
if (c
>= '0' && c
<= '9')
error ("\\x used with no following hex digits");
else if ((count
- 1) * 4 >= TYPE_PRECISION (integer_type_node
)
|| ((1 << (TYPE_PRECISION (integer_type_node
) - (count
- 1) * 4))
warning ("hex escape out of range");
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7':
while ((c
<= '7') && (c
>= '0') && (count
++ < 3))
code
= (code
* 8) + (c
- '0');
case '\\': case '\'': case '"':
/* `\(', etc, are used at beginning of line to avoid confusing Emacs. */
if (c
>= 040 && c
<= 0177)
warning ("unknown escape sequence `\\%c'", c
);
warning ("unknown escape sequence: `\\' followed by char code 0x%x", c
);
/* Value is 1 if we should try to make the next identifier look like a
typename (when it may be a local variable or a class variable).
Value is 0 if we treat this name in a default fashion.
Value is -1 if we must not see a type name. */
int looking_for_typename
= 0;
looking_for_typename
= -1;
looking_for_typename
= 0;
if (yychar
== IDENTIFIER
)
lastiddecl
= lookup_name (yylval
.ttype
);
if (lastiddecl
== 0 && flag_labels_ok
)
lastiddecl
= IDENTIFIER_LABEL_VALUE (yylval
.ttype
);
&& TREE_CODE (lastiddecl
) == TYPE_DECL
)
tree
do_identifier (token
)
register tree id
= lastiddecl
;
/* Scope class declarations before global
if (id
== IDENTIFIER_GLOBAL_VALUE (token
)
&& current_class_type
!= 0
&& TYPE_SIZE (current_class_type
) == 0)
/* Could be from one of the base classes. */
tree field
= lookup_field (current_class_type
, token
, 1);
else if (field
== error_mark_node
)
/* We have already generated the error message.
But we still want to return this value. */
id
= lookup_field (current_class_type
, token
, 0);
else if (TREE_CODE (field
) == VAR_DECL
|| TREE_CODE (field
) == CONST_DECL
)
else if (TREE_CODE (field
) != FIELD_DECL
)
error_with_decl (field
, "invalid use of member `%s' from base class `%s'",
TYPE_NAME_STRING (DECL_FIELD_CONTEXT (field
)));
if (!id
|| id
== error_mark_node
)
if (yychar
== '(' || yychar
== LEFT_RIGHT
)
id
= implicitly_declare (token
);
else if (current_function_decl
== 0)
error ("`%s' undeclared, outside of functions",
IDENTIFIER_POINTER (token
));
if (IDENTIFIER_GLOBAL_VALUE (token
) != error_mark_node
|| IDENTIFIER_ERROR_LOCUS (token
) != current_function_decl
)
extern int undeclared_variable_notice
;
error ("`%s' undeclared (first use this function)",
IDENTIFIER_POINTER (token
));
if (! undeclared_variable_notice
)
error ("(Each undeclared identifier is reported only once");
error ("for each function it appears in.)");
undeclared_variable_notice
= 1;
/* Prevent repeated error messages. */
IDENTIFIER_GLOBAL_VALUE (token
) = error_mark_node
;
SET_IDENTIFIER_ERROR_LOCUS (token
, current_function_decl
);
/* TREE_USED is set in `hack_identifier'. */
if (TREE_CODE (id
) == CONST_DECL
)
if (IDENTIFIER_CLASS_VALUE (token
) == id
)
enum visibility_type visibility
= compute_visibility (CLASSTYPE_AS_LIST (current_class_type
), id
);
if (visibility
== visibility_private
)
error_with_decl (id
, "enum `%s' is private");
/* protected is OK, since it's an enum of `this'. */
else id
= hack_identifier (id
, token
, yychar
);
lastiddecl
= nextlastiddecl
;
goto resume_identifier_processing
;
c
= nextchar
, nextchar
= -1;
/* Effectively do c = skip_white_space (c)
but do it faster in the usual cases. */
c
= skip_white_space (c
);
/* yylloc.first_line = lineno; */
struct pending_inline
*t
;
#ifdef DO_METHODS_THE_OLD_WAY
yylval
.itype
= t
->token_value
;
yylval
.itype
= t
->token_value
;
yylval
.ttype
= t
->fndecl
;
value
= PRE_PARSED_FUNCTION_DECL
;
/* yylloc.first_line = lineno; */
input_filename
= t
->filename
;
/* The buffer we used will be freed at the
pending_inlines
= pending_inlines
->next
;
setvbuf (finput2
, t
->buf
, _IOFBF
, t
->len
- 1);
next_inline_count
= t
->len
- 1;
obstack_free (&inline_text_obstack
, inline_text_firstobj
);
/* The space used by T will be freed after all inline
functions have been processed. */
/* Capital L may start a wide-string or wide-character constant. */
register int c
= getch ();
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'M': case 'N': case 'O':
case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y':
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y':
while (isalnum(c
) || (c
== '_') || c
== '$')
if (p
>= token_buffer
+ maxtoken
)
p
= extend_token_buffer (p
);
if (c
== '$' && ! dollars_in_ident
)
/* Try to recognize a keyword. Uses minimum-perfect hash function */
register struct resword
*ptr
;
if (ptr
= is_reserved_word (token_buffer
, p
- token_buffer
))
if (current_lang_name
!= lang_name_cplusplus
)
&& (ptr
->rid
== RID_CLASS
|| ptr
->rid
== RID_FRIEND
|| ptr
->rid
== RID_VIRTUAL
|| (flag_no_asm
&& ptr
->rid
== RID_INLINE
)))
goto not_reserved_word_after_all
;
&& ((int) ptr
->token
== TYPEOF
|| ptr
->rid
== RID_SIGNED
|| ptr
->rid
== RID_INLINE
))
goto not_reserved_word_after_all
;
tree old_ttype
= ridpointers
[(int) ptr
->rid
];
/* If this provides a type for us, then revert lexical
state to standard state. */
if (TREE_CODE (old_ttype
) == IDENTIFIER_NODE
&& IDENTIFIER_GLOBAL_VALUE (old_ttype
) != 0
&& TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype
)) == TYPE_DECL
)
looking_for_typename
= 0;
/* Check if this is a language-type declaration.
Just glimpse the next non-white character. */
nextchar
= skip_white_space (nextchar
);
/* We are looking at a string. Complain
if the token before the string is no `extern'.
Could cheat some memory by placing this string
on the temporary_, instead of the saveable_
if (ptr
->rid
!= RID_EXTERN
)
error ("invalid modifier `%s' for language string",
value
= EXTERN_LANG_STRING
;
yylval
.ttype
= get_identifier (TREE_STRING_POINTER (yylval
.ttype
));
yylval
.ttype
= old_ttype
;
value
= (int) ptr
->token
;
not_reserved_word_after_all
:
/* If we did not find a keyword, look for an identifier
if (value
== IDENTIFIER
|| value
== TYPESPEC
)
FIELD_xref_ref(current_function_decl
,token_buffer
);
tmp
= get_identifier (token_buffer
);
/* Make sure that user does not collide with our internal
|| DESTRUCTOR_NAME_P (tmp
)
|| WRAPPER_OR_ANTI_WRAPPER_NAME_P (tmp
)
|| OPERATOR_TYPENAME_P (tmp
)
|| ANON_PARMNAME_P (tmp
)))
warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
/* Come into here if we must reprocess an identifier. */
resume_identifier_processing
:
if (looking_for_typename
== 1
lastiddecl
= TREE_TYPE (tmp
);
else lastiddecl
= lookup_name (tmp
);
if (lastiddecl
&& TREE_CODE (lastiddecl
) == TYPE_DECL
&& looking_for_typename
>= 0)
/* This call could blow away yylval. */
c
= skip_white_space (nextchar
);
&& current_function_decl
== NULL_TREE
&& current_class_type
== NULL_TREE
)
error ("missing '.' in `...'");
value
= TYPENAME_ELLIPSIS
;
tmp
= build_tree_list (NULL_TREE
, build_tree_list (TREE_TYPE (lastiddecl
), NULL_TREE
));
warning ("use of obsolete scope operator `.'; use `::' instead");
looking_for_typename
= 0;
if (looking_for_typename
== 1)
looking_for_typename
= 0;
yylval
.ttype
= TREE_TYPE (lastiddecl
);
else if (lastiddecl
== 0 && flag_labels_ok
)
lastiddecl
= IDENTIFIER_LABEL_VALUE (tmp
);
if (value
== NEW
&& ! global_bindings_p ())
looking_for_typename
= 1;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
/* for multi-precision arithmetic,
we store only 8 live bits in each short,
giving us 64 bits of reliable precision */
enum anon1
{ NOT_FLOAT
, AFTER_POINT
, TOO_MANY_POINTS
} floatflag
/* Optimize for most frequent case. */
if (c
== '0' || c
== '1')
register int c1
= getch ();
if (! isalnum (c1
) && c1
!= '.')
yylval
.ttype
= integer_zero_node
;
yylval
.ttype
= integer_one_node
;
for (count
= 0; count
< 8; count
++)
if ((c
== 'x') || (c
== 'X'))
/* Read all the digits-and-decimal-points. */
|| (isalnum (c
) && (c
!= 'l') && (c
!= 'L')
&& (c
!= 'u') && (c
!= 'U')
&& (floatflag
== NOT_FLOAT
|| ((c
!= 'f') && (c
!= 'F')))))
error ("floating constant may not be in radix 16");
if (floatflag
== AFTER_POINT
)
error ("malformed floating constant");
floatflag
= TOO_MANY_POINTS
;
/* Accept '.' as the start of a floating-point number
only when it is followed by a digit.
Otherwise, unread the following non-digit
and use the '.' as a structural token. */
if (p
== token_buffer
+ 2 && !isdigit (c
))
/* It is not a decimal point.
It should be a digit (perhaps a hex digit). */
break; /* start of exponent */
error ("nondigits in number and not hexadecimal");
for (count
= 0; count
< 8; count
++)
shorts
[count
] += (shorts
[count
-1] >> 8);
shorts
[count
-1] &= (1<<8)-1;
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
error ("numeric constant with no digits");
if (largest_digit
>= base
)
error ("numeric constant contains digits beyond the radix");
/* Remove terminating char from the token buffer and delimit the string */
if (floatflag
!= NOT_FLOAT
)
tree type
= double_type_node
;
/* Read explicit exponent if any, and put it in tokenbuf. */
if ((c
== 'e') || (c
== 'E'))
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
if ((c
== '+') || (c
== '-'))
error ("floating constant exponent has no digits");
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
value
= atof (token_buffer
);
if (errno
== ERANGE
&& !flag_traditional
)
/* Check for "0.0" and variants;
Sunos 4 spuriously returns ERANGE for them. */
warning ("floating point number exceeds range of `double'");
/* Read the suffixes to choose a data type. */
if (c
== 'f' || c
== 'F')
error ("two `f's in floating constant");
else if (c
== 'l' || c
== 'L')
error ("two `l's in floating constant");
type
= long_double_type_node
;
error ("garbage at end of number");
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
/* Create a node with determined type and value. */
yylval
.ttype
= build_real (type
, value
);
if (c
== 'u' || c
== 'U')
error ("two `u's in integer constant");
else if (c
== 'l' || c
== 'L')
error ("two `l's in integer constant");
error ("garbage at end of number");
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
if (p
>= token_buffer
+ maxtoken
- 3)
p
= extend_token_buffer (p
);
if (shorts
[7] | shorts
[6] | shorts
[5] | shorts
[4])
warning ("integer constant out of range");
/* This is simplified by the fact that our constant
= build_int_2 ((shorts
[3]<<24) + (shorts
[2]<<16) + (shorts
[1]<<8) + shorts
[0],
if (!spec_long
&& !spec_unsigned
&& int_fits_type_p (yylval
.ttype
, integer_type_node
))
type
= integer_type_node
;
else if (!spec_long
&& base
!= 10
&& int_fits_type_p (yylval
.ttype
, unsigned_type_node
))
type
= unsigned_type_node
;
&& int_fits_type_p (yylval
.ttype
, long_integer_type_node
))
type
= long_integer_type_node
;
type
= long_unsigned_type_node
;
if (! int_fits_type_p (yylval
.ttype
, long_unsigned_type_node
))
warning ("integer constant out of range");
TREE_TYPE (yylval
.ttype
) = type
;
int width
= TYPE_PRECISION (char_type_node
);
if (wide_flag
) width
= TYPE_PRECISION (integer_type_node
);
max_chars
= TYPE_PRECISION (integer_type_node
) / width
;
if (c
== '\'' || c
== EOF
)
if (width
< HOST_BITS_PER_INT
&& (unsigned) c
>= (1 << width
))
warning ("escape sequence out of range for character");
warning ("ANSI C forbids newline in character constant");
if (num_chars
> maxtoken
- 4)
extend_token_buffer (token_buffer
);
token_buffer
[num_chars
] = c
;
/* Merge character into result; ignore excess chars. */
if (num_chars
< max_chars
+ 1)
if (width
< HOST_BITS_PER_INT
)
result
= (result
<< width
) | (c
& ((1 << width
) - 1));
token_buffer
[num_chars
+ 1] = '\'';
token_buffer
[num_chars
+ 2] = 0;
error ("malformatted character constant");
error ("empty character constant");
else if (num_chars
> max_chars
)
error ("character constant too long");
else if (num_chars
!= 1 && ! flag_traditional
)
warning ("multi-character character constant");
/* If char type is signed, sign-extend the constant. */
int num_bits
= num_chars
* width
;
if (TREE_UNSIGNED (char_type_node
)
|| ((result
>> (num_bits
- 1)) & 1) == 0)
= build_int_2 (result
& ((unsigned) ~0
>> (HOST_BITS_PER_INT
- num_bits
)),
= build_int_2 (result
| ~((unsigned) ~0
>> (HOST_BITS_PER_INT
- num_bits
)),
TREE_TYPE (yylval
.ttype
) = char_type_node
;
yylval
.ttype
= build_int_2 (result
, 0);
TREE_TYPE (yylval
.ttype
) = integer_type_node
;
while (c
!= '"' && c
>= 0)
if (!wide_flag
&& c
>= (1 << BITS_PER_UNIT
))
warning ("escape sequence out of range for character");
warning ("ANSI C forbids newline in string constant");
/* Store the char in C into the appropriate buffer. */
if (widep
== wide_buffer
+ max_wide
)
int n
= widep
- wide_buffer
;
wide_buffer
= (int *) xrealloc (wide_buffer
, max_wide
+ 1);
if (p
== token_buffer
+ maxtoken
)
p
= extend_token_buffer (p
);
error("Unterminated string");
/* We have read the entire constant.
Construct a STRING_CST for the result. */
/* If this is a L"..." wide-string, make a vector
of the ints in wide_buffer. */
/* We have not implemented the case where `int'
on the target and on the execution machine differ in size. */
assert (TYPE_PRECISION (integer_type_node
) == sizeof (int) * BITS_PER_UNIT
);
yylval
.ttype
= build_string ((widep
- wide_buffer
) * sizeof (int),
TREE_TYPE (yylval
.ttype
) = int_array_type_node
;
yylval
.ttype
= build_string (p
- token_buffer
, token_buffer
+ 1);
TREE_TYPE (yylval
.ttype
) = char_array_type_node
;
yylval
.code
= PLUS_EXPR
; break;
yylval
.code
= MINUS_EXPR
; break;
yylval
.code
= BIT_AND_EXPR
; break;
yylval
.code
= BIT_IOR_EXPR
; break;
yylval
.code
= MULT_EXPR
; break;
yylval
.code
= TRUNC_DIV_EXPR
; break;
yylval
.code
= TRUNC_MOD_EXPR
; break;
yylval
.code
= BIT_XOR_EXPR
; break;
yylval
.code
= LSHIFT_EXPR
; break;
yylval
.code
= RSHIFT_EXPR
; break;
yylval
.code
= LT_EXPR
; break;
yylval
.code
= GT_EXPR
; break;
token_buffer
[1] = c1
= getch ();
value
= ARITHCOMPARE
; yylval
.code
= LE_EXPR
; goto done
;
value
= ARITHCOMPARE
; yylval
.code
= GE_EXPR
; goto done
;
value
= EQCOMPARE
; yylval
.code
= NE_EXPR
; goto done
;
value
= EQCOMPARE
; yylval
.code
= EQ_EXPR
; goto done
;
value
= ASSIGN
; goto done
;
value
= PLUSPLUS
; goto done
;
value
= MINUSMINUS
; goto done
;
value
= ANDAND
; goto done
;
else if ((c
== '-') && (c1
== '>'))
nextchar
= skip_white_space (getch ());
int next_c
= skip_white_space (getch ());
value
= POINTSAT_LEFT_RIGHT
;
else if (c1
== '?' && (c
== '<' || c
== '>'))
yylval
.code
= (c
== '<' ? MIN_EXPR
: MAX_EXPR
);
/* <?= or >?= expression. */
error ("use of `operator %s' is not standard C++",
if ((c
== '<') || (c
== '>'))
/* Don't make yyparse think this is eof. */
/* try, weakly, to handle casts to pointers to functions. */
nextchar
= skip_white_space (getch ());
int next_c
= skip_white_space (getch ());
yylval
.ttype
= build1 (INDIRECT_REF
, 0, 0);
value
= PAREN_STAR_PAREN
;
/* Go down for a (X::*) or (X::&). */
else if (isalpha (nextchar
) || nextchar
== '_' || nextchar
== '$')
YYSTYPE this_yylval
= yylval
;
tree this_lastiddecl
= lastiddecl
;
if (nextyychar
== TYPENAME_SCOPE
)
nextchar
= skip_white_space (getch ());
if (nextchar
== '*' || nextchar
== '&')
int next_c
= skip_white_space (getch ());
value
= PAREN_X_SCOPE_STAR_PAREN
;
yylval
.ttype
= build_parse_node (SCOPE_REF
, yylval
.ttype
,
build_parse_node (INDIRECT_REF
, 0));
value
= PAREN_X_SCOPE_REF_PAREN
;
yylval
.ttype
= build_parse_node (SCOPE_REF
, yylval
.ttype
,
build_parse_node (ADDR_EXPR
, 0));
nextlastiddecl
= lastiddecl
;
lastiddecl
= this_lastiddecl
;
nextlastiddecl
= lastiddecl
;
lastiddecl
= this_lastiddecl
;
nextlastiddecl
= lastiddecl
;
lastiddecl
= this_lastiddecl
;
else if (nextchar
== ')')
yylval
.ttype
= NULL_TREE
;
/* yylloc.last_line = lineno; */
d_kind
, t_kind
, s_kind
, r_kind
, e_kind
, c_kind
,
id_kind
, op_id_kind
, perm_list_kind
, temp_list_kind
,
x_kind
, lang_decl
, lang_type
, all_kinds
extern int tree_node_kinds
[];
extern int tree_node_sizes
[];
extern char *tree_node_kind_names
[];
/* Place to save freed lang_decls which were allocated on the
permanent_obstack. @@ Not currently used. */
tree free_lang_decl_chain
;
build_lang_decl (code
, name
, type
)
extern struct obstack
*current_obstack
, *saveable_obstack
;
extern struct obstack permanent_obstack
;
register tree t
= build_decl (code
, name
, type
);
struct obstack
*obstack
= current_obstack
;
register int i
= sizeof (struct lang_decl
) / sizeof (int);
if (! TREE_PERMANENT (t
))
obstack
= saveable_obstack
;
#ifdef LANG_DECL_PERMANENT
if (free_lang_decl_chain
&& obstack
== &permanent_obstack
)
pi
= (int *)free_lang_decl_chain
;
free_lang_decl_chain
= TREE_CHAIN (free_lang_decl_chain
);
pi
= (int *) obstack_alloc (obstack
, sizeof (struct lang_decl
));
pi
= (int *) obstack_alloc (obstack
, sizeof (struct lang_decl
));
DECL_LANG_SPECIFIC (t
) = (struct lang_decl
*) pi
;
#ifdef LANG_DECL_PERMANENT
LANG_DECL_PERMANENT ((struct lang_decl
*) pi
)
= obstack
== &permanent_obstack
;
DECL_MAIN_VARIANT (t
) = t
;
DECL_ORIGINAL_NAME (t
) = name
;
if (current_lang_name
== lang_name_cplusplus
)
DECL_LANGUAGE (t
) = lang_cplusplus
;
if (code
== FUNCTION_DECL
&& name
!= 0
&& ! (IDENTIFIER_LENGTH (name
) == 4
&& IDENTIFIER_POINTER (name
)[0] == 'm'
&& strcmp (IDENTIFIER_POINTER (name
), "main") == 0)
&& ! (IDENTIFIER_LENGTH (name
) > 10
&& IDENTIFIER_POINTER (name
)[0] == '_'
&& IDENTIFIER_POINTER (name
)[1] == '_'
&& strncmp (IDENTIFIER_POINTER (name
)+2, "builtin_", 8) == 0))
TREE_OVERLOADED (name
) = 1;
else if (current_lang_name
== lang_name_c
)
DECL_LANGUAGE (t
) = lang_c
;
tree_node_kinds
[(int)lang_decl
] += 1;
tree_node_sizes
[(int)lang_decl
] += sizeof(struct lang_decl
);
build_lang_field_decl (code
, name
, type
)
extern struct obstack
*current_obstack
, *saveable_obstack
;
register tree t
= build_decl (code
, name
, type
);
struct obstack
*obstack
= current_obstack
;
register int i
= sizeof (struct lang_decl_flags
) / sizeof (int);
if (! TREE_PERMANENT (t
))
obstack
= saveable_obstack
;
pi
= (int *) obstack_alloc (obstack
, sizeof (struct lang_decl_flags
));
DECL_LANG_SPECIFIC (t
) = (struct lang_decl
*) pi
;
extern struct obstack
*current_obstack
, *saveable_obstack
;
register tree t
= make_node (code
);
struct obstack
*obstack
= current_obstack
;
register int i
= sizeof (struct lang_type
) / sizeof (int);
if (! TREE_PERMANENT (t
))
obstack
= saveable_obstack
;
pi
= (int *) obstack_alloc (obstack
, sizeof (struct lang_type
));
TYPE_LANG_SPECIFIC (t
) = (struct lang_type
*) pi
;
CLASSTYPE_MAIN_VARIANT (t
) = t
;
CLASSTYPE_AS_LIST (t
) = build_tree_list (NULL_TREE
, t
);
CLASSTYPE_INTERFACE_UNKNOWN (t
) = interface_unknown
;
CLASSTYPE_INTERFACE_ONLY (t
) = interface_only
;
/* Make sure this is laid out, for ease of use later.
In the presence of parse errors, the normal was of assuring
this might not ever get executed, so we lay it out *immediately*. */
tree_node_kinds
[(int)lang_type
] += 1;
tree_node_sizes
[(int)lang_type
] += sizeof(struct lang_type
);
copy_decl_lang_specific (decl
)
extern struct obstack
*current_obstack
, *saveable_obstack
;
register int *old
= (int *)DECL_LANG_SPECIFIC (decl
);
struct obstack
*obstack
= current_obstack
;
register int i
= sizeof (struct lang_decl
) / sizeof (int);
if (! TREE_PERMANENT (decl
))
obstack
= saveable_obstack
;
pi
= (int *) obstack_alloc (obstack
, sizeof (struct lang_decl
));
DECL_LANG_SPECIFIC (decl
) = (struct lang_decl
*) pi
;
tree_node_kinds
[(int)lang_decl
] += 1;
tree_node_sizes
[(int)lang_decl
] += sizeof(struct lang_decl
);
copy_type_lang_specific (type
)
extern struct obstack
*current_obstack
, *saveable_obstack
;
register int *old
= (int *)TYPE_LANG_SPECIFIC (type
);
struct obstack
*obstack
= current_obstack
;
register int i
= sizeof (struct lang_type
) / sizeof (int);
if (! TREE_PERMANENT (type
))
obstack
= saveable_obstack
;
pi
= (int *) obstack_alloc (obstack
, sizeof (struct lang_type
));
TYPE_LANG_SPECIFIC (type
) = (struct lang_type
*) pi
;
CLASSTYPE_AS_LIST (type
) = build_tree_list (NULL_TREE
, type
);
if (CLASSTYPE_N_BASECLASSES (type
) > 0)
CLASSTYPE_BASECLASSES (type
) = (tree
*)obstack_copy (obstack
, CLASSTYPE_BASECLASSES (type
), (CLASSTYPE_N_BASECLASSES (type
)+1) * sizeof (tree
));
tree_node_kinds
[(int)lang_type
] += 1;
tree_node_sizes
[(int)lang_type
] += sizeof(struct lang_type
);
build_with_cleanup (exp
, type
, rtl
)
if (type
!= NULL_TREE
|| TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (exp
)))
tree rval
= make_node (WITH_CLEANUP_EXPR
);
TREE_OPERAND (rval
, 0) = exp
;
TREE_OPERAND (rval
, 1) = make_node (RTL_EXPR
);
TREE_OPERAND (rval
, 2) = build_delete (TYPE_POINTER_TO (type
),
build1 (ADDR_EXPR
, TYPE_POINTER_TO (type
), TREE_OPERAND (rval
, 1)),
integer_two_node
, LOOKUP_NORMAL
, 0);
RTL_EXPR_RTL (TREE_OPERAND (rval
, 1)) = rtl
;
if (TREE_CODE (exp
) == CALL_EXPR
&& TREE_VALUE (TREE_OPERAND (exp
, 1)) == NULL_TREE
)
TREE_VALUE (TREE_OPERAND (exp
, 1)) = TREE_OPERAND (rval
, 1);
register tree prev
= 0, decl
, next
;
int this_time
= my_gettime ();
TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time
))
+= this_time
- body_time
;
fprintf (stderr
, "\n******\n");
print_time ("header files (total)", header_time
);
print_time ("main file (total)", this_time
- body_time
);
fprintf (stderr
, "ratio = %g : 1\n",
(double)header_time
/ (double)(this_time
- body_time
));
fprintf (stderr
, "\n******\n");
for (decl
= filename_times
; decl
; decl
= next
)
next
= IDENTIFIER_GLOBAL_VALUE (decl
);
IDENTIFIER_GLOBAL_VALUE (decl
) = prev
;
for (decl
= prev
; decl
; decl
= IDENTIFIER_GLOBAL_VALUE (decl
))
print_time (IDENTIFIER_POINTER (decl
),
TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl
)));
compiler_error (s
, v
, v2
)
int v
, v2
; /* @@also used as pointer */
error_with_file_and_line (input_filename
, lineno
, "%s (compiler error)", buf
);
compiler_error_with_decl (decl
, s
)
report_error_function (0);
if (TREE_CODE (decl
) == PARM_DECL
)
fprintf (stderr
, "%s:%d: ",
DECL_SOURCE_FILE (DECL_CONTEXT (decl
)),
DECL_SOURCE_LINE (DECL_CONTEXT (decl
)));
fprintf (stderr
, "%s:%d: ",
DECL_SOURCE_FILE (decl
), DECL_SOURCE_LINE (decl
));
name
= lang_printable_name (decl
);
fprintf (stderr
, s
, name
);
fprintf (stderr
, s
, "((anonymous))");
fprintf (stderr
, " (compiler error)\n");