#include "config.h"
#include "system.h"
#include "varray.h"
#include "cpplib.h"
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
#include "toplev.h"
#include "hashtab.h"
#include "c-common.h"
#include "c-pragma.h"
#include "lex.h"
#include "real.h"
#include "jet.h"
#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
typedef struct jet_token GTY (())
{
ENUM_BITFIELD (cpp_ttype) type : 8;
ENUM_BITFIELD (cpp_ttype) cp_type : 8;
ENUM_BITFIELD (rid) keyword : 8;
bool is_use : 1;
bool is_decl : 1;
bool dont_emit : 1;
bool in_system_header : 1;
tree value;
location_t location;
int pending_lang_change;
} jet_token;
static unsigned long n_tokens_allocated = 0;
static unsigned long n_tokens_used = 0;
static GTY((length ("n_tokens_allocated"))) jet_token *token_array = 0;
static void
token_array_expand (void)
{
n_tokens_allocated = 3 * n_tokens_allocated / 2;
token_array = ggc_realloc (token_array,
n_tokens_allocated * sizeof (jet_token));
memset (token_array + n_tokens_used,
0,
(n_tokens_allocated - n_tokens_used) * sizeof(jet_token));
}
static void
debug_print_token (FILE * stream, jet_token* token)
{
const char *token_type = NULL;
#define HANDLE_TOKEN_TYPE(TT) case CPP_ ## TT : token_type = #TT ; break
#define HANDLE_TOKEN_TYPE2(TT,NAME) case CPP_ ## TT : token_type = NAME ; break
switch (token->cp_type)
{
HANDLE_TOKEN_TYPE(EQ);
HANDLE_TOKEN_TYPE(NOT);
HANDLE_TOKEN_TYPE(GREATER);
HANDLE_TOKEN_TYPE(LESS);
HANDLE_TOKEN_TYPE(PLUS);
HANDLE_TOKEN_TYPE(MINUS);
HANDLE_TOKEN_TYPE(MULT);
HANDLE_TOKEN_TYPE(DIV);
HANDLE_TOKEN_TYPE(MOD);
HANDLE_TOKEN_TYPE(AND);
HANDLE_TOKEN_TYPE(OR);
HANDLE_TOKEN_TYPE(XOR);
HANDLE_TOKEN_TYPE(RSHIFT);
HANDLE_TOKEN_TYPE(LSHIFT);
HANDLE_TOKEN_TYPE(MIN);
HANDLE_TOKEN_TYPE(MAX);
HANDLE_TOKEN_TYPE(COMPL);
HANDLE_TOKEN_TYPE(AND_AND);
HANDLE_TOKEN_TYPE(OR_OR);
HANDLE_TOKEN_TYPE(QUERY);
HANDLE_TOKEN_TYPE(COLON);
HANDLE_TOKEN_TYPE(COMMA);
HANDLE_TOKEN_TYPE(OPEN_PAREN);
HANDLE_TOKEN_TYPE(CLOSE_PAREN);
HANDLE_TOKEN_TYPE(EOF);
HANDLE_TOKEN_TYPE(EQ_EQ);
HANDLE_TOKEN_TYPE(NOT_EQ);
HANDLE_TOKEN_TYPE(GREATER_EQ);
HANDLE_TOKEN_TYPE(LESS_EQ);
HANDLE_TOKEN_TYPE(PLUS_EQ);
HANDLE_TOKEN_TYPE(MINUS_EQ);
HANDLE_TOKEN_TYPE(MULT_EQ);
HANDLE_TOKEN_TYPE(DIV_EQ);
HANDLE_TOKEN_TYPE(MOD_EQ);
HANDLE_TOKEN_TYPE(AND_EQ);
HANDLE_TOKEN_TYPE(OR_EQ);
HANDLE_TOKEN_TYPE(XOR_EQ);
HANDLE_TOKEN_TYPE(RSHIFT_EQ);
HANDLE_TOKEN_TYPE(LSHIFT_EQ);
HANDLE_TOKEN_TYPE(MIN_EQ);
HANDLE_TOKEN_TYPE(MAX_EQ);
HANDLE_TOKEN_TYPE(HASH);
HANDLE_TOKEN_TYPE(PASTE);
HANDLE_TOKEN_TYPE(OPEN_SQUARE);
HANDLE_TOKEN_TYPE(CLOSE_SQUARE);
HANDLE_TOKEN_TYPE(OPEN_BRACE);
HANDLE_TOKEN_TYPE(CLOSE_BRACE);
HANDLE_TOKEN_TYPE(SEMICOLON);
HANDLE_TOKEN_TYPE(ELLIPSIS);
HANDLE_TOKEN_TYPE(PLUS_PLUS);
HANDLE_TOKEN_TYPE(MINUS_MINUS);
HANDLE_TOKEN_TYPE(DEREF);
HANDLE_TOKEN_TYPE(DOT);
HANDLE_TOKEN_TYPE(SCOPE);
HANDLE_TOKEN_TYPE(DEREF_STAR);
HANDLE_TOKEN_TYPE(DOT_STAR);
HANDLE_TOKEN_TYPE(ATSIGN);
HANDLE_TOKEN_TYPE(NAME);
HANDLE_TOKEN_TYPE(NUMBER);
HANDLE_TOKEN_TYPE(CHAR);
HANDLE_TOKEN_TYPE(WCHAR);
HANDLE_TOKEN_TYPE(OTHER);
HANDLE_TOKEN_TYPE(STRING);
HANDLE_TOKEN_TYPE(WSTRING);
HANDLE_TOKEN_TYPE(HEADER_NAME);
HANDLE_TOKEN_TYPE(COMMENT);
HANDLE_TOKEN_TYPE(MACRO_ARG);
HANDLE_TOKEN_TYPE(PADDING);
HANDLE_TOKEN_TYPE2(KEYWORD, "keyword");
default:
break;
}
#undef HANDLE_TOKEN_TYPE
if (token_type)
fprintf (stream, "%s", token_type);
else
fprintf (stream, "Token type <%d>", token->cp_type);
if (token->cp_type == CPP_NAME
|| (token->cp_type == CPP_KEYWORD
&& TREE_CODE (token->value) == IDENTIFIER_NODE))
fprintf (stream, " %s", IDENTIFIER_POINTER (token->value));
if (token->cp_type == CPP_STRING)
fprintf (stream, " \"%s\"", TREE_STRING_POINTER(token->value));
}
static unsigned long tok_index = 0;
int
c_get_token (tree *value)
{
if (flag_jet)
{
jet_token *tok;
static int lang_change_old = 0;
do {
my_friendly_assert (token_array != 0, 20040604);
my_friendly_assert (tok_index < n_tokens_used, 20040604);
tok = token_array + tok_index;
++tok_index;
} while (tok->dont_emit);
#if 0
if (flags)
*flags = tok->flags;
#endif
if (value)
*value = tok->value;
in_system_header = tok->in_system_header;
input_filename = tok->location.file;
lineno = tok->location.line;
pending_lang_change += tok->pending_lang_change - lang_change_old;
lang_change_old = tok->pending_lang_change;
return tok->type;
}
else
return c_lex (value);
}
void
c_backup_tokens (unsigned int n)
{
if (flag_jet)
{
my_friendly_assert (token_array != 0, 20040604);
while (n > 0)
{
do {
my_friendly_assert (tok_index < n_tokens_used && tok_index > 0,
20040604);
--tok_index;
} while (token_array[tok_index].dont_emit);
--n;
}
}
else
_cpp_backup_tokens (parse_in, n);
}
typedef ptrdiff_t region_index;
struct region {
jet_token *first_token;
region_index output_with_rgn;
bool must_emit;
bool root_for_must_emit;
bool was_scanned;
};
struct region *regions = 0;
size_t n_regions = 0;
size_t n_regions_allocated = 0;
region_index current_region = 0;
jet_token *token_ending_region = 0;
struct id_definition_list
{
struct id_definition_list *next;
region_index defining_region;
};
struct jet_identifier
{
tree identifier;
struct id_definition_list defn;
bool extern_const : 1;
};
static unsigned int
calc_hash (unsigned char *str, unsigned int len)
{
unsigned int n = len;
unsigned int r = 0;
#define HASHSTEP(r, c) ((r) * 67 + ((c) - 113));
while (n--)
r = HASHSTEP (r, *str++);
return r + len;
#undef HASHSTEP
}
#define IDENTIFIER_HASH_VALUE(id) \
(calc_hash (IDENTIFIER_POINTER(id), IDENTIFIER_LENGTH(id)))
static hashval_t
jet_identifier_hash (const void *item_p)
{
const struct jet_identifier * item = item_p;
return htab_hash_pointer (item->identifier);
}
static int
jet_identifier_eq (const void *a_p, const void *b_p)
{
const struct jet_identifier *a = a_p;
tree b = (tree) b_p;
return a->identifier == b;
}
static void
jet_identifier_free (void *item_p)
{
struct jet_identifier * item = item_p;
struct id_definition_list * defn = item->defn.next;
free (item);
while (defn)
{
struct id_definition_list *defn_next = defn->next;
free (defn);
defn = defn_next;
}
}
static htab_t identifier_htab;
static struct jet_identifier *
append_declaration (tree id, region_index region)
{
void** tmp;
struct jet_identifier **slot;
my_friendly_assert (id != 0 && TREE_CODE (id) == IDENTIFIER_NODE, 20040514);
tmp = htab_find_slot_with_hash (identifier_htab, id, htab_hash_pointer (id),
INSERT);
slot = (struct jet_identifier**) tmp;
if (*slot)
{
struct id_definition_list *p = &((*slot)->defn);
while (p->next && p->defining_region != region)
p = p->next;
if (p->defining_region != region)
{
p->next = xmalloc (sizeof (struct id_definition_list));
p->next->defining_region = region;
p->next->next = 0;
}
}
else
{
*slot = xmalloc (sizeof (struct jet_identifier));
(*slot)->identifier = id;
(*slot)->defn.defining_region = region;
(*slot)->defn.next = 0;
}
return *slot;
}
enum block_type {
cs_none = 0,
cs_toplevel = 1 << 0, cs_visible = 1 << 1, cs_external = 1 << 2,
cs_namespace = cs_external | cs_toplevel,
cs_function = 1 << 3,
cs_class = 1 << 4,
cs_initializer = 1 << 5,
cs_template = 1 << 6,
cs_in_function = 1 << 7,
cs_typedef = 1 << 8,
cs_enum = 1 << 9,
cs_nested_class = 1 << 10
};
enum decl_state_t { ds_none, ds_type, ds_name };
static inline enum decl_state_t
decl_state_next (enum decl_state_t x)
{
return x == ds_none ? ds_type : ds_name;
}
static inline enum decl_state_t
decl_state_prev (enum decl_state_t x)
{
return x == ds_name ? ds_type : ds_none;
}
enum linkage_spec_state_t { ls_none, ls_saw_spec };
enum namespace_state_t { ns_none, ns_saw_name, ns_saw_namespace };
enum pf_state_t {
pf_none, pf_open_paren, pf_star, pf_ident, pf_close_paren
};
enum token_type {
tt_none = 0,
tt_use = 1, tt_declaration = 2,
tt_declaration_and_use = tt_use | tt_declaration,
tt_ignore = 4,
tt_exclude = 8
};
static unsigned int open_angle_bracket_count;
static unsigned int open_paren_count;
static bool after_colon;
static bool after_colon_colon;
static bool after_class_body;
static bool inside_of_attribute;
static bool inside_of_class;
static bool inside_of_const;
static bool inside_of_enum;
static bool inside_of_extern;
static bool inside_of_friend;
static bool inside_of_function_body;
static bool inside_of_function_declaration;
static bool maybe_member_function;
static bool inside_of_initializer;
static bool in_ctor_initializer_list;
static bool inside_of_inline;
static bool inside_of_operator;
static bool inside_of_region;
static bool inside_of_template;
static bool inside_of_typedef;
static bool inside_of_using;
static bool inside_of_virtual;
static bool interesting_data;
static bool last_token_was_curly;
static bool non_built_in_types;
static enum decl_state_t decl_state;
static enum pf_state_t pf_state;
static enum linkage_spec_state_t linkage_spec_state;
static enum namespace_state_t namespace_state;
static jet_token *deferred_function_pointer = 0;
static jet_token *deferred_namespace_name = 0;
static jet_token *deferred_declaration = 0;
static jet_token *deferred_class = 0;
static jet_token *token_before_colon_colon = 0;
static jet_token *possible_opaque_type_token = 0;
static region_index active_namespace = 0;
static GTY(()) varray_type block_stack = 0;
static inline bool
block_toplevel (void)
{
unsigned short top = VARRAY_TOP_USHORT (block_stack);
return (top & cs_toplevel) != 0;
}
static inline bool
block_visible (void)
{
unsigned short top = VARRAY_TOP_USHORT (block_stack);
return (top & (cs_toplevel | cs_visible)) != 0;
}
struct jet_pch_identifier GTY(())
{
tree identifier;
size_t num_deps;
tree GTY ((length ("%h.num_deps"))) dependencies[1];
};
static hashval_t
jet_pch_identifier_hash (const void *item_p)
{
const struct jet_pch_identifier * item = item_p;
return IDENTIFIER_HASH_VALUE (item->identifier);
}
static int
jet_pch_identifier_eq (const void *a_p, const void *b_p)
{
const struct jet_pch_identifier *a = a_p;
tree b = (tree) b_p;
return a->identifier == b;
}
static GTY ((param_is (struct jet_pch_identifier))) htab_t pch_ids;
static int
use_hash_iter (void **elem_p, void *t_p)
{
tree **t = t_p;
tree elem = *elem_p;
**t = elem;
*t += 1;
return 1;
}
static int
save_pch_hash_iter (void **elem_p, void *regions_p)
{
const struct jet_identifier *elem = *elem_p;
struct region *regions = regions_p;
const struct id_definition_list *idp;
struct region *rgn;
htab_t use_hash;
struct jet_pch_identifier *result;
use_hash = htab_create (15, htab_hash_pointer, htab_eq_pointer, NULL);
for (idp = &elem->defn; idp; idp = idp->next)
for (rgn = regions + idp->defining_region; ;)
{
jet_token *tokn;
for (tokn = rgn->first_token; tokn != rgn[1].first_token; tokn++)
if (tokn->is_use)
*(htab_find_slot (use_hash, tokn->value, INSERT)) = tokn->value;
if (rgn->output_with_rgn == rgn - regions)
break;
else
rgn = regions + rgn->output_with_rgn;
}
if (htab_elements (use_hash) != 0)
{
tree * nextt;
PTR * slot;
result = ggc_alloc (sizeof (struct jet_pch_identifier)
+ (htab_elements (use_hash) - 1) * sizeof (tree));
result->identifier = elem->identifier;
result->num_deps = htab_elements (use_hash);
nextt = result->dependencies;
htab_traverse (use_hash, use_hash_iter, &nextt);
if (nextt != result->dependencies + result->num_deps)
abort ();
slot =
htab_find_slot_with_hash (pch_ids, result->identifier,
IDENTIFIER_HASH_VALUE (result->identifier),
INSERT);
if (*slot != NULL)
abort ();
*slot = result;
}
htab_delete (use_hash);
return 1;
}
static void
save_pch_data (struct region *regions, htab_t identifier_htab)
{
my_friendly_assert (regions != 0 && current_region > 0, 20040519);
my_friendly_assert (regions[current_region].first_token != 0, 20040519);
my_friendly_assert (regions[current_region].first_token->cp_type == CPP_EOF,
20040519);
pch_ids = htab_create_ggc (htab_elements (identifier_htab) * 3 / 4,
jet_pch_identifier_hash,
jet_pch_identifier_eq, NULL);
htab_traverse (identifier_htab, save_pch_hash_iter, regions);
}
static htab_t GTY ((param_is (union tree_node))) scanned_for_pch_htab;
static region_index
add_pch_relations (region_index nexti, tree id, struct region *regions,
htab_t identifier_htab)
{
struct jet_pch_identifier *jpi = 0;
PTR *seen;
size_t i;
seen = htab_find_slot (scanned_for_pch_htab, id, INSERT);
if (! *seen)
jpi = htab_find_with_hash (pch_ids,
id, IDENTIFIER_HASH_VALUE (id));
*seen = id;
if (jpi)
for (i = 0; i < jpi->num_deps; i++)
{
struct jet_identifier *ji;
struct id_definition_list *def;
ji = htab_find_with_hash (identifier_htab,
jpi->dependencies[i],
htab_hash_pointer (jpi->dependencies[i]));
if (ji)
for (def = &ji->defn; def; def = def->next)
if (! regions[def->defining_region].must_emit)
{
regions[def->defining_region].must_emit = true;
if (nexti > def->defining_region)
nexti = def->defining_region;
}
nexti = add_pch_relations (nexti, jpi->dependencies[i], regions,
identifier_htab);
}
return nexti;
}
static void
setup_must_emit (jet_token *token_limit,
struct region *regions,
struct region *region_limit)
{
region_index i;
scanned_for_pch_htab = htab_create (12289,
htab_hash_pointer,
htab_eq_pointer,
NULL);
my_friendly_assert (regions != 0 && region_limit != 0, 20040519);
my_friendly_assert (region_limit > regions, 20040519);
my_friendly_assert ((region_limit-1)->first_token == token_limit-1,
20040519);
my_friendly_assert ((token_limit-1)->cp_type == CPP_EOF, 20040519);
{
jet_token *tok;
for (tok = regions[0].first_token; tok != token_limit; tok++)
tok->dont_emit = true;
}
i = 0;
while (regions + i != region_limit)
{
region_index nexti = i + 1;
if (regions[i].must_emit && ! regions[i].was_scanned)
{
jet_token * tok;
regions[i].was_scanned = true;
if (regions[i].output_with_rgn != i
&& regions[i].output_with_rgn != 0
&& ! regions[regions[i].output_with_rgn].must_emit)
{
regions[regions[i].output_with_rgn].must_emit = true;
if (nexti > regions[i].output_with_rgn)
nexti = regions[i].output_with_rgn;
}
for (tok = regions[i].first_token;
tok < regions[i + 1].first_token;
tok++)
{
tok->dont_emit = false;
if (tok->is_use)
{
struct jet_identifier *ji;
struct id_definition_list *def;
ji = htab_find_with_hash (identifier_htab,
tok->value, htab_hash_pointer (tok->value));
if (ji)
for (def = &ji->defn; def; def = def->next)
{
region_index def_rgn = def->defining_region;
if (def_rgn != 0 && ! regions[def_rgn].must_emit)
{
regions[def_rgn].must_emit = true;
if (nexti > def_rgn)
nexti = def_rgn;
}
}
if (pch_ids)
nexti = add_pch_relations (nexti, tok->value,
regions,
identifier_htab);
}
}
}
i = nexti;
}
(token_limit-1)->dont_emit = false;
}
static inline bool
is_class_key (enum rid x)
{
return x == RID_CLASS || x == RID_STRUCT || x == RID_UNION;
}
static void
declare (enum token_type type, jet_token *tok, bool is_initializer)
{
if (type & tt_use)
tok->is_use = true;
if ((type & tt_declaration)
&& (block_toplevel()
|| (VARRAY_TOP_USHORT (block_stack) & cs_enum)
|| is_class_key ((tok-1)->keyword)))
{
struct jet_identifier *id
= append_declaration (tok->value, current_region);
tok->is_decl = true;
append_declaration (tok->value, active_namespace);
if (inside_of_const && inside_of_extern)
id->extern_const = true;
if (inside_of_const && is_initializer && id->extern_const)
{
regions[current_region].must_emit = true;
regions[current_region].root_for_must_emit = true;
}
}
}
static inline bool
is_fundamental_type_specifier (enum rid x)
{
switch (x) {
case RID_CHAR: return true;
case RID_WCHAR: return true;
case RID_BOOL: return true;
case RID_SHORT: return true;
case RID_INT: return true;
case RID_LONG: return true;
case RID_SIGNED: return true;
case RID_UNSIGNED: return true;
case RID_FLOAT: return true;
case RID_DOUBLE: return true;
case RID_VOID: return true;
default: return false;
}
}
static void
maybe_reallocate_region_array (void)
{
if (n_regions == n_regions_allocated)
{
n_regions_allocated *= 2;
regions = xrealloc (regions,
n_regions_allocated * sizeof (struct region));
memset (regions + n_regions,
0,
(n_regions_allocated - n_regions) * sizeof (struct region));
}
}
static void
maybe_begin_region (jet_token *tok)
{
if (!inside_of_region)
{
struct region *reg;
maybe_reallocate_region_array ();
++n_regions;
current_region = n_regions-1;
reg = regions + current_region;
reg->first_token = tok;
reg->output_with_rgn = active_namespace;
reg->must_emit = false;
reg->root_for_must_emit = false;
reg->was_scanned = false;
decl_state = ds_none;
last_token_was_curly = false;
inside_of_region = true;
my_friendly_assert (!token_ending_region
|| tok == token_ending_region + 1,
20040514);
}
}
static void
end_region (jet_token *tok)
{
my_friendly_assert (inside_of_region, 20040514);
token_ending_region = tok;
inside_of_region = false;
}
static void
reset_parse_context (void)
{
open_angle_bracket_count = 0;
after_colon = false;
after_colon_colon = false;
after_class_body = false;
inside_of_attribute = false;
inside_of_class = false;
inside_of_const = false;
inside_of_enum = false;
inside_of_friend = false;
inside_of_extern = false;
inside_of_function_body = false;
inside_of_function_declaration = false;
maybe_member_function = false;
inside_of_initializer = false;
in_ctor_initializer_list = false;
inside_of_inline = false;
inside_of_operator = false;
inside_of_template = false;
inside_of_typedef = false;
inside_of_using = false;
inside_of_virtual = false;
interesting_data = false;
last_token_was_curly = false;
non_built_in_types = false;
decl_state = ds_none;
pf_state = pf_none;
linkage_spec_state = ls_none;
deferred_namespace_name = 0;
deferred_declaration = 0;
token_before_colon_colon = 0;
possible_opaque_type_token = 0;
}
static void
initialize_parse_context (jet_token *first_token)
{
VARRAY_USHORT_INIT (block_stack, 16, "nested block stack");
VARRAY_PUSH_USHORT (block_stack, cs_toplevel);
n_regions = 0;
n_regions_allocated = 1000;
regions = xcalloc (n_regions_allocated, sizeof (struct region));
identifier_htab = htab_create (12289, jet_identifier_hash, jet_identifier_eq,
jet_identifier_free);
open_paren_count = 0;
namespace_state = ns_none;
deferred_function_pointer = 0;
deferred_class = 0;
regions[0].first_token = first_token;
regions[0].output_with_rgn = 0;
regions[0].must_emit = false;
regions[0].root_for_must_emit = false;
regions[0].was_scanned = false;
active_namespace = 0;
n_regions = 1;
current_region = 0;
inside_of_region = false;
reset_parse_context();
}
static void
destroy_parse_context (void)
{
htab_delete (identifier_htab);
free (regions);
n_regions = 0;
current_region = 0;
n_regions_allocated = 0;
regions = 0;
VARRAY_POP_ALL (block_stack);
}
static bool
declared_as_namespace_p (tree id)
{
struct jet_identifier *ji;
my_friendly_assert (id != 0 && TREE_CODE (id) == IDENTIFIER_NODE, 20040525);
ji = htab_find_with_hash (identifier_htab, id, htab_hash_pointer (id));
if (ji)
{
struct id_definition_list *def = &(ji->defn);
while (def)
{
struct region *reg = regions + def->defining_region;
struct jet_token *tok = reg->first_token;
if (tok->keyword != RID_NAMESPACE
|| (tok+1)->cp_type != CPP_NAME
|| (tok+1)->value != id)
return false;
def = def->next;
}
return true;
}
else
return false;
}
static void
analyze_identifier (jet_token *tok)
{
bool is_nested_name_specifier;
bool is_namespace_name;
my_friendly_assert (tok != 0 && tok->cp_type == CPP_NAME, 20040512);
my_friendly_assert (block_visible(), 20040512);
if (namespace_state == ns_saw_namespace)
{
namespace_state = ns_saw_name;
deferred_namespace_name = tok;
return;
}
if (inside_of_operator && decl_state == ds_none)
non_built_in_types = true;
if (open_angle_bracket_count > 0 || inside_of_initializer)
return;
if (VARRAY_TOP_USHORT (block_stack) & cs_enum)
{
declare (tt_declaration, tok, false);
return;
}
is_nested_name_specifier = (tok+1)->cp_type == CPP_SCOPE;
is_namespace_name =
is_nested_name_specifier && declared_as_namespace_p (tok->value);
if (inside_of_using)
{
if (is_nested_name_specifier && !is_namespace_name)
declare (tt_use, tok, false);
else if (!is_nested_name_specifier)
declare (tt_declaration_and_use, tok, false);
}
if (!(VARRAY_TOP_USHORT (block_stack) & cs_class)
&& inside_of_operator
&& open_paren_count > 0
&& decl_state == ds_none
&& !inside_of_template
&& !is_namespace_name)
{
declare (tt_declaration_and_use, tok, false);
return;
}
if (inside_of_attribute)
return;
if (after_class_body && open_paren_count == 0)
{
declare (tt_declaration, tok, false);
}
if (inside_of_typedef && decl_state == ds_name && open_paren_count == 0)
{
declare (tt_declaration, tok, false);
return;
}
switch (pf_state) {
case pf_none:
if (tok == token_before_colon_colon)
break;
else if (after_colon_colon)
{
after_colon_colon = false;
return;
}
else if (!inside_of_enum && decl_state == ds_none)
return;
case pf_open_paren:
case pf_close_paren:
case pf_ident:
pf_state = pf_none;
break;
case pf_star:
pf_state = pf_ident;
deferred_function_pointer = tok;
return;
}
if (open_paren_count > 0 || open_angle_bracket_count > 0)
return;
if (inside_of_class)
{
if (inside_of_template)
{
deferred_class = tok;
return;
}
else if (after_colon)
return;
else if (last_token_was_curly
|| (inside_of_typedef && decl_state == ds_name))
declare (tt_declaration, tok, false);
else if (decl_state == ds_type)
{
deferred_class = tok;
return;
}
}
deferred_declaration = tok;
}
#define GOTO_ERROR fancy_abort (__FILE__, __LINE__, __FUNCTION__)
static bool
parse_token_stream (jet_token *first, jet_token *last)
{
jet_token *tok;
tok = first;
while (tok != last)
{
if (tok->cp_type == CPP_STRING || tok->cp_type == CPP_WSTRING) {
if (!inside_of_region)
GOTO_ERROR;
if (inside_of_extern && decl_state == ds_none)
linkage_spec_state = ls_saw_spec;
if (inside_of_initializer)
interesting_data = true;
++tok;
}
else if (tok->keyword == RID_VIRTUAL) {
inside_of_virtual = true;
maybe_begin_region (tok);
++tok;
}
else if (tok->keyword == RID_ENUM) {
if (block_toplevel())
decl_state = decl_state_next (decl_state);
inside_of_enum = true;
maybe_begin_region (tok);
++tok;
}
else if (is_class_key (tok->keyword)) {
maybe_begin_region (tok);
if (inside_of_template)
decl_state = ds_none;
if (block_toplevel())
decl_state = decl_state_next (decl_state);
if (open_angle_bracket_count == 0)
inside_of_class = true;
++tok;
}
else if (tok->keyword == RID_TEMPLATE) {
maybe_begin_region (tok);
if (block_visible ())
decl_state = decl_state_next (decl_state);
inside_of_template = true;
++tok;
}
else if (tok->keyword == RID_NAMESPACE) {
if (block_toplevel()) {
if (inside_of_using)
{
regions[current_region].must_emit = true;
regions[current_region].root_for_must_emit = true;
}
else
namespace_state = ns_saw_namespace;
}
maybe_begin_region (tok);
++tok;
}
else if (tok->keyword == RID_USING) {
if (block_toplevel())
inside_of_using = true;
maybe_begin_region (tok);
++tok;
}
else if (is_fundamental_type_specifier (tok->keyword)) {
maybe_begin_region (tok);
if (block_visible ())
decl_state = ds_type;
++tok;
}
else if (tok->keyword == RID_EXTERN) {
if (block_visible ())
inside_of_extern = true;
maybe_begin_region (tok);
++tok;
}
else if (tok->keyword == RID_STATIC) {
maybe_begin_region (tok);
++tok;
}
else if (tok->keyword == RID_INLINE) {
if (block_visible ())
inside_of_inline = true;
maybe_begin_region (tok);
++tok;
}
else if (tok->keyword == RID_ATTRIBUTE) {
maybe_begin_region (tok);
inside_of_attribute = true;
++tok;
}
else if (tok->keyword == RID_ASM) {
maybe_begin_region (tok);
++tok;
}
else if (tok->keyword == RID_EXTENSION) {
maybe_begin_region (tok);
++tok;
}
else if (tok->keyword == RID_THREAD) {
maybe_begin_region (tok);
++tok;
}
else if (tok->keyword == RID_OPERATOR) {
maybe_begin_region (tok);
if (block_visible ())
inside_of_operator = true;
++tok;
}
else if (tok->keyword == RID_TYPEDEF) {
maybe_begin_region (tok);
if (block_visible ())
inside_of_typedef = true;
++tok;
}
else if (tok->keyword == RID_FRIEND) {
inside_of_friend = true;
maybe_begin_region (tok);
++tok;
}
else if (tok->keyword == RID_CONST) {
maybe_begin_region (tok);
if (block_toplevel() && decl_state == ds_none)
inside_of_const = true;
++tok;
}
else if (tok->keyword == RID_VOLATILE) {
maybe_begin_region (tok);
++tok;
}
else if (tok->cp_type == CPP_SEMICOLON)
{
if (block_visible ()
&& linkage_spec_state == ls_saw_spec
&& !inside_of_initializer)
{
linkage_spec_state = ls_none;
end_region (tok);
}
else if (block_toplevel())
{
if (deferred_declaration)
declare (tt_declaration, deferred_declaration, false);
deferred_declaration = 0;
if (inside_of_class)
{
if (deferred_class && decl_state == ds_name)
declare (tt_declaration_and_use, deferred_class, false);
}
if (interesting_data
|| (!(inside_of_const || inside_of_template
|| inside_of_extern || inside_of_inline
|| inside_of_typedef || inside_of_enum)
&& (inside_of_initializer || inside_of_function_body
|| (!inside_of_function_declaration
&& !inside_of_class
&& !inside_of_using
&& !last_token_was_curly))))
{
regions[current_region].must_emit = true;
regions[current_region].root_for_must_emit = true;
}
open_angle_bracket_count = 0;
deferred_class = 0;
if (inside_of_region)
end_region (tok);
else
{
maybe_begin_region (tok);
end_region (tok);
}
}
reset_parse_context();
namespace_state = ns_none;
++tok;
}
else if (tok->cp_type == CPP_OPEN_SQUARE) {
if (block_visible ())
++open_paren_count;
if (!inside_of_region)
GOTO_ERROR;
++tok;
}
else if (tok->cp_type == CPP_CLOSE_SQUARE) {
if (block_visible ()) {
if (open_paren_count == 0)
GOTO_ERROR;
--open_paren_count;
}
if (!inside_of_region)
GOTO_ERROR;
++tok;
}
else if (tok->cp_type == CPP_EQ) {
if (!inside_of_region)
GOTO_ERROR;
if (deferred_declaration)
declare (tt_declaration, deferred_declaration, true);
deferred_declaration = 0;
decl_state = ds_none;
if (possible_opaque_type_token)
{
possible_opaque_type_token->is_use = false;
possible_opaque_type_token = 0;
}
if (block_toplevel() || (VARRAY_TOP_USHORT (block_stack) & cs_enum))
{
if (open_angle_bracket_count == 0 && !inside_of_operator)
inside_of_initializer = true;
if (namespace_state == ns_saw_name && !inside_of_using)
{
jet_token *t = regions[current_region].first_token;
namespace_state = ns_saw_namespace;
while (t != tok)
{
if (t->cp_type == CPP_NAME)
declare (tt_declaration, t, false);
++t;
}
}
}
++tok;
}
else if (tok->cp_type == CPP_COMMA) {
if (!inside_of_region)
GOTO_ERROR;
if (open_angle_bracket_count == 0)
{
if (deferred_declaration)
declare (tt_declaration, deferred_declaration, false);
deferred_declaration = 0;
}
inside_of_initializer = false;
if (open_paren_count > 0)
decl_state = ds_none;
++tok;
}
else if (tok->cp_type == CPP_MULT) {
if (!inside_of_region)
GOTO_ERROR;
if (pf_state == pf_open_paren)
pf_state = pf_star;
else if (pf_state == pf_none
&& open_paren_count > 0
&& ((tok-1)->cp_type == CPP_OPEN_PAREN || (tok-1)->cp_type == CPP_SCOPE))
pf_state = pf_star;
else
pf_state = pf_none;
++tok;
}
else if (tok->cp_type == CPP_DEREF_STAR || tok->cp_type == CPP_DOT_STAR) {
if (!inside_of_region)
GOTO_ERROR;
if (open_paren_count > 0)
pf_state = pf_star;
else
pf_state = pf_none;
++tok;
}
else if (tok->cp_type == CPP_OPEN_PAREN) {
if (block_visible ())
{
if (deferred_declaration)
declare (tt_declaration, deferred_declaration, false);
deferred_declaration = 0;
++open_paren_count;
decl_state = ds_none;
token_before_colon_colon = 0;
if (!inside_of_initializer)
inside_of_function_declaration = true;
switch (pf_state) {
case pf_none:
pf_state = pf_open_paren;
break;
case pf_open_paren:
case pf_star:
case pf_ident:
pf_state = pf_none;
break;
case pf_close_paren:
if (!deferred_function_pointer)
GOTO_ERROR;
declare (tt_declaration, deferred_function_pointer, false);
pf_state = pf_none;
break;
}
}
maybe_begin_region (tok);
++tok;
}
else if (tok->cp_type == CPP_CLOSE_PAREN) {
if (!inside_of_region)
GOTO_ERROR;
if (block_visible ())
{
--open_paren_count;
if (open_paren_count == 0)
{
inside_of_attribute = false;
if (inside_of_operator
&& !(VARRAY_TOP_USHORT (block_stack) & cs_class)
&& !non_built_in_types)
{
regions[current_region].must_emit = true;
regions[current_region].root_for_must_emit = true;
}
}
if (pf_state == pf_ident)
pf_state = pf_close_paren;
}
++tok;
}
else if (tok->cp_type == CPP_OPEN_BRACE) {
if (!inside_of_region)
GOTO_ERROR;
if (deferred_declaration)
declare (tt_declaration, deferred_declaration, false);
deferred_declaration = 0;
if (inside_of_class && deferred_class && !after_colon)
declare (tt_declaration_and_use, deferred_class, false);
VARRAY_PUSH_USHORT (block_stack, cs_none);
if (linkage_spec_state == ls_saw_spec
|| namespace_state == ns_saw_namespace
|| namespace_state == ns_saw_name)
{
VARRAY_TOP_USHORT (block_stack) |= cs_namespace;
namespace_state = ns_none;
active_namespace = current_region;
if (deferred_namespace_name)
{
declare (tt_declaration, deferred_namespace_name, false);
deferred_namespace_name = 0;
}
end_region (tok);
}
else
{
unsigned short prev;
if (VARRAY_ACTIVE_SIZE(block_stack) < 2)
GOTO_ERROR;
prev = VARRAY_USHORT(block_stack, VARRAY_ACTIVE_SIZE(block_stack) - 2);
if (prev & (cs_function | cs_in_function))
VARRAY_TOP_USHORT (block_stack) |= cs_in_function;
else
{
VARRAY_TOP_USHORT (block_stack) =
prev & (cs_class | cs_template | cs_initializer);
if (inside_of_function_declaration
&& !inside_of_initializer)
{
VARRAY_TOP_USHORT (block_stack) |= cs_function;
inside_of_function_body = true;
if (!(VARRAY_TOP_USHORT (block_stack) & (cs_template | cs_class)))
{
if ((!inside_of_template || inside_of_operator)
&& (!inside_of_inline
|| maybe_member_function
|| inside_of_operator))
{
regions[current_region].must_emit = true;
regions[current_region].root_for_must_emit = true;
}
maybe_member_function = false;
}
}
if (inside_of_class)
VARRAY_TOP_USHORT (block_stack) |= cs_class;
if (inside_of_template)
VARRAY_TOP_USHORT (block_stack) |= cs_template;
if (inside_of_typedef)
VARRAY_TOP_USHORT (block_stack) |= cs_typedef;
if ((prev & cs_toplevel) == cs_toplevel)
{
VARRAY_TOP_USHORT (block_stack) |= cs_external;
if (inside_of_class)
VARRAY_TOP_USHORT (block_stack) |= cs_visible;
}
if (inside_of_enum)
{
VARRAY_TOP_USHORT (block_stack) |= cs_enum;
if (prev & (cs_visible | cs_toplevel))
VARRAY_TOP_USHORT (block_stack) |= cs_visible;
}
if (inside_of_initializer)
{
VARRAY_TOP_USHORT (block_stack) |= cs_initializer;
}
deferred_class = 0;
after_colon = false;
if (VARRAY_TOP_USHORT (block_stack) == cs_none)
VARRAY_TOP_USHORT (block_stack) = cs_nested_class;
}
maybe_begin_region (tok);
}
reset_parse_context();
++tok;
}
else if (tok->cp_type == CPP_CLOSE_BRACE) {
size_t n = VARRAY_ACTIVE_SIZE (block_stack);
unsigned short top;
region_index enclosing_namespace;
if (n < 2)
GOTO_ERROR;
top = VARRAY_TOP_USHORT (block_stack);
switch (top & ~((unsigned short)(cs_template | cs_visible))) {
case cs_namespace:
my_friendly_assert (tok != first, 20040514);
if (inside_of_region)
end_region (tok-1);
maybe_begin_region (tok);
enclosing_namespace = regions[active_namespace].output_with_rgn;
regions[active_namespace].output_with_rgn = current_region;
regions[current_region].output_with_rgn = enclosing_namespace;
active_namespace = enclosing_namespace;
end_region(tok);
reset_parse_context();
break;
case cs_function | cs_external:
end_region (tok);
reset_parse_context ();
break;
case cs_class | cs_typedef:
case cs_external | cs_class | cs_typedef:
case cs_typedef | cs_external:
case cs_enum | cs_external:
case cs_typedef:
case cs_enum:
case cs_function:
case cs_class:
case cs_initializer | cs_external:
case cs_class | cs_external:
case cs_external:
case cs_class | cs_function:
my_friendly_assert (inside_of_region, 20040514);
reset_parse_context ();
break;
case cs_none:
GOTO_ERROR;
case cs_in_function:
case cs_nested_class:
case cs_initializer:
default:
my_friendly_assert (inside_of_region, 20040514);
break;
}
after_class_body = (top & (cs_class | cs_nested_class | cs_enum))
&& !(top & cs_function);
interesting_data = (top & cs_initializer);
last_token_was_curly = true;
VARRAY_POP(block_stack);
++tok;
}
else if (tok->cp_type == CPP_LESS) {
if (!inside_of_region)
GOTO_ERROR;
if ((inside_of_typedef || (inside_of_template && block_toplevel())
|| (inside_of_function_declaration && open_paren_count > 0))
&& (tok-1)->keyword != RID_OPERATOR)
{
++open_angle_bracket_count;
}
++tok;
}
else if (tok->cp_type == CPP_GREATER) {
if (!inside_of_region)
GOTO_ERROR;
if ((inside_of_typedef || (inside_of_template && block_toplevel())
|| (inside_of_function_declaration && open_paren_count > 0))
&& (tok-1)->keyword != RID_OPERATOR)
{
if (open_angle_bracket_count == 0)
GOTO_ERROR;
--open_angle_bracket_count;
after_colon_colon = false;
}
++tok;
}
else if (tok->cp_type == CPP_COLON) {
if (!inside_of_region)
GOTO_ERROR;
if (block_toplevel()
&& (inside_of_template || inside_of_class)
&& deferred_class != 0)
{
declare (tt_declaration_and_use, deferred_class, false);
deferred_class = 0;
}
if (inside_of_function_declaration
&& maybe_member_function
&& (block_toplevel() || (VARRAY_TOP_USHORT (block_stack) & cs_class)))
in_ctor_initializer_list = true;
after_colon = true;
++tok;
}
else if (tok->cp_type == CPP_SCOPE) {
if (block_toplevel())
{
if (deferred_declaration)
{
enum token_type tt = tt_declaration_and_use;
if (inside_of_template)
{
my_friendly_assert (deferred_declaration != first, 20040524);
if ((deferred_declaration-1)->keyword == RID_TYPENAME)
tt = tt_use;
}
declare (tt, deferred_declaration, false);
deferred_declaration = 0;
}
if (open_paren_count == 0 && open_angle_bracket_count == 0)
maybe_member_function = true;
if (open_angle_bracket_count == 0)
decl_state = decl_state_prev (decl_state);
}
after_colon_colon = true;
if (tok != first)
token_before_colon_colon = tok - 1;
maybe_begin_region (tok);
++tok;
}
else if (tok->cp_type == CPP_NAME) {
bool is_function_parameter_name =
inside_of_function_declaration
&& open_paren_count == 1
&& open_angle_bracket_count == 0
&& decl_state == ds_type
&& !in_ctor_initializer_list;
if (decl_state == ds_type
&& inside_of_class
&& inside_of_virtual
&& open_paren_count > 0
&& (VARRAY_TOP_USHORT(block_stack) & cs_class)
&& !in_ctor_initializer_list)
possible_opaque_type_token = tok;
maybe_begin_region (tok);
if (!is_function_parameter_name
&& tok != first
&& (tok-1)->keyword != RID_NAMESPACE
&& !declared_as_namespace_p (tok->value))
tok->is_use = true;
if (block_visible() && !in_ctor_initializer_list)
analyze_identifier (tok);
if (tok != first
&& open_angle_bracket_count == 0
&& is_class_key ((tok-1)->keyword))
declare (tt_declaration_and_use, tok, false);
if (block_toplevel()
&& open_angle_bracket_count == 0
&& !in_ctor_initializer_list)
decl_state = decl_state_next (decl_state);
++tok;
}
else if (tok->cp_type == CPP_EOF) {
if (tok != last-1)
GOTO_ERROR;
if (inside_of_region)
end_region (0);
maybe_begin_region (tok);
regions[current_region].output_with_rgn = current_region;
regions[current_region].must_emit = true;
regions[current_region].root_for_must_emit = true;
++tok;
}
else if (tok->cp_type == CPP_NUMBER) { ++tok; }
else if (tok->cp_type == CPP_CHAR || tok->cp_type == CPP_WCHAR) { ++tok; }
else { ++tok; }
}
return true;
}
static void
debug_print_regions (jet_token *token_stream, size_t n_tokens)
{
unsigned long n;
my_friendly_assert (token_stream != 0 && n_tokens > 0, 20040517);
my_friendly_assert (regions != 0 && n_regions > 0, 20040517);
fprintf (stderr, "\nJet regions:\n");
for (n = 0lu; n < (unsigned long) n_regions; ++n)
{
struct region *reg = regions+n;
unsigned long first_token
= (unsigned long) (reg->first_token - token_stream);
unsigned long last_token
= n < n_regions-1
? (unsigned long) ((reg+1)->first_token - token_stream)
: (unsigned long) n_tokens;
unsigned long output_with = (unsigned long) reg->output_with_rgn;
fprintf (stderr, " Region %05lu%c%c ",
n,
(reg->must_emit ? '*' : ' '),
(reg->root_for_must_emit ? '*' : ' '));
fprintf (stderr, "tokens [%lu-%lu)",
first_token, last_token);
if (output_with != n)
fprintf (stderr, " -> %05lu\n", output_with);
else
fprintf (stderr, "\n");
}
}
static int
debug_print_id_traversal (void **slot, void *dummy ATTRIBUTE_UNUSED)
{
struct jet_identifier *jet_id;
tree id;
struct id_definition_list *def;
my_friendly_assert (slot != 0 && *slot != 0, 20040517);
jet_id = (struct jet_identifier*) (*slot);
id = jet_id->identifier;
def = &(jet_id->defn);
my_friendly_assert (id != 0 && TREE_CODE (id) == IDENTIFIER_NODE, 20040517);
fprintf (stderr, " ID \"%s\"", IDENTIFIER_POINTER (id));
fprintf (stderr, " (def: ");
while (def)
{
fprintf (stderr, "%lu%s",
(unsigned long) def->defining_region,
def->next ? " " : "");
def = def->next;
}
fprintf (stderr, ")");
if (jet_id->extern_const)
fprintf (stderr, " extern const");
fprintf (stderr, "\n");
return 1;
}
static void
debug_print_identifiers (void)
{
fprintf (stderr, "\nJet identifiers:\n");
htab_traverse (identifier_htab,
&debug_print_id_traversal,
(void*) 0);
}
static inline double
get_time (void)
{
struct timeval t;
gettimeofday (&t, 0);
return t.tv_sec + 1.e-6 * t.tv_usec;
}
#define mix(a,b,c) \
{ \
a -= b; a -= c; a ^= (c>>13); \
b -= c; b -= a; b ^= (a<< 8); \
c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
}
hashval_t iterative_hash (k_in, length, initval)
const PTR k_in;
register size_t length;
register hashval_t initval;
{
register const unsigned char *k = (const unsigned char *)k_in;
register hashval_t a,b,c,len;
len = length;
a = b = 0x9e3779b9;
c = initval;
#ifndef WORDS_BIGENDIAN
if (sizeof (hashval_t) == 4 && (((size_t)k)&3) == 0)
while (len >= 12)
{
a += *(hashval_t *)(k+0);
b += *(hashval_t *)(k+4);
c += *(hashval_t *)(k+8);
mix(a,b,c);
k += 12; len -= 12;
}
else
#endif
while (len >= 12)
{
a += (k[0] +((hashval_t)k[1]<<8) +((hashval_t)k[2]<<16) +((hashval_t)k[3]<<24));
b += (k[4] +((hashval_t)k[5]<<8) +((hashval_t)k[6]<<16) +((hashval_t)k[7]<<24));
c += (k[8] +((hashval_t)k[9]<<8) +((hashval_t)k[10]<<16)+((hashval_t)k[11]<<24));
mix(a,b,c);
k += 12; len -= 12;
}
c += length;
switch(len)
{
case 11: c+=((hashval_t)k[10]<<24);
case 10: c+=((hashval_t)k[9]<<16);
case 9 : c+=((hashval_t)k[8]<<8);
case 8 : b+=((hashval_t)k[7]<<24);
case 7 : b+=((hashval_t)k[6]<<16);
case 6 : b+=((hashval_t)k[5]<<8);
case 5 : b+=k[4];
case 4 : a+=((hashval_t)k[3]<<24);
case 3 : a+=((hashval_t)k[2]<<16);
case 2 : a+=((hashval_t)k[1]<<8);
case 1 : a+=k[0];
}
mix(a,b,c);
return c;
}
static hashval_t
iterative_hash_buf (const void *buf, int n, hashval_t val)
{
const char *first = buf;
const char *last = first + n;
while (first != last)
{
int chunk = (last - first) < 4 ? (last - first) : 4;
val = iterative_hash (first, chunk, val);
first += chunk;
}
return val;
}
static hashval_t
iterative_hash_node (tree t, hashval_t val)
{
switch (TREE_CODE (t))
{
case INTEGER_CST:
{
unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (t);
HOST_WIDE_INT high = TREE_INT_CST_HIGH (t);
val = iterative_hash (&low, sizeof(low), val);
val = iterative_hash (&high, sizeof(high), val);
break;
}
case REAL_CST:
{
struct real_value *r = TREE_REAL_CST_PTR (t);
val = iterative_hash_buf (r, sizeof(struct real_value), val);
break;
}
case COMPLEX_CST:
val = iterative_hash_node (TREE_REALPART (t), val);
val = iterative_hash_node (TREE_IMAGPART (t), val);
break;
case STRING_CST:
val = iterative_hash_buf (TREE_STRING_POINTER (t),
TREE_STRING_LENGTH (t),
val);
break;
case IDENTIFIER_NODE:
{
unsigned int h = IDENTIFIER_HASH_VALUE (t);
val = iterative_hash (&h, sizeof(h), val);
break;
}
default:
fancy_abort (__FILE__, __LINE__, __FUNCTION__);
}
return val;
}
static hashval_t
hash_token_array (jet_token *first, jet_token *last)
{
hashval_t val = toplev_argv_hash;
for ( ; first != last; ++first)
if (!first->dont_emit)
{
int type_and_kw = ((int) first->type << 16) + (int) first->keyword;
val = iterative_hash (&type_and_kw, sizeof(int), val);
if (first->value)
val = iterative_hash_node (first->value, val);
}
return val != 0 ? val : 1;
}
unsigned int jet_token_hash;
static void
read_token (jet_token *tok)
{
my_friendly_assert (tok != 0, 20040618);
tok->type = c_lex (&tok->value );
tok->in_system_header = in_system_header;
tok->location.file = input_filename;
tok->location.line = lineno;
tok->pending_lang_change = pending_lang_change;
if (tok->type == CPP_NAME
&& C_IS_RESERVED_WORD (tok->value))
{
tok->cp_type = CPP_KEYWORD;
tok->keyword = C_RID_CODE (tok->value);
}
else
{
tok->cp_type = tok->type;
tok->keyword = RID_MAX;
}
}
void
initialize_jet(void)
{
jet_token *tok;
jet_token first_tok;
bool ok;
double time_before_lex = 0, time_after_lex = 0;
double time_before_parse = 0, time_after_parse = 0;
double time_after_graph = 0;
double time_before_hash = 0, time_after_hash = 0;
my_friendly_assert (flag_jet != 0, 20040604);
if (flag_debug_jet & 16)
time_before_lex = get_time();
memset (&first_tok, 0, sizeof(first_tok));
read_token (&first_tok);
n_tokens_allocated = 10000;
n_tokens_used = 1;
token_array = ggc_calloc (n_tokens_allocated, sizeof (jet_token));
token_array[0] = first_tok;
if (first_tok.type != CPP_EOF)
do {
if (n_tokens_used == n_tokens_allocated)
token_array_expand ();
++n_tokens_used;
tok = token_array + n_tokens_used - 1;
read_token (tok);
} while (tok->type != CPP_EOF);
if (flag_debug_jet & 16)
time_after_lex = get_time();
if (flag_debug_jet & 1)
{
fprintf(stderr, "\nBefore jet: Token array: %ld used, %ld allocated\n",
n_tokens_used, n_tokens_allocated);
{
unsigned long i;
for (i = 0; i < n_tokens_used; ++i)
{
fprintf (stderr, "%7lu (%5d): ", i, token_array[i].location.line);
debug_print_token (stderr, token_array+i);
fprintf(stderr, "\n");
}
}
}
if (flag_debug_jet & 16)
time_before_parse = get_time();
initialize_parse_context (token_array);
ok = parse_token_stream (token_array, token_array + n_tokens_used);
if (flag_debug_jet & 4)
debug_print_regions (token_array, n_tokens_used);
if (flag_debug_jet & 8)
debug_print_identifiers ();
if (flag_debug_jet & 16)
time_after_parse = get_time();
if (ok)
{
if (pch_file)
save_pch_data (regions, identifier_htab);
else
setup_must_emit (token_array + n_tokens_used,
regions,
regions + n_regions);
}
else
{
warning ("jet parsing failed, reverting to ordinary parse");
}
destroy_parse_context();
if (! pch_file)
htab_delete (scanned_for_pch_htab);
if (flag_debug_jet & 16)
{
size_t n_emitted;
size_t i;
time_after_graph = get_time();
n_emitted = 0;
for (i = 0; i < n_tokens_used; ++i)
if (!token_array[i].dont_emit)
++n_emitted;
fprintf (stderr, "\nJet timing (tokens: %lu before, %lu after)\n",
n_tokens_used, n_emitted);
fprintf (stderr, " Lexing: %g\n", time_after_lex - time_before_lex);
fprintf (stderr, " Parsing: %g\n", time_after_parse - time_before_parse);
fprintf (stderr, " Graph: %g\n", time_after_graph - time_after_parse);
fprintf (stderr, " Total: %g\n", time_after_graph - time_before_parse);
}
if (flag_debug_jet & 2)
{
fprintf(stderr, "\nAfter jet:\n");
{
unsigned long i;
for (i = 0; i < n_tokens_used; ++i)
{
if (token_array[i].dont_emit)
continue;
fprintf (stderr, "%7lu%c%c(%5d): ",
i,
token_array[i].is_use ? '*' : ' ',
token_array[i].is_decl ? '=' : ' ',
token_array[i].location.line);
debug_print_token (stderr, token_array+i);
fprintf(stderr, "\n");
}
}
}
if (flag_debug_jet & 32)
time_before_hash = get_time();
jet_token_hash = hash_token_array (token_array, token_array+n_tokens_used);
if (flag_debug_jet & 32)
time_after_hash = get_time();
if (flag_debug_jet & 32)
{
fprintf(stderr, "Hash of token stream:%u Args:%u Command line:%u\n",
jet_token_hash, toplev_argv_hash, flag_jet_hash_code);
fprintf(stderr, " Hash timing: %g\n",
time_after_hash - time_before_hash);
}
}
#include "gt-cp-jet.h"