#include "config.h"
#include "system.h"
#include "input.h"
#include "tree.h"
#include "lex.h"
#include "cp-tree.h"
#include "parse.h"
#include "flags.h"
#include "obstack.h"
#include "toplev.h"
struct token {
short yychar;
short end_of_file;
YYSTYPE yylval;
};
static int do_aggr PROTO((void));
static int probe_obstack PROTO((struct obstack *, tree, unsigned int));
static void scan_tokens PROTO((unsigned int));
#ifdef SPEW_DEBUG
static int num_tokens PROTO((void));
static struct token *nth_token PROTO((int));
static void add_token PROTO((struct token *));
static void consume_token PROTO((void));
static int debug_yychar PROTO((int));
#endif
extern tree lastiddecl;
extern int yychar;
extern YYSTYPE yylval;
extern int end_of_file;
struct obstack token_obstack;
int first_token;
#ifdef SPEW_DEBUG
int spew_debug = 0;
static unsigned int yylex_ctr = 0;
static int debug_yychar ();
#endif
void
init_spew ()
{
gcc_obstack_init (&token_obstack);
}
#ifdef SPEW_DEBUG
static int
num_tokens ()
{
return (obstack_object_size (&token_obstack) / sizeof (struct token))
- first_token;
}
static struct token*
nth_token (n)
int n;
{
my_friendly_assert (n < num_tokens (), 298);
return ((struct token*)obstack_base (&token_obstack)) + n + first_token;
}
static void
add_token (t)
struct token* t;
{
obstack_grow (&token_obstack, t, sizeof (struct token));
}
static void
consume_token ()
{
if (num_tokens () == 1)
{
obstack_free (&token_obstack, obstack_base (&token_obstack));
first_token = 0;
}
else
first_token++;
}
#else
#define num_tokens() \
((obstack_object_size (&token_obstack) / sizeof (struct token)) - first_token)
#define nth_token(N) \
(((struct token*)obstack_base (&token_obstack))+(N)+first_token)
#define add_token(T) obstack_grow (&token_obstack, (T), sizeof (struct token))
#define consume_token() \
(num_tokens () == 1 \
? (obstack_free (&token_obstack, obstack_base (&token_obstack)), \
(first_token = 0)) \
: first_token++)
#endif
static void
scan_tokens (n)
unsigned int n;
{
unsigned int i;
struct token *tmp;
i = num_tokens ();
if (i > n)
return;
while (i-- > 0)
{
tmp = nth_token (i);
if (tmp->yychar == '{' || tmp->yychar == ':' || tmp->yychar == ';')
goto pad_tokens;
}
while (num_tokens () <= n)
{
obstack_blank (&token_obstack, sizeof (struct token));
tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
tmp->yychar = real_yylex ();
tmp->end_of_file = end_of_file;
tmp->yylval = yylval;
end_of_file = 0;
if (tmp->yychar == '{'
|| tmp->yychar == ':'
|| tmp->yychar == ';')
{
pad_tokens:
while (num_tokens () <= n)
{
obstack_blank (&token_obstack, sizeof (struct token));
tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
tmp->yychar = EMPTY;
tmp->end_of_file = 0;
}
}
}
}
static int
probe_obstack (h, obj, nlevels)
struct obstack *h;
tree obj;
unsigned int nlevels;
{
register struct _obstack_chunk* lp;
register struct _obstack_chunk* plp;
lp = (h)->chunk;
for (; nlevels != 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);
nlevels -= 1)
{
plp = lp->prev;
lp = plp;
}
return nlevels != 0 && lp != 0;
}
extern int looking_for_typename;
int looking_for_template;
extern int do_snarf_defarg;
extern struct obstack *current_obstack, *saveable_obstack;
tree got_scope;
tree got_object;
int
peekyylex ()
{
scan_tokens (0);
return nth_token (0)->yychar;
}
int
yylex ()
{
struct token tmp_token;
tree trrr = NULL_TREE;
int old_looking_for_typename = 0;
retry:
#ifdef SPEW_DEBUG
if (spew_debug)
{
yylex_ctr ++;
fprintf (stderr, "\t\t## %d ##", yylex_ctr);
}
#endif
if (do_snarf_defarg)
{
my_friendly_assert (num_tokens () == 0, 2837);
tmp_token.yychar = DEFARG;
tmp_token.yylval.ttype = snarf_defarg ();
tmp_token.end_of_file = 0;
do_snarf_defarg = 0;
add_token (&tmp_token);
}
else if (num_tokens ())
{
tmp_token= *nth_token (0);
if ((tmp_token.yychar == CONSTANT
|| tmp_token.yychar == STRING)
&& ! TREE_PERMANENT (tmp_token.yylval.ttype)
&& ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2)
&& ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2))
tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype);
}
else
{
tmp_token.yychar = real_yylex ();
tmp_token.yylval = yylval;
tmp_token.end_of_file = end_of_file;
add_token (&tmp_token);
}
switch (tmp_token.yychar)
{
case EMPTY:
consume_token ();
#ifdef SPEW_DEBUG
if (spew_debug)
debug_yychar (tmp_token.yychar);
#endif
goto retry;
case IDENTIFIER:
scan_tokens (1);
if (nth_token (1)->yychar == SCOPE)
{
old_looking_for_typename = looking_for_typename;
looking_for_typename = 1;
}
else if (nth_token (1)->yychar == '<')
looking_for_template = 1;
trrr = lookup_name (tmp_token.yylval.ttype, -2);
if (trrr)
{
tmp_token.yychar = identifier_type (trrr);
switch (tmp_token.yychar)
{
case TYPENAME:
case SELFNAME:
case NSNAME:
case PTYPENAME:
lastiddecl = trrr;
if (got_scope || got_object)
tmp_token.yylval.ttype = trrr;
break;
case PFUNCNAME:
case IDENTIFIER:
lastiddecl = trrr;
break;
default:
my_friendly_abort (101);
}
}
else
lastiddecl = NULL_TREE;
got_scope = NULL_TREE;
case IDENTIFIER_DEFN:
case TYPENAME:
case TYPENAME_DEFN:
case PTYPENAME:
case PTYPENAME_DEFN:
consume_token ();
looking_for_typename = old_looking_for_typename;
looking_for_template = 0;
break;
case SCSPEC:
if (tmp_token.yylval.ttype == get_identifier("export"))
{
warning ("keyword 'export' not implemented and will be ignored");
consume_token ();
goto retry;
}
else
{
++first_token;
break;
}
case NEW:
++first_token;
break;
case TYPESPEC:
consume_token ();
break;
case AGGR:
*nth_token (0) = tmp_token;
do_aggr ();
case ENUM:
looking_for_typename = 2;
default:
consume_token ();
}
if (tmp_token.yychar != '~')
got_object = NULL_TREE;
if (tmp_token.yychar == '{' || tmp_token.yychar == ':'
|| tmp_token.yychar == ';')
looking_for_typename = 0;
yylval = tmp_token.yylval;
yychar = tmp_token.yychar;
end_of_file = tmp_token.end_of_file;
#ifdef SPEW_DEBUG
if (spew_debug)
debug_yychar (yychar);
#endif
return yychar;
}
static int
do_aggr ()
{
int yc1, yc2;
scan_tokens (2);
yc1 = nth_token (1)->yychar;
if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
return 0;
yc2 = nth_token (2)->yychar;
if (yc2 == ';')
{
if (first_token > 0)
{
if (nth_token (-1)->yychar == SCSPEC
&& nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
return 0;
if (nth_token (-1)->yychar == NEW)
return 0;
}
}
else if (yc2 != '{' && yc2 != ':')
return 0;
switch (yc1)
{
case TYPENAME:
nth_token (1)->yychar = TYPENAME_DEFN;
break;
case PTYPENAME:
nth_token (1)->yychar = PTYPENAME_DEFN;
break;
case IDENTIFIER:
nth_token (1)->yychar = IDENTIFIER_DEFN;
break;
default:
my_friendly_abort (102);
}
return 0;
}
#ifdef SPEW_DEBUG
static int
debug_yychar (yy)
int yy;
{
extern char *debug_yytranslate ();
int i;
if (yy<256) {
fprintf (stderr, "<%d: %c >\n", yy, yy);
return 0;
}
fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy));
return 1;
}
#endif
#ifdef OBJCPLUS
void
forget_saved_protocol_qualifiers ()
{
int i;
struct token *tmp;
i = num_tokens ();
while (i-- > 0)
{
tmp = nth_token (i);
if (tmp->yychar == TYPE_QUAL
&& TREE_CODE (tmp->yylval.ttype) == IDENTIFIER_NODE)
{
char *name = IDENTIFIER_POINTER (tmp->yylval.ttype);
if (strcmp (name, "in") == 0
|| strcmp (name, "out") == 0
|| strcmp (name, "inout") == 0
|| strcmp (name, "bycopy") == 0
|| strcmp (name, "byref") == 0
|| strcmp (name, "oneway") == 0)
tmp->yychar = IDENTIFIER;
}
}
}
#endif