New macro expander.

2000-10-28  Neil Booth  <neilb@earthling.net>

	New macro expander.

	* cpplib.c (struct answer): New.
	(struct if_stack): Use cpp_lexer_pos rather than line and col.
	Rename cmacro mi_cmacro.
	(struct directive, KANDR, STDC89, EXTENSION, COND, IF_COND, INCL,
	IN_I): New directive and flags.
	(skip_rest_of_line, check_eol, run_directive, glue_header_name,
	parse_answer, parse_assertion, find_answer): New functions.
	(parse_ifdef, detect_if_not_defined, validate_else): Remove.
	(lex_macro_node): New function to replace parse_ifdef and
	get_define_node.

	(_cpp_handle_directive): New function, combines _cpp_check_directive
	and _cpp_check_linemarker.

	(do_define, do_undef, parse_include, do_include, do_import,
	do_include_next, read_line_number, do_line, do_ident, do_pragma,
	do_pragma_once, do_pragma_poison, do_pragma_dependency):
	Update for new token getting interface.

	(do_ifdef, do_ifndef, do_if, do_else, do_endif, push_conditional)
	: Update for new multiple-include optimisation technique.
	(do_elif): Don't forget to invalidate controlling macros.

	(unwind_if_stack, cpp_defined, cpp_push_buffer, cpp_pop_buffer): Update.
	(parse_assertion, parse_answer, find_answer, _cpp_test_assertion):
	Functions to handle assertions with the new token interface.
	(do_assert, do_unassert): Use them.

	(cpp_define, _cpp_define_builtin, cpp_undef, cpp_assert, cpp_unassert):
	Use run_directive.

	(_cpp_init_stacks): Register directive names.  Don't register special
	nodes.

	* cpperror.c (print_containing_files, _cpp_begin_message): Update to
	new position recording regime.
	(cpp_ice, cpp_fatal, cpp_error, cpp_error_with_line, cpp_warning,
	cpp_warning_with_line, cpp_pedwarn, cpp_pedwarn_with_line,
	cpp_pedwarn_with_file_and_line): Update for _cpp_begin_message changes.
	(cpp_type2name): Move to cpplex.c.

	* cppexp.c (parse_charconst): spec_nodes is no longer a pointer.
	(parse_defined): Update to handle new multiple include optimisation
	method.  Remove poisoned identifier warning.
	(parse_assertion, TYPE_NAME): Delete.
	(lex): Update for multiple include optimisation, removal of
	CPP_DEFINED, to use _cpp_test_assertion for assertions and
	cpp_token_as_text.
	(_cpp_parse_expr): Update for MI optimisation, and to use op_as_text.
	(op_as_text): New function, to wrap cpp_token_as_text.

	* cppfiles.c (stack_include_file, _cpp_pop_file_buffer):
	Update for MI optimisation.
	(_cpp_execute_include): Take a token rather than 3 arguments.  Fix
	segfault on diagnostic.
	(_cpp_compare_file_date): Take a token rather than 3 args.
	(cpp_read_file): Work correctly for zero-length files.

	* cpphash.c (_cpp_init_macros, _cpp_cleanup_macros): Rename
	_cpp_init_hashtable and _cpp_cleanup_hashtable.
	(cpp_lookup): Place identifiers at front of identifier pool
	for _cpp_lookup_with_hash.
	(_cpp_lookup_with_hash): Require identifiers to be at the front of
	the identifier pool.  Commit the memory if not already in the
	hash table.

	* cppinit.c (cpp_reader_init): Move cpp_init_completed test to top.
	Initialise various members of cpp_reader, memory pools, and the
	special nodes.
	(cpp_printer_init): Delete.
	(cpp_cleanup): Update.
	(struct builtin, builtin_array, initialize_builtins): Update for new
	hashnode definition and builtin handling.
	(cpp_start_read, cpp_finish): Don't take or initialise a
	printer.  Update.

	* cpplib.h (cpp_printer, cpp_toklist, CPP_DEFINED, BOL,
	PASTED, VAR_ARGS, BEG_OF_FILE, IN_DIRECTIVE, KNOWN_DIRECTIVE,
	T_VOID, T_SPECLINE, T_DATE, T_FILE, T_BASE_FILE, T_INCLUDE_LEVEL,
	T_TIME, T_STDC, T_OPERATOR, T_POISON, T_MACRO, T_ASSERTION): Delete.
	(struct cpp_pool, struct cpp_macro, struct cpp_lexer_pos,
	struct cpp_lookahead, CPP_DHASH, enum mi_state, enum mi_ind,
	NO_EXPAND, VARARGS_FIRST, struct cpp_token_with_pos,
	struct toklist, struct cpp_context, struct specnodes,
	TOKEN_LOOKAHEAD, TOKEN_BUFFSIZE, NODE_OPERATOR, NODE_POISONED,
	NODE_BUILTIN, NODE_DIAGNOSTIC, NT_VOID, NT_MACRO, NT_ASSERTION,
	enum builtin_type, cpp_can_paste): New.
	(struct cpp_token): Delete line and col members.
	(struct cpp_buffer): New member output_lineno.
	(struct lexer_state): Delete indented, in_lex_line, seen_dot.
	Add va_args_ok, poisoned_ok, prevent_expansion, parsing_args.
	(struct cpp_reader): New members lexer_pos, macro_pos, directive_pos,
	ident_pool, temp_string_pool, macro_pool, argument_pool, string_pool,
	base_context, context, directive, mi_state, mi_if_not_defined,
	mi_lexed, mi_cmacro, mi_ind_cmacro, la_read, la_write, la_unused,
	mlstring_pos, macro_buffer, macro_buffer_len.
	Delete members mls_line, mls_column, token_list, potential_control_macro,
	temp_tokens, temp_cap, temp_alloced, temp_used, first_directive_token,
	context_cap, cur_context, no_expand_level, paste_level, contexts, args,
	save_parameter_spellings, need_newline, .
	Change type of date, time and spec_nodes members.
	Change prototypes for include and ident callbacks.
	(struct cpp_hashnode): Change type of name.  Remove union members
	expansion and code.  Add members macro, operator and builtin.

	(cpp_token_len, cpp_token_as_text, cpp_spell_token, cpp_start_read,
	cpp_finish, cpp_avoid_paste, cpp_get_token, cpp_get_line,
	cpp_get_output_line, cpp_macro_definition, cpp_start_lookahead,
	cpp_stop_lookahead): New prototypes.
	(cpp_printer_init, cpp_dump_definition): Delete prototypes.

	(U_CHAR, U, ustrcmp, ustrncmp, ustrlen, uxstrdup, ustrchr, ufputs):
	Move from cpphash.h.

	* cpphash.h (U_CHAR, U, ustrcmp, ustrncmp, ustrlen, uxstrdup, ustrchr,
	ufputs): Move to cpplib.h.
	(enum spell_type, struct token_spelling, _cpp_token_spellings, TOKEN_SPELL,
	TOKEN_NAME, struct answer, FREE_ANSWER, KANDR, STDC89, EXTENSION,
	COND, EXPAND, INCL, COMMENTS, IN_I, struct directive, directive_handler,
	struct spec_nodes, _cpp_digraph_spellings, _cpp_free_temp_tokens,
	_cpp_init_input_buffer, _cpp_grow_token_buffer, _cpp_init_toklist,
	_cpp_clear_toklist, _cpp_expand_token_space, _cpp_expand_name_space,
	_cpp_equiv_tokens, _cpp_equiv_toklists, _cpp_process_directive,
	_cpp_run_directive, _cpp_get_line, _cpp_get_raw_token, _cpp_glue_header_name,
	_cpp_can_paste, _cpp_check_directive, _cpp_check_linemarker,
	_cpp_parse_assertion, _cpp_find_answer): Delete.
	(VALID_SIGN, ALIGN, POOL_FRONT, POOL_LIMIT, POOL_BASE, POOL_SIZE,
	POOL_USED, POOL_COMMIT, struct cpp_chunk, _cpp_lex_token, _cpp_init_pool,
	_cpp_free_pool, _cpp_pool_reserve, _cpp_pool_alloc, _cpp_next_chunk,
	_cpp_lock_pool, _cpp_unlock_pool, _cpp_test_assertion,
	_cpp_handle_directive, DSC): New.
	(struct include_file): New member defined.

	(DO_NOT_REREAD, _cpp_begin_message, _cpp_execute_include,
	_cpp_compare_file_date): Update.
	(_cpp_pop_context, _cpp_get_token, _cpp_free_lookaheads, _cpp_push_token): New.
	(_cpp_init_macros, _cpp_cleanup_macros): Rename to _cpp_init_hashtable,
	_cpp_cleanup_hashtable.

	* Makefile.in: Remove cppoutput.c.

	* cppoutput.c: Delete

	* fixheader.c (read_scan_file): Update for new cpp_get_token
	prototype.
	(recognized_function): New argument LINE.

	* scan-decls.c (skip_to_closing_brace, scan_decls): Update for
	new cpp_get_token prototype.

	* scan.h (recognized_function): Update prototype.

	* po/POTFILES.in: Remove cppoutput.c.

From-SVN: r37098
This commit is contained in:
Neil Booth 2000-10-28 17:59:06 +00:00 committed by Neil Booth
parent de48b52da8
commit 93c80368d9
18 changed files with 4012 additions and 4232 deletions

View File

@ -1,3 +1,161 @@
2000-10-28 Neil Booth <neilb@earthling.net>
New macro expander.
* cpplib.c (struct answer): New.
(struct if_stack): Use cpp_lexer_pos rather than line and col.
Rename cmacro mi_cmacro.
(struct directive, KANDR, STDC89, EXTENSION, COND, IF_COND, INCL,
IN_I): New directive and flags.
(skip_rest_of_line, check_eol, run_directive, glue_header_name,
parse_answer, parse_assertion, find_answer): New functions.
(parse_ifdef, detect_if_not_defined, validate_else): Remove.
(lex_macro_node): New function to replace parse_ifdef and
get_define_node.
(_cpp_handle_directive): New function, combines _cpp_check_directive
and _cpp_check_linemarker.
(do_define, do_undef, parse_include, do_include, do_import,
do_include_next, read_line_number, do_line, do_ident, do_pragma,
do_pragma_once, do_pragma_poison, do_pragma_dependency):
Update for new token getting interface.
(do_ifdef, do_ifndef, do_if, do_else, do_endif, push_conditional)
: Update for new multiple-include optimisation technique.
(do_elif): Don't forget to invalidate controlling macros.
(unwind_if_stack, cpp_defined, cpp_push_buffer, cpp_pop_buffer): Update.
(parse_assertion, parse_answer, find_answer, _cpp_test_assertion):
Functions to handle assertions with the new token interface.
(do_assert, do_unassert): Use them.
(cpp_define, _cpp_define_builtin, cpp_undef, cpp_assert, cpp_unassert):
Use run_directive.
(_cpp_init_stacks): Register directive names. Don't register special
nodes.
* cpperror.c (print_containing_files, _cpp_begin_message): Update to
new position recording regime.
(cpp_ice, cpp_fatal, cpp_error, cpp_error_with_line, cpp_warning,
cpp_warning_with_line, cpp_pedwarn, cpp_pedwarn_with_line,
cpp_pedwarn_with_file_and_line): Update for _cpp_begin_message changes.
(cpp_type2name): Move to cpplex.c.
* cppexp.c (parse_charconst): spec_nodes is no longer a pointer.
(parse_defined): Update to handle new multiple include optimisation
method. Remove poisoned identifier warning.
(parse_assertion, TYPE_NAME): Delete.
(lex): Update for multiple include optimisation, removal of
CPP_DEFINED, to use _cpp_test_assertion for assertions and
cpp_token_as_text.
(_cpp_parse_expr): Update for MI optimisation, and to use op_as_text.
(op_as_text): New function, to wrap cpp_token_as_text.
* cppfiles.c (stack_include_file, _cpp_pop_file_buffer):
Update for MI optimisation.
(_cpp_execute_include): Take a token rather than 3 arguments. Fix
segfault on diagnostic.
(_cpp_compare_file_date): Take a token rather than 3 args.
(cpp_read_file): Work correctly for zero-length files.
* cpphash.c (_cpp_init_macros, _cpp_cleanup_macros): Rename
_cpp_init_hashtable and _cpp_cleanup_hashtable.
(cpp_lookup): Place identifiers at front of identifier pool
for _cpp_lookup_with_hash.
(_cpp_lookup_with_hash): Require identifiers to be at the front of
the identifier pool. Commit the memory if not already in the
hash table.
* cppinit.c (cpp_reader_init): Move cpp_init_completed test to top.
Initialise various members of cpp_reader, memory pools, and the
special nodes.
(cpp_printer_init): Delete.
(cpp_cleanup): Update.
(struct builtin, builtin_array, initialize_builtins): Update for new
hashnode definition and builtin handling.
(cpp_start_read, cpp_finish): Don't take or initialise a
printer. Update.
* cpplib.h (cpp_printer, cpp_toklist, CPP_DEFINED, BOL,
PASTED, VAR_ARGS, BEG_OF_FILE, IN_DIRECTIVE, KNOWN_DIRECTIVE,
T_VOID, T_SPECLINE, T_DATE, T_FILE, T_BASE_FILE, T_INCLUDE_LEVEL,
T_TIME, T_STDC, T_OPERATOR, T_POISON, T_MACRO, T_ASSERTION): Delete.
(struct cpp_pool, struct cpp_macro, struct cpp_lexer_pos,
struct cpp_lookahead, CPP_DHASH, enum mi_state, enum mi_ind,
NO_EXPAND, VARARGS_FIRST, struct cpp_token_with_pos,
struct toklist, struct cpp_context, struct specnodes,
TOKEN_LOOKAHEAD, TOKEN_BUFFSIZE, NODE_OPERATOR, NODE_POISONED,
NODE_BUILTIN, NODE_DIAGNOSTIC, NT_VOID, NT_MACRO, NT_ASSERTION,
enum builtin_type, cpp_can_paste): New.
(struct cpp_token): Delete line and col members.
(struct cpp_buffer): New member output_lineno.
(struct lexer_state): Delete indented, in_lex_line, seen_dot.
Add va_args_ok, poisoned_ok, prevent_expansion, parsing_args.
(struct cpp_reader): New members lexer_pos, macro_pos, directive_pos,
ident_pool, temp_string_pool, macro_pool, argument_pool, string_pool,
base_context, context, directive, mi_state, mi_if_not_defined,
mi_lexed, mi_cmacro, mi_ind_cmacro, la_read, la_write, la_unused,
mlstring_pos, macro_buffer, macro_buffer_len.
Delete members mls_line, mls_column, token_list, potential_control_macro,
temp_tokens, temp_cap, temp_alloced, temp_used, first_directive_token,
context_cap, cur_context, no_expand_level, paste_level, contexts, args,
save_parameter_spellings, need_newline, .
Change type of date, time and spec_nodes members.
Change prototypes for include and ident callbacks.
(struct cpp_hashnode): Change type of name. Remove union members
expansion and code. Add members macro, operator and builtin.
(cpp_token_len, cpp_token_as_text, cpp_spell_token, cpp_start_read,
cpp_finish, cpp_avoid_paste, cpp_get_token, cpp_get_line,
cpp_get_output_line, cpp_macro_definition, cpp_start_lookahead,
cpp_stop_lookahead): New prototypes.
(cpp_printer_init, cpp_dump_definition): Delete prototypes.
(U_CHAR, U, ustrcmp, ustrncmp, ustrlen, uxstrdup, ustrchr, ufputs):
Move from cpphash.h.
* cpphash.h (U_CHAR, U, ustrcmp, ustrncmp, ustrlen, uxstrdup, ustrchr,
ufputs): Move to cpplib.h.
(enum spell_type, struct token_spelling, _cpp_token_spellings, TOKEN_SPELL,
TOKEN_NAME, struct answer, FREE_ANSWER, KANDR, STDC89, EXTENSION,
COND, EXPAND, INCL, COMMENTS, IN_I, struct directive, directive_handler,
struct spec_nodes, _cpp_digraph_spellings, _cpp_free_temp_tokens,
_cpp_init_input_buffer, _cpp_grow_token_buffer, _cpp_init_toklist,
_cpp_clear_toklist, _cpp_expand_token_space, _cpp_expand_name_space,
_cpp_equiv_tokens, _cpp_equiv_toklists, _cpp_process_directive,
_cpp_run_directive, _cpp_get_line, _cpp_get_raw_token, _cpp_glue_header_name,
_cpp_can_paste, _cpp_check_directive, _cpp_check_linemarker,
_cpp_parse_assertion, _cpp_find_answer): Delete.
(VALID_SIGN, ALIGN, POOL_FRONT, POOL_LIMIT, POOL_BASE, POOL_SIZE,
POOL_USED, POOL_COMMIT, struct cpp_chunk, _cpp_lex_token, _cpp_init_pool,
_cpp_free_pool, _cpp_pool_reserve, _cpp_pool_alloc, _cpp_next_chunk,
_cpp_lock_pool, _cpp_unlock_pool, _cpp_test_assertion,
_cpp_handle_directive, DSC): New.
(struct include_file): New member defined.
(DO_NOT_REREAD, _cpp_begin_message, _cpp_execute_include,
_cpp_compare_file_date): Update.
(_cpp_pop_context, _cpp_get_token, _cpp_free_lookaheads, _cpp_push_token): New.
(_cpp_init_macros, _cpp_cleanup_macros): Rename to _cpp_init_hashtable,
_cpp_cleanup_hashtable.
* Makefile.in: Remove cppoutput.c.
* cppoutput.c: Delete
* fixheader.c (read_scan_file): Update for new cpp_get_token
prototype.
(recognized_function): New argument LINE.
* scan-decls.c (skip_to_closing_brace, scan_decls): Update for
new cpp_get_token prototype.
* scan.h (recognized_function): Update prototype.
* po/POTFILES.in: Remove cppoutput.c.
2000-10-27 Mark Mitchell <mark@codesourcery.com>
* c-typeck.c (check_init_type_bitfields): Remove.

View File

@ -1841,7 +1841,7 @@ PREPROCESSOR_DEFINES = \
-DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\"
LIBCPP_OBJS = cpplib.o cpplex.o cppmacro.o cppexp.o cppfiles.o \
cpphash.o cpperror.o cppinit.o cppdefault.o cppoutput.o \
cpphash.o cpperror.o cppinit.o cppdefault.o \
mkdeps.o prefix.o version.o mbchar.o
LIBCPP_DEPS = cpplib.h cpphash.h intl.h system.h
@ -1863,7 +1863,6 @@ cpperror.o: cpperror.c $(CONFIG_H) $(LIBCPP_DEPS)
cppexp.o: cppexp.c $(CONFIG_H) $(LIBCPP_DEPS) defaults.h
cpplex.o: cpplex.c $(CONFIG_H) $(LIBCPP_DEPS)
cppmacro.o: cppmacro.c $(CONFIG_H) $(LIBCPP_DEPS)
cppoutput.o: cppoutput.c $(CONFIG_H) $(LIBCPP_DEPS)
cpplib.o: cpplib.c $(CONFIG_H) $(LIBCPP_DEPS) $(OBSTACK_H)
cpphash.o: cpphash.c $(CONFIG_H) $(LIBCPP_DEPS) $(OBSTACK_H)
cppfiles.o: cppfiles.c $(CONFIG_H) $(LIBCPP_DEPS) $(SPLAY_TREE_H) mkdeps.h

View File

@ -57,11 +57,10 @@ print_containing_files (pfile, ip)
if (first)
{
first = 0;
/* N.B. The current line in each outer source file is one
greater than the line of the #include, so we must
subtract one to correct for that. */
/* The current line in each outer source file is now the
same as the line of the #include. */
fprintf (stderr, _("In file included from %s:%u"),
ip->nominal_fname, CPP_BUF_LINE (ip) - 1);
ip->nominal_fname, CPP_BUF_LINE (ip));
}
else
/* Translators note: this message is used in conjunction
@ -107,12 +106,11 @@ print_file_and_line (filename, line, column)
If it returns 0, this error has been suppressed. */
int
_cpp_begin_message (pfile, code, file, line, col)
_cpp_begin_message (pfile, code, file, pos)
cpp_reader *pfile;
enum error_type code;
const char *file;
unsigned int line;
unsigned int col;
const cpp_lexer_pos *pos;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
int is_warning = 0;
@ -177,11 +175,11 @@ _cpp_begin_message (pfile, code, file, line, col)
{
if (file == NULL)
file = ip->nominal_fname;
if (line == 0)
line = _cpp_get_line (pfile, &col);
if (pos == 0)
pos = cpp_get_line (pfile);
print_containing_files (pfile, ip);
print_file_and_line (file, line,
CPP_OPTION (pfile, show_column) ? col : 0);
print_file_and_line (file, pos->line,
CPP_OPTION (pfile, show_column) ? pos->col : 0);
}
else
fprintf (stderr, "%s: ", progname);
@ -213,7 +211,7 @@ cpp_ice VPARAMS ((cpp_reader *pfile, const char *msgid, ...))
msgid = va_arg (ap, const char *);
#endif
if (_cpp_begin_message (pfile, ICE, NULL, 0, 0))
if (_cpp_begin_message (pfile, ICE, NULL, 0))
v_message (msgid, ap);
va_end(ap);
}
@ -240,7 +238,7 @@ cpp_fatal VPARAMS ((cpp_reader *pfile, const char *msgid, ...))
msgid = va_arg (ap, const char *);
#endif
if (_cpp_begin_message (pfile, FATAL, NULL, 0, 0))
if (_cpp_begin_message (pfile, FATAL, NULL, 0))
v_message (msgid, ap);
va_end(ap);
}
@ -261,7 +259,7 @@ cpp_error VPARAMS ((cpp_reader * pfile, const char *msgid, ...))
msgid = va_arg (ap, const char *);
#endif
if (_cpp_begin_message (pfile, ERROR, NULL, 0, 0))
if (_cpp_begin_message (pfile, ERROR, NULL, 0))
v_message (msgid, ap);
va_end(ap);
}
@ -277,6 +275,7 @@ cpp_error_with_line VPARAMS ((cpp_reader *pfile, int line, int column,
const char *msgid;
#endif
va_list ap;
cpp_lexer_pos pos;
VA_START (ap, msgid);
@ -287,7 +286,9 @@ cpp_error_with_line VPARAMS ((cpp_reader *pfile, int line, int column,
msgid = va_arg (ap, const char *);
#endif
if (_cpp_begin_message (pfile, ERROR, NULL, line, column))
pos.line = line;
pos.col = column;
if (_cpp_begin_message (pfile, ERROR, NULL, &pos))
v_message (msgid, ap);
va_end(ap);
}
@ -317,7 +318,7 @@ cpp_warning VPARAMS ((cpp_reader * pfile, const char *msgid, ...))
msgid = va_arg (ap, const char *);
#endif
if (_cpp_begin_message (pfile, WARNING, NULL, 0, 0))
if (_cpp_begin_message (pfile, WARNING, NULL, 0))
v_message (msgid, ap);
va_end(ap);
}
@ -333,6 +334,7 @@ cpp_warning_with_line VPARAMS ((cpp_reader * pfile, int line, int column,
const char *msgid;
#endif
va_list ap;
cpp_lexer_pos pos;
VA_START (ap, msgid);
@ -343,7 +345,9 @@ cpp_warning_with_line VPARAMS ((cpp_reader * pfile, int line, int column,
msgid = va_arg (ap, const char *);
#endif
if (_cpp_begin_message (pfile, WARNING, NULL, line, column))
pos.line = line;
pos.col = column;
if (_cpp_begin_message (pfile, WARNING, NULL, &pos))
v_message (msgid, ap);
va_end(ap);
}
@ -364,7 +368,7 @@ cpp_pedwarn VPARAMS ((cpp_reader * pfile, const char *msgid, ...))
msgid = va_arg (ap, const char *);
#endif
if (_cpp_begin_message (pfile, PEDWARN, NULL, 0, 0))
if (_cpp_begin_message (pfile, PEDWARN, NULL, 0))
v_message (msgid, ap);
va_end(ap);
}
@ -380,6 +384,7 @@ cpp_pedwarn_with_line VPARAMS ((cpp_reader * pfile, int line, int column,
const char *msgid;
#endif
va_list ap;
cpp_lexer_pos pos;
VA_START (ap, msgid);
@ -390,7 +395,9 @@ cpp_pedwarn_with_line VPARAMS ((cpp_reader * pfile, int line, int column,
msgid = va_arg (ap, const char *);
#endif
if (_cpp_begin_message (pfile, PEDWARN, NULL, line, column))
pos.line = line;
pos.col = column;
if (_cpp_begin_message (pfile, PEDWARN, NULL, &pos))
v_message (msgid, ap);
va_end(ap);
}
@ -411,6 +418,7 @@ cpp_pedwarn_with_file_and_line VPARAMS ((cpp_reader *pfile,
const char *msgid;
#endif
va_list ap;
cpp_lexer_pos pos;
VA_START (ap, msgid);
@ -422,7 +430,9 @@ cpp_pedwarn_with_file_and_line VPARAMS ((cpp_reader *pfile,
msgid = va_arg (ap, const char *);
#endif
if (_cpp_begin_message (pfile, PEDWARN, file, line, col))
pos.line = line;
pos.col = col;
if (_cpp_begin_message (pfile, PEDWARN, file, &pos))
v_message (msgid, ap);
va_end(ap);
}
@ -462,11 +472,3 @@ cpp_notice_from_errno (pfile, name)
name = "stdout";
cpp_notice (pfile, "%s: %s", name, xstrerror (errno));
}
const char *
cpp_type2name (type)
enum cpp_ttype type;
{
return (const char *) _cpp_token_spellings[type].name;
}

View File

@ -63,10 +63,10 @@ static HOST_WIDEST_INT right_shift PARAMS ((cpp_reader *, HOST_WIDEST_INT,
static struct op parse_number PARAMS ((cpp_reader *, const cpp_token *));
static struct op parse_charconst PARAMS ((cpp_reader *, const cpp_token *));
static struct op parse_defined PARAMS ((cpp_reader *));
static struct op parse_assertion PARAMS ((cpp_reader *));
static HOST_WIDEST_INT parse_escape PARAMS ((cpp_reader *, const U_CHAR **,
const U_CHAR *, HOST_WIDEST_INT));
static struct op lex PARAMS ((cpp_reader *, int));
static struct op lex PARAMS ((cpp_reader *, int, cpp_token *));
static const unsigned char *op_as_text PARAMS ((cpp_reader *, enum cpp_ttype));
struct op
{
@ -291,7 +291,7 @@ parse_charconst (pfile, tok)
/* If char type is signed, sign-extend the constant. */
num_bits = num_chars * width;
if (pfile->spec_nodes->n__CHAR_UNSIGNED__->type != T_VOID
if (pfile->spec_nodes.n__CHAR_UNSIGNED__->type == NT_MACRO
|| ((result >> (num_bits - 1)) & 1) == 0)
op.value = result & ((unsigned HOST_WIDEST_INT) ~0
>> (HOST_BITS_PER_WIDEST_INT - num_bits));
@ -313,85 +313,85 @@ static struct op
parse_defined (pfile)
cpp_reader *pfile;
{
int paren;
const cpp_token *tok;
int paren = 0;
cpp_hashnode *node = 0;
cpp_token token;
struct op op;
paren = 0;
tok = _cpp_get_raw_token (pfile);
if (tok->type == CPP_OPEN_PAREN)
/* Don't expand macros. */
pfile->state.prevent_expansion++;
_cpp_get_token (pfile, &token);
if (token.type == CPP_OPEN_PAREN)
{
paren = 1;
tok = _cpp_get_raw_token (pfile);
_cpp_get_token (pfile, &token);
}
if (tok->type != CPP_NAME)
SYNTAX_ERROR ("\"defined\" without an identifier");
if (paren && _cpp_get_raw_token (pfile)->type != CPP_CLOSE_PAREN)
SYNTAX_ERROR ("missing close paren after \"defined\"");
if (tok->val.node->type == T_POISON)
SYNTAX_ERROR2 ("attempt to use poisoned \"%s\"", tok->val.node->name);
op.value = tok->val.node->type != T_VOID;
op.unsignedp = 0;
op.op = CPP_INT;
return op;
syntax_error:
op.op = CPP_ERROR;
return op;
}
static struct op
parse_assertion (pfile)
cpp_reader *pfile;
{
struct op op;
struct answer *answer;
cpp_hashnode *hp;
op.op = CPP_ERROR;
hp = _cpp_parse_assertion (pfile, &answer);
if (hp)
if (token.type == CPP_NAME)
{
/* If we get here, the syntax is valid. */
op.op = CPP_INT;
op.unsignedp = 0;
op.value = (hp->type == T_ASSERTION &&
(answer == 0 || *_cpp_find_answer (hp, &answer->list) != 0));
if (answer)
FREE_ANSWER (answer);
node = token.val.node;
if (paren)
{
_cpp_get_token (pfile, &token);
if (token.type != CPP_CLOSE_PAREN)
{
cpp_error (pfile, "missing ')' after \"defined\"");
node = 0;
}
}
}
else
cpp_error (pfile, "\"defined\" without an identifier");
if (!node)
op.op = CPP_ERROR;
else
{
op.value = node->type == NT_MACRO;
op.unsignedp = 0;
op.op = CPP_INT;
/* No macros? At top of file? */
if (pfile->mi_state == MI_OUTSIDE && pfile->mi_cmacro == 0
&& pfile->mi_if_not_defined == MI_IND_NOT && pfile->mi_lexed == 1)
{
cpp_start_lookahead (pfile);
cpp_get_token (pfile, &token);
if (token.type == CPP_EOF)
pfile->mi_ind_cmacro = node;
cpp_stop_lookahead (pfile, 0);
}
}
pfile->state.prevent_expansion--;
return op;
}
/* Read one token. */
static struct op
lex (pfile, skip_evaluation)
lex (pfile, skip_evaluation, token)
cpp_reader *pfile;
int skip_evaluation;
cpp_token *token;
{
struct op op;
const cpp_token *tok;
retry:
tok = _cpp_get_token (pfile);
_cpp_get_token (pfile, token);
switch (tok->type)
switch (token->type)
{
case CPP_PLACEMARKER:
goto retry;
case CPP_INT:
case CPP_NUMBER:
return parse_number (pfile, tok);
return parse_number (pfile, token);
case CPP_CHAR:
case CPP_WCHAR:
return parse_charconst (pfile, tok);
return parse_charconst (pfile, token);
case CPP_STRING:
case CPP_WSTRING:
@ -401,36 +401,60 @@ lex (pfile, skip_evaluation)
SYNTAX_ERROR ("floating point numbers are not valid in #if");
case CPP_OTHER:
if (ISGRAPH (tok->val.aux))
SYNTAX_ERROR2 ("invalid character '%c' in #if", tok->val.aux);
if (ISGRAPH (token->val.aux))
SYNTAX_ERROR2 ("invalid character '%c' in #if", token->val.aux);
else
SYNTAX_ERROR2 ("invalid character '\\%03o' in #if", tok->val.aux);
case CPP_DEFINED:
return parse_defined (pfile);
SYNTAX_ERROR2 ("invalid character '\\%03o' in #if", token->val.aux);
case CPP_NAME:
if (token->val.node == pfile->spec_nodes.n_defined)
{
if (pfile->context->prev && CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "\"defined\" operator appears during macro expansion");
return parse_defined (pfile);
}
/* Controlling #if expressions cannot contain identifiers (they
could become macros in the future). */
pfile->mi_state = MI_FAILED;
op.op = CPP_INT;
op.unsignedp = 0;
op.value = 0;
if (CPP_OPTION (pfile, warn_undef) && !skip_evaluation)
cpp_warning (pfile, "\"%s\" is not defined", tok->val.node->name);
cpp_warning (pfile, "\"%s\" is not defined", token->val.node->name);
return op;
case CPP_HASH:
return parse_assertion (pfile);
{
int temp;
op.op = CPP_INT;
if (_cpp_test_assertion (pfile, &temp))
op.op = CPP_ERROR;
op.unsignedp = 0;
op.value = temp;
return op;
}
case CPP_NOT:
/* We don't worry about its position here. */
pfile->mi_if_not_defined = MI_IND_NOT;
/* Fall through. */
default:
if ((tok->type > CPP_EQ && tok->type < CPP_PLUS_EQ)
|| tok->type == CPP_EOF)
if ((token->type > CPP_EQ && token->type < CPP_PLUS_EQ)
|| token->type == CPP_EOF)
{
op.op = tok->type;
op.op = token->type;
return op;
}
SYNTAX_ERROR2("'%s' is not valid in #if expressions", TOKEN_NAME (tok));
}
SYNTAX_ERROR2 ("\"%s\" is not valid in #if expressions",
cpp_token_as_text (pfile, token));
}
syntax_error:
op.op = CPP_ERROR;
@ -709,8 +733,6 @@ op_to_prio[] =
/* Parse and evaluate a C expression, reading from PFILE.
Returns the truth value of the expression. */
#define TYPE_NAME(t) _cpp_token_spellings[t].name
int
_cpp_parse_expr (pfile)
cpp_reader *pfile;
@ -729,6 +751,7 @@ _cpp_parse_expr (pfile)
struct op init_stack[INIT_STACK_SIZE];
struct op *stack = init_stack;
struct op *limit = stack + INIT_STACK_SIZE;
cpp_token token;
register struct op *top = stack + 1;
int skip_evaluation = 0;
int result;
@ -737,6 +760,10 @@ _cpp_parse_expr (pfile)
int save_skipping = pfile->skipping;
pfile->skipping = 0;
/* Set up detection of #if ! defined(). */
pfile->mi_lexed = 0;
pfile->mi_if_not_defined = MI_IND_NONE;
/* We've finished when we try to reduce this. */
top->op = CPP_EOF;
/* Nifty way to catch missing '('. */
@ -751,7 +778,8 @@ _cpp_parse_expr (pfile)
struct op op;
/* Read a token */
op = lex (pfile, skip_evaluation);
op = lex (pfile, skip_evaluation, &token);
pfile->mi_lexed++;
/* If the token is an operand, push its value and get next
token. If it is an operator, get its priority and flags, and
@ -797,7 +825,7 @@ _cpp_parse_expr (pfile)
SYNTAX_ERROR ("void expression between '(' and ')'");
else
SYNTAX_ERROR2 ("operator '%s' has no right operand",
TYPE_NAME (top->op));
op_as_text (pfile, top->op));
}
unsigned2 = top->unsignedp, v2 = top->value;
@ -808,7 +836,8 @@ _cpp_parse_expr (pfile)
switch (top[1].op)
{
default:
cpp_ice (pfile, "impossible operator type %s", TYPE_NAME (op.op));
cpp_ice (pfile, "impossible operator '%s'",
op_as_text (pfile, top[1].op));
goto syntax_error;
case CPP_NOT: UNARY(!); break;
@ -967,13 +996,13 @@ _cpp_parse_expr (pfile)
{
if (top->flags & HAVE_VALUE)
SYNTAX_ERROR2 ("missing binary operator before '%s'",
TYPE_NAME (op.op));
op_as_text (pfile, top->op));
}
else
{
if (!(top->flags & HAVE_VALUE))
SYNTAX_ERROR2 ("operator '%s' has no left operand",
TYPE_NAME (op.op));
op_as_text (pfile, top->op));
}
/* Check for and handle stack overflow. */
@ -1017,3 +1046,15 @@ _cpp_parse_expr (pfile)
pfile->skipping = save_skipping;
return result;
}
static const unsigned char *
op_as_text (pfile, op)
cpp_reader *pfile;
enum cpp_ttype op;
{
cpp_token token;
token.type = op;
token.flags = 0;
return cpp_token_as_text (pfile, &token);
}

View File

@ -217,6 +217,10 @@ stack_include_file (pfile, inc)
if (fp == 0)
return 0;
/* Initialise controlling macro state. */
pfile->mi_state = MI_OUTSIDE;
pfile->mi_cmacro = 0;
fp->inc = inc;
fp->nominal_fname = inc->name;
fp->buf = inc->buffer;
@ -233,8 +237,10 @@ stack_include_file (pfile, inc)
fp->inc->refcnt++;
pfile->include_depth++;
pfile->input_stack_listing_current = 0;
if (pfile->cb.enter_file)
(*pfile->cb.enter_file) (pfile);
return 1;
}
@ -562,17 +568,21 @@ report_missing_guard (n, b)
#define PRINT_THIS_DEP(p, b) (CPP_PRINT_DEPS(p) > (b||p->system_include_depth))
void
_cpp_execute_include (pfile, f, len, no_reinclude, search_start, angle_brackets)
_cpp_execute_include (pfile, header, no_reinclude, search_start)
cpp_reader *pfile;
const U_CHAR *f;
unsigned int len;
const cpp_token *header;
int no_reinclude;
struct file_name_list *search_start;
int angle_brackets;
{
unsigned int len = header->val.str.len;
unsigned int angle_brackets = header->type == CPP_HEADER_NAME;
struct include_file *inc;
char *fname;
fname = alloca (len + 1);
memcpy (fname, header->val.str.text, len);
fname[len] = '\0';
if (!search_start)
{
if (angle_brackets)
@ -581,18 +591,14 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start, angle_brackets)
search_start = CPP_OPTION (pfile, quote_include);
else
search_start = CPP_BUFFER (pfile)->actual_dir;
}
if (!search_start)
{
cpp_error (pfile, "No include path in which to find %s", f);
return;
if (!search_start)
{
cpp_error (pfile, "No include path in which to find %s", fname);
return;
}
}
fname = alloca (len + 1);
memcpy (fname, f, len);
fname[len] = '\0';
inc = find_include_file (pfile, fname, search_start);
if (inc)
@ -666,20 +672,17 @@ _cpp_execute_include (pfile, f, len, no_reinclude, search_start, angle_brackets)
/* Locate file F, and determine whether it is newer than PFILE. Return -1,
if F cannot be located or dated, 1, if it is newer and 0 if older. */
int
_cpp_compare_file_date (pfile, f, len, angle_brackets)
_cpp_compare_file_date (pfile, f)
cpp_reader *pfile;
const U_CHAR *f;
unsigned int len;
int angle_brackets;
const cpp_token *f;
{
unsigned int len = f->val.str.len;
char *fname;
struct file_name_list *search_start;
struct include_file *inc;
struct include_file *current_include = CPP_BUFFER (pfile)->inc;
if (angle_brackets)
if (f->type == CPP_HEADER_NAME)
search_start = CPP_OPTION (pfile, bracket_include);
else if (CPP_OPTION (pfile, ignore_srcdir))
search_start = CPP_OPTION (pfile, quote_include);
@ -687,7 +690,7 @@ _cpp_compare_file_date (pfile, f, len, angle_brackets)
search_start = CPP_BUFFER (pfile)->actual_dir;
fname = alloca (len + 1);
memcpy (fname, f, len);
memcpy (fname, f->val.str.text, len);
fname[len] = '\0';
inc = find_include_file (pfile, fname, search_start);
@ -699,7 +702,7 @@ _cpp_compare_file_date (pfile, f, len, angle_brackets)
inc->fd = -1;
}
return inc->st.st_mtime > current_include->st.st_mtime;
return inc->st.st_mtime > CPP_BUFFER (pfile)->inc->st.st_mtime;
}
@ -723,6 +726,10 @@ cpp_read_file (pfile, fname)
return 0;
}
/* Return success for zero-length files. */
if (DO_NOT_REREAD (f))
return 1;
return stack_include_file (pfile, f);
}
@ -739,14 +746,19 @@ _cpp_pop_file_buffer (pfile, buf)
pfile->system_include_depth--;
if (pfile->include_depth)
pfile->include_depth--;
if (pfile->potential_control_macro)
{
if (inc->cmacro != NEVER_REREAD)
inc->cmacro = pfile->potential_control_macro;
pfile->potential_control_macro = 0;
}
pfile->input_stack_listing_current = 0;
/* Record the inclusion-preventing macro and its definedness. */
if (pfile->mi_state == MI_OUTSIDE && inc->cmacro != NEVER_REREAD)
{
/* This could be NULL meaning no controlling macro. */
inc->cmacro = pfile->mi_cmacro;
inc->defined = 1;
}
/* Invalidate control macros in the #including file. */
pfile->mi_state = MI_FAILED;
inc->refcnt--;
if (inc->refcnt == 0 && DO_NOT_REREAD (inc))
purge_cache (inc);

View File

@ -49,7 +49,7 @@ static unsigned long higher_prime_number PARAMS ((unsigned long));
/* Set up and tear down internal structures for macro expansion. */
void
_cpp_init_macros (pfile)
_cpp_init_hashtable (pfile)
cpp_reader *pfile;
{
pfile->hash_ob = xnew (struct obstack);
@ -63,7 +63,7 @@ _cpp_init_macros (pfile)
}
void
_cpp_cleanup_macros (pfile)
_cpp_cleanup_hashtable (pfile)
cpp_reader *pfile;
{
cpp_hashnode **p, **limit;
@ -101,29 +101,32 @@ cpp_lookup (pfile, name, len)
size_t n = len;
unsigned int r = 0;
const U_CHAR *str = name;
U_CHAR *dest = _cpp_pool_reserve (&pfile->ident_pool, len + 1);
do
{
r = HASHSTEP (r, *str);
str++;
*dest++ = *str++;
}
while (--n);
*dest = '\0';
return _cpp_lookup_with_hash (pfile, name, len, r);
return _cpp_lookup_with_hash (pfile, len, r);
}
/* NAME is a null-terminated identifier of length len. It is assumed
to have been placed at the front of the identifier pool. */
cpp_hashnode *
_cpp_lookup_with_hash (pfile, name, len, hash)
_cpp_lookup_with_hash (pfile, len, hash)
cpp_reader *pfile;
const U_CHAR *name;
size_t len;
unsigned int hash;
{
unsigned int index;
unsigned int hash2;
size_t size;
cpp_hashnode *entry;
cpp_hashnode **entries;
unsigned char *name = POOL_FRONT (&pfile->ident_pool);
entries = pfile->hashtab->entries;
size = pfile->hashtab->size;
@ -132,48 +135,49 @@ _cpp_lookup_with_hash (pfile, name, len, hash)
index = hash % size;
entry = entries[index];
if (entry == NULL)
goto insert;
if (entry->hash == hash && entry->length == len
&& !memcmp (entry->name, name, len))
return entry;
hash2 = 1 + hash % (size - 2);
for (;;)
if (entry)
{
index += hash2;
if (index >= size)
index -= size;
entry = entries[index];
unsigned int hash2;
if (entry == NULL)
goto insert;
if (entry->hash == hash && entry->length == len
&& !memcmp (entry->name, name, len))
return entry;
hash2 = 1 + hash % (size - 2);
for (;;)
{
index += hash2;
if (index >= size)
index -= size;
entry = entries[index];
if (entry == NULL)
break;
if (entry->hash == hash && entry->length == len
&& !memcmp (entry->name, name, len))
return entry;
}
}
insert:
/* Commit the memory for the identifier. */
POOL_COMMIT (&pfile->ident_pool, len + 1);
/* Create a new hash node and insert it in the table. */
entries[index] = obstack_alloc (pfile->hash_ob, sizeof (cpp_hashnode));
entry = entries[index];
entry->type = NT_VOID;
entry->flags = 0;
entry->fe_value = 0;
entry->directive_index = 0;
entry->arg_index = 0;
entry->length = len;
entry->hash = hash;
entry->name = name;
entry->value.macro = 0;
pfile->hashtab->nelts++;
/* Create a new hash node. */
{
U_CHAR *p = obstack_alloc (pfile->hash_ob, sizeof (cpp_hashnode) + len);
entry = (cpp_hashnode *)p;
p += offsetof (cpp_hashnode, name);
entry->type = T_VOID;
entry->fe_value = 0;
entry->length = len;
entry->hash = hash;
entry->value.expansion = NULL;
memcpy (p, name, len);
p[len] = 0;
entries[index] = entry;
}
if (size * 3 <= pfile->hashtab->nelts * 4)
expand_hash (pfile->hashtab);

View File

@ -22,68 +22,30 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef __GCC_CPPHASH__
#define __GCC_CPPHASH__
typedef unsigned char U_CHAR;
#define U (const U_CHAR *) /* Intended use: U"string" */
/* Test if a sign is valid within a preprocessing number. */
#define VALID_SIGN(c, prevc) \
(((c) == '+' || (c) == '-') && \
((prevc) == 'e' || (prevc) == 'E' \
|| (((prevc) == 'p' || (prevc) == 'P') && !CPP_OPTION (pfile, c89))))
/* Tokens with SPELL_STRING store their spelling in the token list,
and it's length in the token->val.name.len. */
enum spell_type
/* Memory pools. */
#define ALIGN(size, align) (((size) + ((align) - 1)) & ~((align) - 1))
#define POOL_FRONT(p) ((p)->cur->front)
#define POOL_LIMIT(p) ((p)->cur->limit)
#define POOL_BASE(p) ((p)->cur->base)
#define POOL_SIZE(p) ((p)->cur->limit - (p)->cur->base)
#define POOL_ROOM(p) ((p)->cur->limit - (p)->cur->front)
#define POOL_USED(p) ((p)->cur->front - (p)->cur->base)
#define POOL_COMMIT(p, len) do {((p)->cur->front += ALIGN (len, (p)->align));\
if ((p)->cur->front > (p)->cur->limit) abort ();} while (0)
typedef struct cpp_chunk cpp_chunk;
struct cpp_chunk
{
SPELL_OPERATOR = 0,
SPELL_CHAR,
SPELL_IDENT,
SPELL_STRING,
SPELL_NONE
};
struct token_spelling
{
enum spell_type category;
const U_CHAR *name;
};
extern const struct token_spelling _cpp_token_spellings[];
#define TOKEN_SPELL(token) (_cpp_token_spellings[(token)->type].category)
#define TOKEN_NAME(token) (_cpp_token_spellings[(token)->type].name)
/* Chained list of answers to an assertion. */
struct answer
{
struct answer *next;
cpp_toklist list;
};
#define FREE_ANSWER(answer) do {_cpp_free_toklist (&answer->list); \
free (answer); } while (0)
/* Values for the origin field of struct directive. KANDR directives
come from traditional (K&R) C. STDC89 directives come from the
1989 C standard. EXTENSION directives are extensions. */
#define KANDR 0
#define STDC89 1
#define EXTENSION 2
/* Values for the flags field of struct directive. COND indicates a
conditional. EXPAND means that macros are to be expanded on the
directive line. INCL means to treat "..." and <...> as
q-char-sequence and h-char-sequence respectively. COMMENTS means
preserve comments in the directive if -C. IN_I means this directive
should be handled even if -fpreprocessed is in effect (these are the
directives with callback hooks). */
#define COND (1 << 0)
#define EXPAND (1 << 1)
#define INCL (1 << 2)
#define COMMENTS (1 << 3)
#define IN_I (1 << 4)
/* Defines one #-directive, including how to handle it. */
typedef void (*directive_handler) PARAMS ((cpp_reader *));
struct directive
{
directive_handler handler; /* Function to handle directive. */
const U_CHAR *name; /* Name of directive. */
unsigned short length; /* Length of name. */
unsigned char origin; /* Origin of directive. */
unsigned char flags; /* Flags describing this directive. */
cpp_chunk *next;
unsigned char *front;
unsigned char *limit;
unsigned char *base;
};
/* List of directories to look for include files in. */
@ -122,28 +84,18 @@ struct include_file
unsigned short refcnt; /* number of stacked buffers using this file */
unsigned char sysp; /* file is a system header */
unsigned char mapped; /* file buffer is mmapped */
unsigned char defined; /* cmacro prevents inclusion in this state */
};
/* The cmacro works like this: If it's NULL, the file is to be
included again. If it's NEVER_REREAD, the file is never to be
included again. Otherwise it is a macro hashnode, and the file is
to be included again if the macro is not defined. */
to be included again if the macro is defined or not as specified by
DEFINED. */
#define NEVER_REREAD ((const cpp_hashnode *)-1)
#define DO_NOT_REREAD(inc) \
((inc)->cmacro && \
((inc)->cmacro == NEVER_REREAD || (inc)->cmacro->type != T_VOID))
/* Special nodes - identifiers with predefined significance.
Note that the array length of dirs[] must be kept in sync with
cpplib.c's dtable[]. */
struct spec_nodes
{
cpp_hashnode *n_L; /* L"str" */
cpp_hashnode *n__STRICT_ANSI__; /* STDC_0_IN_SYSTEM_HEADERS */
cpp_hashnode *n__CHAR_UNSIGNED__; /* plain char is unsigned */
cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */
cpp_hashnode *dirs[19]; /* 19 directives counting #sccs */
};
((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \
|| ((inc)->cmacro->type == NT_MACRO) == (inc)->defined))
/* Character classes.
If the definition of `numchar' looks odd to you, please look up the
@ -200,27 +152,30 @@ extern unsigned char _cpp_trigraph_map[UCHAR_MAX + 1];
/* In cpperror.c */
enum error_type { WARNING = 0, PEDWARN, ERROR, FATAL, ICE };
extern int _cpp_begin_message PARAMS ((cpp_reader *, enum error_type,
const char *, unsigned int,
unsigned int));
const char *, const cpp_lexer_pos *));
/* In cppmacro.c */
extern void _cpp_free_definition PARAMS ((cpp_hashnode *));
extern int _cpp_create_definition PARAMS ((cpp_reader *, cpp_hashnode *));
extern void _cpp_pop_context PARAMS ((cpp_reader *));
extern void _cpp_get_token PARAMS ((cpp_reader *, cpp_token *));
extern void _cpp_free_lookaheads PARAMS ((cpp_reader *));
extern void _cpp_push_token PARAMS ((cpp_reader *, const cpp_token *,
const cpp_lexer_pos *));
/* In cpphash.c */
extern void _cpp_init_macros PARAMS ((cpp_reader *));
extern void _cpp_cleanup_macros PARAMS ((cpp_reader *));
extern cpp_hashnode *_cpp_lookup_with_hash PARAMS ((cpp_reader*, const U_CHAR *,
size_t, unsigned int));
extern void _cpp_init_hashtable PARAMS ((cpp_reader *));
extern void _cpp_cleanup_hashtable PARAMS ((cpp_reader *));
extern cpp_hashnode *_cpp_lookup_with_hash PARAMS ((cpp_reader*, size_t,
unsigned int));
/* In cppfiles.c */
extern void _cpp_simplify_pathname PARAMS ((char *));
extern void _cpp_execute_include PARAMS ((cpp_reader *, const U_CHAR *,
unsigned int, int,
struct file_name_list *,
int));
extern int _cpp_compare_file_date PARAMS ((cpp_reader *, const U_CHAR *,
unsigned int, int));
extern void _cpp_execute_include PARAMS ((cpp_reader *,
const cpp_token *, int,
struct file_name_list *));
extern int _cpp_compare_file_date PARAMS ((cpp_reader *,
const cpp_token *));
extern void _cpp_report_missing_guards PARAMS ((cpp_reader *));
extern void _cpp_init_includes PARAMS ((cpp_reader *));
extern void _cpp_cleanup_includes PARAMS ((cpp_reader *));
@ -231,113 +186,33 @@ extern void _cpp_pop_file_buffer PARAMS ((cpp_reader *, cpp_buffer *));
extern int _cpp_parse_expr PARAMS ((cpp_reader *));
/* In cpplex.c */
extern const unsigned char *_cpp_digraph_spellings[];
extern void _cpp_skip_rest_of_line PARAMS ((cpp_reader *));
extern void _cpp_free_temp_tokens PARAMS ((cpp_reader *));
extern void _cpp_init_input_buffer PARAMS ((cpp_reader *));
extern void _cpp_grow_token_buffer PARAMS ((cpp_reader *, long));
extern void _cpp_init_toklist PARAMS ((cpp_toklist *, int));
extern void _cpp_clear_toklist PARAMS ((cpp_toklist *));
extern void _cpp_free_toklist PARAMS ((const cpp_toklist *));
extern void _cpp_lex_token PARAMS ((cpp_reader *, cpp_token *));
extern int _cpp_equiv_tokens PARAMS ((const cpp_token *,
const cpp_token *));
extern int _cpp_equiv_toklists PARAMS ((const cpp_toklist *,
const cpp_toklist *));
extern void _cpp_expand_token_space PARAMS ((cpp_toklist *, unsigned int));
extern void _cpp_reserve_name_space PARAMS ((cpp_toklist *, unsigned int));
extern void _cpp_expand_name_space PARAMS ((cpp_toklist *, unsigned int));
extern int _cpp_equiv_tokens PARAMS ((const cpp_token *,
const cpp_token *));
extern void _cpp_process_directive PARAMS ((cpp_reader *, const cpp_token *));
extern void _cpp_run_directive PARAMS ((cpp_reader *,
const struct directive *,
const char *, size_t,
const char *));
extern unsigned int _cpp_get_line PARAMS ((cpp_reader *,
unsigned int *));
extern const cpp_token *_cpp_get_token PARAMS ((cpp_reader *));
extern const cpp_token *_cpp_get_raw_token PARAMS ((cpp_reader *));
extern void _cpp_push_token PARAMS ((cpp_reader *, const cpp_token*));
extern const cpp_token *_cpp_glue_header_name PARAMS ((cpp_reader *));
extern enum cpp_ttype _cpp_can_paste PARAMS ((cpp_reader *, const cpp_token *,
const cpp_token *, int *));
extern void _cpp_init_pool PARAMS ((cpp_pool *, unsigned int,
unsigned int, unsigned int));
extern void _cpp_free_pool PARAMS ((cpp_pool *));
extern unsigned char *_cpp_pool_reserve PARAMS ((cpp_pool *, unsigned int));
extern unsigned char *_cpp_pool_alloc PARAMS ((cpp_pool *, unsigned int));
extern unsigned char *_cpp_next_chunk PARAMS ((cpp_pool *, unsigned int,
unsigned char **));
extern void _cpp_lock_pool PARAMS ((cpp_pool *));
extern void _cpp_unlock_pool PARAMS ((cpp_pool *));
/* In cpplib.c */
extern const struct directive *_cpp_check_directive
PARAMS ((cpp_reader *, const cpp_token *));
extern const struct directive *_cpp_check_linemarker
PARAMS ((cpp_reader *, const cpp_token *));
extern cpp_hashnode *_cpp_parse_assertion PARAMS ((cpp_reader *,
struct answer **));
extern struct answer **_cpp_find_answer PARAMS ((cpp_hashnode *,
const cpp_toklist *));
extern void _cpp_define_builtin PARAMS ((cpp_reader *, const char *));
extern int _cpp_test_assertion PARAMS ((cpp_reader *, int *));
extern int _cpp_handle_directive PARAMS ((cpp_reader *, int));
extern void _cpp_define_builtin PARAMS ((cpp_reader *, const char *));
extern void _cpp_init_stacks PARAMS ((cpp_reader *));
extern void _cpp_cleanup_stacks PARAMS ((cpp_reader *));
extern void _cpp_init_internal_pragmas PARAMS ((cpp_reader *));
/* Utility routines and macros. */
#define DSC(str) (const U_CHAR *)str, sizeof str - 1
#define xnew(T) (T *) xmalloc (sizeof(T))
#define xcnew(T) (T *) xcalloc (1, sizeof(T))
#define xnewvec(T, N) (T *) xmalloc (sizeof(T) * (N))
#define xcnewvec(T, N) (T *) xcalloc (N, sizeof(T))
#define xobnew(O, T) (T *) obstack_alloc (O, sizeof(T))
/* These are inline functions instead of macros so we can get type
checking. */
static inline int ustrcmp PARAMS ((const U_CHAR *, const U_CHAR *));
static inline int ustrncmp PARAMS ((const U_CHAR *, const U_CHAR *,
size_t));
static inline size_t ustrlen PARAMS ((const U_CHAR *));
static inline U_CHAR *uxstrdup PARAMS ((const U_CHAR *));
static inline U_CHAR *ustrchr PARAMS ((const U_CHAR *, int));
static inline int ufputs PARAMS ((const U_CHAR *, FILE *));
static inline int
ustrcmp (s1, s2)
const U_CHAR *s1, *s2;
{
return strcmp ((const char *)s1, (const char *)s2);
}
static inline int
ustrncmp (s1, s2, n)
const U_CHAR *s1, *s2;
size_t n;
{
return strncmp ((const char *)s1, (const char *)s2, n);
}
static inline size_t
ustrlen (s1)
const U_CHAR *s1;
{
return strlen ((const char *)s1);
}
static inline U_CHAR *
uxstrdup (s1)
const U_CHAR *s1;
{
return (U_CHAR *) xstrdup ((const char *)s1);
}
static inline U_CHAR *
ustrchr (s1, c)
const U_CHAR *s1;
int c;
{
return (U_CHAR *) strchr ((const char *)s1, c);
}
static inline int
ufputs (s, f)
const U_CHAR *s;
FILE *f;
{
return fputs ((const char *)s, f);
}
#endif

View File

@ -427,8 +427,19 @@ void
cpp_reader_init (pfile)
cpp_reader *pfile;
{
struct spec_nodes *s;
memset ((char *) pfile, 0, sizeof (cpp_reader));
/* If cpp_init hasn't been called, generate a fatal error (by hand)
and call it here. */
if (!cpp_init_completed)
{
fputs ("cpp_reader_init: internal error: cpp_init not called.\n", stderr);
pfile->errors = CPP_FATAL_LIMIT;
cpp_init ();
}
CPP_OPTION (pfile, dollars_in_ident) = 1;
CPP_OPTION (pfile, cplusplus_comments) = 1;
CPP_OPTION (pfile, warn_import) = 1;
@ -441,44 +452,45 @@ cpp_reader_init (pfile)
CPP_OPTION (pfile, pending) =
(struct cpp_pending *) xcalloc (1, sizeof (struct cpp_pending));
/* If cpp_init hasn't been called, generate a fatal error (by hand)
and call it here. */
if (!cpp_init_completed)
{
fputs ("cpp_reader_init: internal error: cpp_init not called.\n", stderr);
pfile->errors = CPP_FATAL_LIMIT;
cpp_init ();
}
/* Initialize comment saving state. */
pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
_cpp_init_macros (pfile);
/* Indicate date and time not yet calculated. */
pfile->date.type = CPP_EOF;
/* Initialise the base context. */
pfile->context = &pfile->base_context;
pfile->base_context.macro = 0;
pfile->base_context.prev = pfile->base_context.next = 0;
/* Identifier pool initially 8K. Unaligned, permanent pool. */
_cpp_init_pool (&pfile->ident_pool, 8 * 1024, 1, 0);
/* String and number pool initially 4K. Unaligned, temporary pool. */
_cpp_init_pool (&pfile->temp_string_pool, 4 * 1024, 1, 1);
/* Argument pool initially 8K. Aligned, temporary pool. */
_cpp_init_pool (&pfile->argument_pool, 8 * 1024, 0, 1);
/* Macro pool initially 8K. Aligned, permanent pool. */
_cpp_init_pool (&pfile->macro_pool, 8 * 1024, 0, 0);
/* Start with temporary pool. */
pfile->string_pool = &pfile->temp_string_pool;
_cpp_init_hashtable (pfile);
_cpp_init_stacks (pfile);
_cpp_init_includes (pfile);
_cpp_init_internal_pragmas (pfile);
}
/* Initialize a cpp_printer structure. As a side effect, open the
output file. */
cpp_printer *
cpp_printer_init (pfile, print)
cpp_reader *pfile;
cpp_printer *print;
{
memset (print, '\0', sizeof (cpp_printer));
if (CPP_OPTION (pfile, out_fname) == NULL)
CPP_OPTION (pfile, out_fname) = "";
if (CPP_OPTION (pfile, out_fname)[0] == '\0')
print->outf = stdout;
else
{
print->outf = fopen (CPP_OPTION (pfile, out_fname), "w");
if (! print->outf)
{
cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname));
return NULL;
}
}
return print;
/* Initialize the special nodes. */
s = &pfile->spec_nodes;
s->n_L = cpp_lookup (pfile, DSC("L"));
s->n_defined = cpp_lookup (pfile, DSC("defined"));
s->n__STRICT_ANSI__ = cpp_lookup (pfile, DSC("__STRICT_ANSI__"));
s->n__CHAR_UNSIGNED__ = cpp_lookup (pfile, DSC("__CHAR_UNSIGNED__"));
s->n__VA_ARGS__ = cpp_lookup (pfile, DSC("__VA_ARGS__"));
s->n__VA_ARGS__->flags |= NODE_DIAGNOSTIC;
}
/* Free resources used by PFILE.
@ -487,69 +499,84 @@ void
cpp_cleanup (pfile)
cpp_reader *pfile;
{
struct file_name_list *dir, *next;
struct file_name_list *dir, *dirn;
cpp_context *context, *contextn;
while (CPP_BUFFER (pfile) != NULL)
cpp_pop_buffer (pfile);
if (pfile->macro_buffer)
free ((PTR) pfile->macro_buffer);
if (pfile->deps)
deps_free (pfile->deps);
if (pfile->spec_nodes)
free (pfile->spec_nodes);
_cpp_free_temp_tokens (pfile);
_cpp_cleanup_includes (pfile);
_cpp_cleanup_stacks (pfile);
_cpp_cleanup_macros (pfile);
_cpp_cleanup_hashtable (pfile);
for (dir = CPP_OPTION (pfile, quote_include); dir; dir = next)
_cpp_free_lookaheads (pfile);
_cpp_free_pool (&pfile->ident_pool);
_cpp_free_pool (&pfile->temp_string_pool);
_cpp_free_pool (&pfile->macro_pool);
_cpp_free_pool (&pfile->argument_pool);
for (dir = CPP_OPTION (pfile, quote_include); dir; dir = dirn)
{
next = dir->next;
dirn = dir->next;
free (dir->name);
free (dir);
}
for (context = pfile->base_context.next; context; context = contextn)
{
contextn = context->next;
free (context);
}
}
/* This structure defines one built-in macro. A node of type TYPE will
be entered in the macro hash table under the name NAME, with value
VALUE (if any). If TYPE is T_OPERATOR, the CODE field is used instead.
/* This structure defines one built-in identifier. A node will be
entered in the hash table under the name NAME, with value VALUE (if
any). If flags has OPERATOR, the node's operator field is used; if
flags has BUILTIN the node's builtin field is used.
Two values are not compile time constants, so we tag
them in the FLAGS field instead:
VERS value is the global version_string, quoted
ULP value is the global user_label_prefix
Also, macros with CPLUS set in the flags field are entered only for C++.
*/
Also, macros with CPLUS set in the flags field are entered only for C++. */
struct builtin
{
const U_CHAR *name;
const char *value;
unsigned char code;
unsigned char type;
unsigned char builtin;
unsigned char operator;
unsigned short flags;
unsigned int len;
unsigned short len;
};
#define VERS 0x01
#define ULP 0x02
#define CPLUS 0x04
#define VERS 0x01
#define ULP 0x02
#define CPLUS 0x04
#define BUILTIN 0x08
#define OPERATOR 0x10
#define B(n, t) { U n, 0, 0, t, 0, sizeof n - 1 }
#define C(n, v) { U n, v, 0, T_MACRO, 0, sizeof n - 1 }
#define X(n, f) { U n, 0, 0, T_MACRO, f, sizeof n - 1 }
#define O(n, c, f) { U n, 0, c, T_OPERATOR, f, sizeof n - 1 }
#define B(n, t) { U n, 0, t, 0, BUILTIN, sizeof n - 1 }
#define C(n, v) { U n, v, 0, 0, 0, sizeof n - 1 }
#define X(n, f) { U n, 0, 0, 0, f, sizeof n - 1 }
#define O(n, c, f) { U n, 0, 0, c, OPERATOR | f, sizeof n - 1 }
static const struct builtin builtin_array[] =
{
B("__TIME__", T_TIME),
B("__DATE__", T_DATE),
B("__FILE__", T_FILE),
B("__BASE_FILE__", T_BASE_FILE),
B("__LINE__", T_SPECLINE),
B("__INCLUDE_LEVEL__", T_INCLUDE_LEVEL),
B("__STDC__", T_STDC),
B("__TIME__", BT_TIME),
B("__DATE__", BT_DATE),
B("__FILE__", BT_FILE),
B("__BASE_FILE__", BT_BASE_FILE),
B("__LINE__", BT_SPECLINE),
B("__INCLUDE_LEVEL__", BT_INCLUDE_LEVEL),
B("__STDC__", BT_STDC),
X("__VERSION__", VERS),
X("__USER_LABEL_PREFIX__", ULP),
@ -570,9 +597,8 @@ static const struct builtin builtin_array[] =
/* Named operators known to the preprocessor. These cannot be #defined
and always have their stated meaning. They are treated like normal
string tokens except for the type code and the meaning. Most of them
identifiers except for the type code and the meaning. Most of them
are only for C++ (but see iso646.h). */
O("defined", CPP_DEFINED, 0),
O("and", CPP_AND_AND, CPLUS),
O("and_eq", CPP_AND_EQ, CPLUS),
O("bitand", CPP_AND, CPLUS),
@ -583,7 +609,7 @@ static const struct builtin builtin_array[] =
O("or", CPP_OR_OR, CPLUS),
O("or_eq", CPP_OR_EQ, CPLUS),
O("xor", CPP_XOR, CPLUS),
O("xor_eq", CPP_XOR_EQ, CPLUS),
O("xor_eq", CPP_XOR_EQ, CPLUS)
};
#undef B
#undef C
@ -601,10 +627,25 @@ initialize_builtins (pfile)
for(b = builtin_array; b < builtin_array_end; b++)
{
if (b->flags & CPLUS && ! CPP_OPTION (pfile, cplusplus))
if ((b->flags & CPLUS) && ! CPP_OPTION (pfile, cplusplus))
continue;
if (b->type == T_MACRO)
if (b->flags & (OPERATOR | BUILTIN))
{
cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
if (b->flags & OPERATOR)
{
hp->flags |= NODE_OPERATOR;
hp->value.operator = b->operator;
}
else
{
hp->type = NT_MACRO;
hp->flags |= NODE_BUILTIN;
hp->value.builtin = b->builtin;
}
}
else /* A standard macro of some kind. */
{
const char *val;
char *str;
@ -629,17 +670,13 @@ initialize_builtins (pfile)
_cpp_define_builtin (pfile, str);
}
else
{
cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
hp->type = b->type;
if (b->type == T_OPERATOR)
hp->value.code = b->code;
}
}
}
#undef BUILTIN
#undef OPERATOR
#undef VERS
#undef ULP
#undef CPLUS
#undef builtin_array_end
/* Another subroutine of cpp_start_read. This one sets up to do
@ -799,9 +836,8 @@ initialize_standard_includes (pfile)
*/
int
cpp_start_read (pfile, print, fname)
cpp_start_read (pfile, fname)
cpp_reader *pfile;
cpp_printer *print;
const char *fname;
{
struct pending_option *p, *q;
@ -829,19 +865,6 @@ cpp_start_read (pfile, print, fname)
if (CPP_OPTION (pfile, user_label_prefix) == NULL)
CPP_OPTION (pfile, user_label_prefix) = USER_LABEL_PREFIX;
/* Figure out if we need to save function macro parameter spellings.
We don't use CPP_PEDANTIC() here because that depends on whether
or not the current file is a system header, and there is no
current file yet. */
pfile->save_parameter_spellings =
CPP_OPTION (pfile, pedantic)
|| CPP_OPTION (pfile, debug_output)
|| CPP_OPTION (pfile, dump_macros) == dump_definitions
|| CPP_OPTION (pfile, dump_macros) == dump_only;
/* Set up the tables used by read_and_prescan. */
_cpp_init_input_buffer (pfile);
/* Set up the include search path now. */
if (! CPP_OPTION (pfile, no_standard_includes))
initialize_standard_includes (pfile);
@ -893,13 +916,6 @@ cpp_start_read (pfile, print, fname)
}
pfile->done_initializing = 1;
/* We start at line 1 of the main input file. */
if (print)
{
print->last_fname = CPP_BUFFER (pfile)->nominal_fname;
print->lineno = 1;
}
/* The -imacros files can be scanned now, but the -include files
have to be pushed onto the include stack and processed later,
in the main loop calling cpp_get_token. */
@ -934,9 +950,8 @@ cpp_start_read (pfile, print, fname)
clear macro definitions, such that you could call cpp_start_read
with a new filename to restart processing. */
void
cpp_finish (pfile, print)
cpp_finish (pfile)
cpp_reader *pfile;
cpp_printer *print;
{
if (CPP_BUFFER (pfile))
{
@ -971,15 +986,6 @@ cpp_finish (pfile, print)
}
}
/* Flush any pending output. */
if (print)
{
if (pfile->need_newline)
putc ('\n', print->outf);
if (ferror (print->outf) || fclose (print->outf))
cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname));
}
/* Report on headers that could use multiple include guards. */
if (CPP_OPTION (pfile, print_include_names))
_cpp_report_missing_guards (pfile);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -34,11 +34,21 @@ typedef struct cpp_reader cpp_reader;
#endif
typedef struct cpp_buffer cpp_buffer;
typedef struct cpp_options cpp_options;
typedef struct cpp_printer cpp_printer;
typedef struct cpp_token cpp_token;
typedef struct cpp_toklist cpp_toklist;
typedef struct cpp_string cpp_string;
typedef struct cpp_hashnode cpp_hashnode;
typedef struct cpp_pool cpp_pool;
typedef struct cpp_macro cpp_macro;
typedef struct cpp_lexer_pos cpp_lexer_pos;
typedef struct cpp_lookahead cpp_lookahead;
struct directive; /* These are deliberately incomplete. */
struct answer;
struct cpp_macro;
struct macro_args;
struct cpp_chunk;
struct file_name_map_list;
struct htab;
/* The first two groups, apart from '=', can appear in preprocessor
expressions. This allows a lookup table to be implemented in
@ -114,7 +124,6 @@ typedef struct cpp_hashnode cpp_hashnode;
OP(CPP_SCOPE, "::") \
OP(CPP_DEREF_STAR, "->*") \
OP(CPP_DOT_STAR, ".*") \
OP(CPP_DEFINED, "defined") /* #if */ \
\
TK(CPP_NAME, SPELL_IDENT) /* word */ \
TK(CPP_INT, SPELL_STRING) /* 23 */ \
@ -131,9 +140,10 @@ typedef struct cpp_hashnode cpp_hashnode;
TK(CPP_HEADER_NAME, SPELL_STRING) /* <stdio.h> in #include */ \
\
TK(CPP_COMMENT, SPELL_STRING) /* Only if output comments. */ \
TK(CPP_DHASH, SPELL_NONE) /* The # of a directive. */ \
TK(CPP_MACRO_ARG, SPELL_NONE) /* Macro argument. */ \
TK(CPP_PLACEMARKER, SPELL_NONE) /* Placemarker token. */ \
TK(CPP_EOF, SPELL_NONE) /* End of file. */
OP(CPP_EOF, "EOL") /* End of line or file. */
#define OP(e, s) e,
#define TK(e, s) e,
@ -145,6 +155,10 @@ enum cpp_ttype
#undef OP
#undef TK
/* Multiple-include optimisation. */
enum mi_state {MI_FAILED = 0, MI_OUTSIDE};
enum mi_ind {MI_IND_NONE = 0, MI_IND_NOT};
/* Payload of a NUMBER, FLOAT, STRING, or COMMENT token. */
struct cpp_string
{
@ -154,19 +168,17 @@ struct cpp_string
/* Flags for the cpp_token structure. */
#define PREV_WHITE (1 << 0) /* If whitespace before this token. */
#define BOL (1 << 1) /* Beginning of logical line. */
#define DIGRAPH (1 << 2) /* If it was a digraph. */
#define STRINGIFY_ARG (1 << 3) /* If macro argument to be stringified. */
#define PASTE_LEFT (1 << 4) /* If on LHS of a ## operator. */
#define PASTED (1 << 5) /* The result of a ## operator. */
#define NAMED_OP (1 << 6) /* C++ named operators, also "defined". */
#define DIGRAPH (1 << 1) /* If it was a digraph. */
#define STRINGIFY_ARG (1 << 2) /* If macro argument to be stringified. */
#define PASTE_LEFT (1 << 3) /* If on LHS of a ## operator. */
#define NAMED_OP (1 << 4) /* C++ named operators, also "defined". */
#define NO_EXPAND (1 << 5) /* Do not macro-expand this token. */
#define VARARGS_FIRST STRINGIFY_ARG /* First token of varargs expansion. */
/* A preprocessing token. This has been carefully packed and should
occupy 16 bytes on 32-bit hosts and 24 bytes on 64-bit hosts. */
occupy 12 bytes on 32-bit hosts and 16 bytes on 64-bit hosts. */
struct cpp_token
{
unsigned int line; /* starting line number of this token */
unsigned short col; /* starting column of this token */
ENUM_BITFIELD(cpp_ttype) type : CHAR_BIT; /* token type */
unsigned char flags; /* flags - see above */
@ -180,37 +192,58 @@ struct cpp_token
} val;
};
/* cpp_toklist flags. */
#define VAR_ARGS (1 << 0)
#define BEG_OF_FILE (1 << 1)
struct directive; /* These are deliberately incomplete. */
struct answer;
struct macro_args;
struct cpp_context;
struct cpp_toklist
/* The position of a token in the current file. */
struct cpp_lexer_pos
{
cpp_token *tokens; /* actual tokens as an array */
unsigned int tokens_used; /* tokens used */
unsigned int tokens_cap; /* tokens allocated */
unsigned int line;
unsigned int output_line;
unsigned short col;
};
unsigned char *namebuf; /* names buffer */
unsigned int name_used; /* _bytes_ used */
unsigned int name_cap; /* _bytes_ allocated */
typedef struct cpp_token_with_pos cpp_token_with_pos;
struct cpp_token_with_pos
{
cpp_token token;
cpp_lexer_pos pos;
};
/* If the list represents a directive, this points to it. */
const struct directive *directive;
/* Token lookahead. */
struct cpp_lookahead
{
struct cpp_lookahead *next;
cpp_token_with_pos *tokens;
cpp_lexer_pos pos;
unsigned int cur, count, cap;
};
const char *file; /* in file name */
unsigned int line; /* starting line number */
/* Memory pools. */
struct cpp_pool
{
struct cpp_chunk *cur, *locked;
unsigned char *pos; /* Current position. */
unsigned int align;
unsigned int locks;
};
unsigned short params_len; /* length of macro parameter names. */
typedef struct toklist toklist;
struct toklist
{
cpp_token *first;
cpp_token *limit;
};
short int paramc; /* no. of macro params (-1 = obj-like). */
typedef struct cpp_context cpp_context;
struct cpp_context
{
/* Doubly-linked list. */
cpp_context *next, *prev;
/* Per-list flags, see above */
unsigned short flags;
/* Contexts other than the base context are contiguous tokens.
e.g. macro expansions, expanded argument tokens. */
struct toklist list;
/* For a macro context, these are the macro and its arguments. */
cpp_macro *macro;
};
/* A standalone character. We may want to make it unsigned for the
@ -257,9 +290,6 @@ struct cpp_buffer
char warned_cplusplus_comments;
};
struct file_name_map_list;
struct htab;
/* Maximum nesting of cpp_buffers. We use a static limit, partly for
efficiency, and partly to limit runaway recursion. */
#define CPP_STACK_MAX 200
@ -448,10 +478,6 @@ struct lexer_state
/* Nonzero if first token on line is CPP_HASH. */
unsigned char in_directive;
/* Nonzero if the directive's # was not in the first column. Used
by -Wtraditional. */
unsigned char indented;
/* Nonzero if in a directive that takes angle-bracketed headers. */
unsigned char angled_headers;
@ -459,24 +485,38 @@ struct lexer_state
all directives apart from #define. */
unsigned char save_comments;
/* Nonzero to force the lexer to skip newlines. */
/* If nonzero the lexer skips newlines. Internal to the lexer. */
unsigned char skip_newlines;
/* Nonzero if we're in the subroutine lex_line. */
unsigned char in_lex_line;
/* Nonzero if we're mid-comment. */
unsigned char lexing_comment;
/* Tells parse_number we saw a leading period. */
unsigned char seen_dot;
};
#define IN_DIRECTIVE(pfile) (pfile->state.in_directive)
#define KNOWN_DIRECTIVE(list) (list->directive != 0)
/* Nonzero if lexing __VA_ARGS__ is valid. */
unsigned char va_args_ok;
/* A cpp_reader encapsulates the "state" of a pre-processor run.
/* Nonzero if lexing poisoned identifiers is valid. */
unsigned char poisoned_ok;
/* Nonzero to prevent macro expansion. */
unsigned char prevent_expansion;
/* Nonzero when parsing arguments to a function-like macro. */
unsigned char parsing_args;
};
/* Special nodes - identifiers with predefined significance. */
struct spec_nodes
{
cpp_hashnode *n_L; /* L"str" */
cpp_hashnode *n_defined; /* defined operator */
cpp_hashnode *n__STRICT_ANSI__; /* STDC_0_IN_SYSTEM_HEADERS */
cpp_hashnode *n__CHAR_UNSIGNED__; /* plain char is unsigned */
cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */
};
/* a cpp_reader encapsulates the "state" of a pre-processor run.
Applying cpp_get_token repeatedly yields a stream of pre-processor
tokens. Usually, there is only one cpp_reader object active. */
tokens. Usually, there is only one cpp_reader object active. */
struct cpp_reader
{
@ -486,70 +526,76 @@ struct cpp_reader
/* Lexer state. */
struct lexer_state state;
/* Error counter for exit code */
/* The position of the last lexed token, last lexed directive, and
last macro invocation. */
cpp_lexer_pos lexer_pos;
cpp_lexer_pos macro_pos;
cpp_lexer_pos directive_pos;
/* Memory pools. */
cpp_pool ident_pool; /* For all identifiers, and permanent
numbers and strings. */
cpp_pool temp_string_pool; /* For temporary numbers and strings. */
cpp_pool macro_pool; /* For macro definitions. Permanent. */
cpp_pool argument_pool; /* For macro arguments. Temporary. */
cpp_pool* string_pool; /* Either temp_string_pool or ident_pool. */
/* Context stack. */
struct cpp_context base_context;
struct cpp_context *context;
/* If in_directive, the directive if known. */
const struct directive *directive;
/* Multiple inlcude optimisation. */
enum mi_state mi_state;
enum mi_ind mi_if_not_defined;
unsigned int mi_lexed;
const cpp_hashnode *mi_cmacro;
const cpp_hashnode *mi_ind_cmacro;
/* Token lookahead. */
struct cpp_lookahead *la_read; /* Read from this lookahead. */
struct cpp_lookahead *la_write; /* Write to this lookahead. */
struct cpp_lookahead *la_unused; /* Free store. */
/* Error counter for exit code. */
unsigned int errors;
/* Line and column where a newline was first seen in a string
constant (multi-line strings). */
unsigned int mls_line;
unsigned int mls_column;
cpp_lexer_pos mlstring_pos;
/* Buffer to hold macro definition string. */
unsigned char *macro_buffer;
unsigned int macro_buffer_len;
/* Current depth in #include directives that use <...>. */
unsigned int system_include_depth;
/* Current depth of buffer stack. */
/* Current depth of buffer stack. */
unsigned int buffer_stack_depth;
/* Current depth in #include directives. */
unsigned int include_depth;
/* Hash table of macros and assertions. See cpphash.c */
/* Hash table of macros and assertions. See cpphash.c. */
struct htab *hashtab;
/* Tree of other included files. See cppfiles.c */
/* Tree of other included files. See cppfiles.c. */
struct splay_tree_s *all_include_files;
/* Chain of `actual directory' file_name_list entries,
for "" inclusion. */
/* Chain of `actual directory' file_name_list entries, for ""
inclusion. */
struct file_name_list *actual_dirs;
/* Current maximum length of directory names in the search path
for include files. (Altered as we get more of them.) */
unsigned int max_include_len;
/* Potential controlling macro for the current buffer. This is only
live between the #endif and the end of file, and there can only
be one at a time, so it is per-reader not per-buffer. */
const cpp_hashnode *potential_control_macro;
/* Token list used to store logical lines with new lexer. */
cpp_toklist token_list;
/* Temporary token store. */
cpp_token **temp_tokens;
unsigned int temp_cap;
unsigned int temp_alloced;
unsigned int temp_used;
/* Date and time tokens. Calculated together if either is requested. */
cpp_token *date;
cpp_token *time;
/* The # of a the current directive. It may not be first in line if
we append, and finding it is tedious. */
const cpp_token *first_directive_token;
/* Context stack. Used for macro expansion and for determining
which macros are disabled. */
unsigned int context_cap;
unsigned int cur_context;
unsigned int no_expand_level;
unsigned int paste_level;
struct cpp_context *contexts;
/* Current arguments when scanning arguments. Used for pointer
fix-up. */
struct macro_args *args;
cpp_token date;
cpp_token time;
/* Buffer of -M output. */
struct deps *deps;
@ -572,17 +618,21 @@ struct cpp_reader
void (*leave_file) PARAMS ((cpp_reader *));
void (*rename_file) PARAMS ((cpp_reader *));
void (*include) PARAMS ((cpp_reader *, const unsigned char *,
const unsigned char *, unsigned int, int));
const cpp_token *));
void (*define) PARAMS ((cpp_reader *, cpp_hashnode *));
void (*undef) PARAMS ((cpp_reader *, cpp_hashnode *));
void (*poison) PARAMS ((cpp_reader *));
void (*ident) PARAMS ((cpp_reader *, const unsigned char *, unsigned int));
void (*ident) PARAMS ((cpp_reader *, const cpp_string *));
void (*def_pragma) PARAMS ((cpp_reader *));
} cb;
/* User visible options. */
struct cpp_options opts;
/* Special nodes - identifiers with predefined significance to the
preprocessor. */
struct spec_nodes spec_nodes;
/* Nonzero means we have printed (while error reporting) a list of
containing files that matches the current status. */
unsigned char input_stack_listing_current;
@ -596,28 +646,6 @@ struct cpp_reader
/* True if we are skipping a failed conditional group. */
unsigned char skipping;
/* True if we need to save parameter spellings - only if -pedantic,
or we might need to write out definitions. */
unsigned char save_parameter_spellings;
/* True if output_line_command needs to output a newline. */
unsigned char need_newline;
/* Special nodes - identifiers with predefined significance to the
preprocessor. */
struct spec_nodes *spec_nodes;
};
/* struct cpp_printer encapsulates state used to convert the stream of
tokens coming from cpp_get_token back into a text file. Not
everyone wants to do that, hence we separate the function. */
struct cpp_printer
{
FILE *outf; /* stream to write to */
const char *last_fname; /* previous file name */
unsigned int lineno; /* line currently being written */
};
#define CPP_FATAL_LIMIT 1000
@ -633,28 +661,41 @@ struct cpp_printer
/* Name under which this program was invoked. */
extern const char *progname;
/* The structure of a node in the hash table. The hash table
has entries for all tokens defined by #define commands (type T_MACRO),
plus some special tokens like __LINE__ (these each have their own
type, and the appropriate code is run when that type of node is seen.
It does not contain control words like "#define", which are recognized
by a separate piece of code. */
/* The structure of a node in the hash table. The hash table has
entries for all identifiers: either macros defined by #define
commands (type NT_MACRO), assertions created with #assert
(NT_ASSERTION), or neither of the above (NT_VOID). Builtin macros
like __LINE__ are flagged NODE_BUILTIN. Poisioned identifiers are
flagged NODE_POISONED. NODE_OPERATOR (C++ only) indicates an
identifier that behaves like an operator such as "xor".
NODE_DIAGNOSTIC is for speed in lex_token: it indicates a
diagnostic may be required for this node. Currently this only
applies to __VA_ARGS__ and poisoned identifiers. */
/* different flavors of hash nodes */
/* Hash node flags. */
#define NODE_OPERATOR (1 << 0) /* C++ named operator. */
#define NODE_POISONED (1 << 1) /* Poisoned identifier. */
#define NODE_BUILTIN (1 << 2) /* Builtin macro. */
#define NODE_DIAGNOSTIC (1 << 3) /* Possible diagnostic when lexed. */
/* Different flavors of hash node. */
enum node_type
{
T_VOID = 0, /* no definition yet */
T_SPECLINE, /* `__LINE__' */
T_DATE, /* `__DATE__' */
T_FILE, /* `__FILE__' */
T_BASE_FILE, /* `__BASE_FILE__' */
T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
T_TIME, /* `__TIME__' */
T_STDC, /* `__STDC__' */
T_OPERATOR, /* operator with a name; val.code is token type */
T_POISON, /* poisoned identifier */
T_MACRO, /* a macro, either object-like or function-like */
T_ASSERTION /* predicate for #assert */
NT_VOID = 0, /* No definition yet. */
NT_MACRO, /* A macro of some form. */
NT_ASSERTION /* Predicate for #assert. */
};
/* Different flavors of builtin macro. */
enum builtin_type
{
BT_SPECLINE = 0, /* `__LINE__' */
BT_DATE, /* `__DATE__' */
BT_FILE, /* `__FILE__' */
BT_BASE_FILE, /* `__BASE_FILE__' */
BT_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
BT_TIME, /* `__TIME__' */
BT_STDC /* `__STDC__' */
};
/* There is a slot in the hashnode for use by front ends when integrated
@ -665,47 +706,56 @@ union tree_node;
struct cpp_hashnode
{
const unsigned char *name; /* null-terminated name */
unsigned int hash; /* cached hash value */
unsigned short length; /* length of name */
ENUM_BITFIELD(node_type) type : 8; /* node type */
unsigned short length; /* length of name excluding null */
unsigned short arg_index; /* macro argument index */
unsigned char directive_index; /* index into directive table. */
ENUM_BITFIELD(node_type) type : 8; /* node type. */
unsigned char flags; /* node flags. */
union
{
const cpp_toklist *expansion; /* a macro's replacement list. */
cpp_macro *macro; /* a macro. */
struct answer *answers; /* answers to an assertion. */
enum cpp_ttype code; /* code for a named operator. */
enum cpp_ttype operator; /* code for a named operator. */
enum builtin_type builtin; /* code for a builtin macro. */
} value;
union tree_node *fe_value; /* front end value */
const unsigned char name[1]; /* name[length] */
};
extern unsigned int cpp_token_len PARAMS ((const cpp_token *));
extern unsigned char *cpp_token_as_text PARAMS ((cpp_reader *, const cpp_token *));
extern unsigned char *cpp_spell_token PARAMS ((cpp_reader *, const cpp_token *,
unsigned char *));
extern void cpp_init PARAMS ((void));
extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **));
extern int cpp_handle_option PARAMS ((cpp_reader *, int, char **));
extern void cpp_reader_init PARAMS ((cpp_reader *));
extern cpp_printer *cpp_printer_init PARAMS ((cpp_reader *, cpp_printer *));
extern void cpp_register_pragma PARAMS ((cpp_reader *,
const char *, const char *,
void (*) PARAMS ((cpp_reader *))));
extern void cpp_register_pragma_space PARAMS ((cpp_reader *, const char *));
extern int cpp_start_read PARAMS ((cpp_reader *, cpp_printer *, const char *));
extern void cpp_output_tokens PARAMS ((cpp_reader *, cpp_printer *,
unsigned int));
extern void cpp_finish PARAMS ((cpp_reader *, cpp_printer *));
extern int cpp_start_read PARAMS ((cpp_reader *, const char *));
extern void cpp_finish PARAMS ((cpp_reader *));
extern void cpp_cleanup PARAMS ((cpp_reader *));
extern const cpp_token *cpp_get_token PARAMS ((cpp_reader *));
extern int cpp_avoid_paste PARAMS ((cpp_reader *, const cpp_token *,
const cpp_token *));
extern enum cpp_ttype cpp_can_paste PARAMS ((cpp_reader *, const cpp_token *,
const cpp_token *, int *));
extern void cpp_get_token PARAMS ((cpp_reader *, cpp_token *));
extern const cpp_lexer_pos *cpp_get_line PARAMS ((cpp_reader *));
extern const unsigned char *cpp_macro_definition PARAMS ((cpp_reader *,
const cpp_hashnode *));
extern void cpp_define PARAMS ((cpp_reader *, const char *));
extern void cpp_assert PARAMS ((cpp_reader *, const char *));
extern void cpp_undef PARAMS ((cpp_reader *, const char *));
extern void cpp_unassert PARAMS ((cpp_reader *, const char *));
extern void cpp_free_token_list PARAMS ((cpp_toklist *));
extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *,
const unsigned char *, long));
extern cpp_buffer *cpp_pop_buffer PARAMS ((cpp_reader *));
@ -740,32 +790,23 @@ extern void cpp_pedwarn_with_file_and_line PARAMS ((cpp_reader *, const char *,
extern void cpp_error_from_errno PARAMS ((cpp_reader *, const char *));
extern void cpp_notice_from_errno PARAMS ((cpp_reader *, const char *));
extern const char *cpp_type2name PARAMS ((enum cpp_ttype));
/* In cpplex.c */
extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *,
const unsigned char *, long));
extern cpp_buffer *cpp_pop_buffer PARAMS ((cpp_reader *));
extern void cpp_scan_buffer PARAMS ((cpp_reader *, cpp_printer *));
extern void cpp_scan_buffer_nooutput PARAMS ((cpp_reader *));
extern int cpp_ideq PARAMS ((const cpp_token *,
const char *));
extern void cpp_printf PARAMS ((cpp_reader *, cpp_printer *,
const char *, ...));
extern void cpp_output_list PARAMS ((cpp_reader *, FILE *,
const cpp_toklist *,
const cpp_token *));
extern void cpp_output_line PARAMS ((cpp_reader *, FILE *));
extern void cpp_output_token PARAMS ((const cpp_token *, FILE *));
extern const char *cpp_type2name PARAMS ((enum cpp_ttype));
/* In cpphash.c */
extern cpp_hashnode *cpp_lookup PARAMS ((cpp_reader *,
const unsigned char *, size_t));
extern void cpp_forall_identifiers PARAMS ((cpp_reader *,
int (*) PARAMS ((cpp_reader *,
cpp_hashnode *))));
extern cpp_hashnode *cpp_lookup PARAMS ((cpp_reader *,
const unsigned char *, size_t));
extern void cpp_forall_identifiers PARAMS ((cpp_reader *,
int (*) PARAMS ((cpp_reader *,
cpp_hashnode *))));
/* In cppmacro.c */
extern void cpp_dump_definition PARAMS ((cpp_reader *, FILE *,
const cpp_hashnode *));
extern void cpp_scan_buffer_nooutput PARAMS ((cpp_reader *));
extern void cpp_start_lookahead PARAMS ((cpp_reader *));
extern void cpp_stop_lookahead PARAMS ((cpp_reader *, int));
/* In cppfiles.c */
extern int cpp_included PARAMS ((cpp_reader *, const char *));
@ -773,6 +814,64 @@ extern int cpp_read_file PARAMS ((cpp_reader *, const char *));
extern void cpp_make_system_header PARAMS ((cpp_reader *, cpp_buffer *, int));
extern const char *cpp_syshdr_flags PARAMS ((cpp_reader *, cpp_buffer *));
/* These are inline functions instead of macros so we can get type
checking. */
typedef unsigned char U_CHAR;
#define U (const U_CHAR *) /* Intended use: U"string" */
static inline int ustrcmp PARAMS ((const U_CHAR *, const U_CHAR *));
static inline int ustrncmp PARAMS ((const U_CHAR *, const U_CHAR *,
size_t));
static inline size_t ustrlen PARAMS ((const U_CHAR *));
static inline U_CHAR *uxstrdup PARAMS ((const U_CHAR *));
static inline U_CHAR *ustrchr PARAMS ((const U_CHAR *, int));
static inline int ufputs PARAMS ((const U_CHAR *, FILE *));
static inline int
ustrcmp (s1, s2)
const U_CHAR *s1, *s2;
{
return strcmp ((const char *)s1, (const char *)s2);
}
static inline int
ustrncmp (s1, s2, n)
const U_CHAR *s1, *s2;
size_t n;
{
return strncmp ((const char *)s1, (const char *)s2, n);
}
static inline size_t
ustrlen (s1)
const U_CHAR *s1;
{
return strlen ((const char *)s1);
}
static inline U_CHAR *
uxstrdup (s1)
const U_CHAR *s1;
{
return (U_CHAR *) xstrdup ((const char *)s1);
}
static inline U_CHAR *
ustrchr (s1, c)
const U_CHAR *s1;
int c;
{
return (U_CHAR *) strchr ((const char *)s1, c);
}
static inline int
ufputs (s, f)
const U_CHAR *s;
FILE *f;
{
return fputs ((const char *)s, f);
}
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -25,29 +25,45 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "cpplib.h"
#include "intl.h"
const char *progname;
cpp_reader parse_in;
cpp_printer parse_out;
/* Encapsulates state used to convert the stream of tokens coming from
cpp_get_token back into a text file. */
struct printer
{
FILE *outf; /* stream to write to. */
const char *last_fname; /* previous file name. */
const char *syshdr_flags; /* system header flags, if any. */
unsigned int lineno; /* line currently being written. */
unsigned char printed; /* nonzero if something output at lineno. */
unsigned char no_line_dirs; /* nonzero to output no line directives. */
};
int main PARAMS ((int, char **));
/* General output routines. */
static void scan_buffer PARAMS ((cpp_reader *));
static int printer_init PARAMS ((cpp_reader *));
static int dump_macro PARAMS ((cpp_reader *, cpp_hashnode *));
static void print_line PARAMS ((const char *));
static void maybe_print_line PARAMS ((unsigned int));
static void move_printer PARAMS ((cpp_reader *, unsigned int, const char *));
/* Callback routines for the parser. Most of these are active only
in specific modes. */
static void cb_define PARAMS ((cpp_reader *, cpp_hashnode *));
static void cb_undef PARAMS ((cpp_reader *, cpp_hashnode *));
static void cb_include PARAMS ((cpp_reader *, const unsigned char *,
const unsigned char *, unsigned int, int));
static void cb_ident PARAMS ((cpp_reader *, const unsigned char *,
unsigned int));
const cpp_token *));
static void cb_ident PARAMS ((cpp_reader *, const cpp_string *));
static void cb_enter_file PARAMS ((cpp_reader *));
static void cb_leave_file PARAMS ((cpp_reader *));
static void cb_rename_file PARAMS ((cpp_reader *));
static void cb_def_pragma PARAMS ((cpp_reader *));
static void do_pragma_implementation PARAMS ((cpp_reader *));
static int dump_macros_helper PARAMS ((cpp_reader *, cpp_hashnode *));
const char *progname;
cpp_reader parse_in;
struct printer print;
int
main (argc, argv)
@ -56,7 +72,6 @@ main (argc, argv)
{
char *p;
cpp_reader *pfile = &parse_in;
cpp_printer *print;
int argi = 1; /* Next argument to handle. */
p = argv[0] + strlen (argv[0]);
@ -83,8 +98,7 @@ main (argc, argv)
/* Open the output now. We must do so even if no_output is on,
because there may be other output than from the actual
preprocessing (e.g. from -dM). */
print = cpp_printer_init (pfile, &parse_out);
if (! print)
if (printer_init (pfile))
return (FATAL_EXIT_CODE);
/* Set callbacks. */
@ -116,134 +130,260 @@ main (argc, argv)
cpp_register_pragma(pfile, 0, "implementation", do_pragma_implementation);
cpp_register_pragma(pfile, "GCC", "implementation", do_pragma_implementation);
if (! cpp_start_read (pfile, print, CPP_OPTION (pfile, in_fname)))
if (! cpp_start_read (pfile, CPP_OPTION (pfile, in_fname)))
return (FATAL_EXIT_CODE);
if (CPP_OPTION (pfile, no_output))
while (CPP_BUFFER (pfile) != NULL)
cpp_scan_buffer_nooutput (pfile);
else
while (CPP_BUFFER (pfile) != NULL)
cpp_scan_buffer (pfile, print);
if (CPP_BUFFER (pfile))
{
if (CPP_OPTION (pfile, no_output))
cpp_scan_buffer_nooutput (pfile);
else
scan_buffer (pfile);
}
/* -dM command line option. */
if (CPP_OPTION (pfile, dump_macros) == dump_only)
cpp_forall_identifiers (pfile, dump_macros_helper);
cpp_finish (pfile, print);
cpp_forall_identifiers (pfile, dump_macro);
cpp_finish (pfile);
cpp_cleanup (pfile);
/* Flush any pending output. */
if (print.printed)
putc ('\n', print.outf);
if (ferror (print.outf) || fclose (print.outf))
cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname));
if (parse_in.errors)
return (FATAL_EXIT_CODE);
return (SUCCESS_EXIT_CODE);
}
/* Writes out the preprocessed file. Alternates between two tokens,
so that we can avoid accidental token pasting. */
static void
scan_buffer (pfile)
cpp_reader *pfile;
{
unsigned int index, line;
cpp_token tokens[2], *token;
do
{
for (index = 0;; index = 1 - index)
{
token = &tokens[index];
cpp_get_token (pfile, token);
if (token->type == CPP_EOF)
break;
line = cpp_get_line (pfile)->output_line;
if (print.lineno != line)
{
unsigned int col = cpp_get_line (pfile)->col;
/* Supply enough whitespace to put this token in its original
column. Don't bother trying to reconstruct tabs; we can't
get it right in general, and nothing ought to care. (Yes,
some things do care; the fault lies with them.) */
maybe_print_line (line);
if (col > 1)
{
if (token->flags & PREV_WHITE)
col--;
while (--col)
putc (' ', print.outf);
}
}
else if (print.printed && ! (token->flags & PREV_WHITE)
&& cpp_avoid_paste (pfile, &tokens[1 - index], token))
token->flags |= PREV_WHITE;
cpp_output_token (token, print.outf);
print.printed = 1;
}
}
while (cpp_pop_buffer (pfile) != 0);
}
/* Initialize a cpp_printer structure. As a side effect, open the
output file. */
static int
printer_init (pfile)
cpp_reader *pfile;
{
print.last_fname = 0;
print.lineno = 0;
print.printed = 0;
print.no_line_dirs = CPP_OPTION (pfile, no_line_commands);
if (CPP_OPTION (pfile, out_fname) == NULL)
CPP_OPTION (pfile, out_fname) = "";
if (CPP_OPTION (pfile, out_fname)[0] == '\0')
print.outf = stdout;
else
{
print.outf = fopen (CPP_OPTION (pfile, out_fname), "w");
if (! print.outf)
{
cpp_notice_from_errno (pfile, CPP_OPTION (pfile, out_fname));
return 1;
}
}
return 0;
}
/* Newline-terminate any output line currently in progress. If
appropriate, write the current line number to the output, or pad
with newlines so the output line matches the current line. */
static void
maybe_print_line (line)
unsigned int line;
{
/* End the previous line of text (probably only needed until we get
multi-line tokens fixed). */
if (print.printed)
{
putc ('\n', print.outf);
print.lineno++;
print.printed = 0;
}
if (print.no_line_dirs)
return;
if (line >= print.lineno && line < print.lineno + 8)
{
while (line > print.lineno)
{
putc ('\n', print.outf);
print.lineno++;
}
}
else
{
print.lineno = line;
print_line ("");
}
}
static void
print_line (special_flags)
const char *special_flags;
{
/* End any previous line of text. */
if (print.printed)
putc ('\n', print.outf);
print.printed = 0;
fprintf (print.outf, "# %u \"%s\"%s%s\n",
print.lineno, print.last_fname, special_flags, print.syshdr_flags);
}
static void
move_printer (pfile, line, special_flags)
cpp_reader *pfile;
unsigned int line;
const char *special_flags;
{
print.lineno = line;
print.last_fname = pfile->buffer->nominal_fname;
print.syshdr_flags = cpp_syshdr_flags (pfile, pfile->buffer);
print_line (special_flags);
}
/* Callbacks */
static void
cb_ident (pfile, str, len)
cpp_reader *pfile;
const unsigned char *str;
unsigned int len;
cb_ident (pfile, str)
cpp_reader *pfile ATTRIBUTE_UNUSED;
const cpp_string * str;
{
cpp_printf (pfile, &parse_out, "#ident \"%.*s\"\n", (int) len, str);
parse_out.lineno++;
maybe_print_line (cpp_get_line (pfile)->output_line);
fprintf (print.outf, "#ident \"%.*s\"\n", (int) str->len, str->text);
print.lineno++;
}
static void
cb_define (pfile, hash)
cb_define (pfile, node)
cpp_reader *pfile;
cpp_hashnode *hash;
cpp_hashnode *node;
{
if (pfile->done_initializing)
{
cpp_printf (pfile, &parse_out, "#define %s", hash->name);
maybe_print_line (cpp_get_line (pfile)->output_line);
fprintf (print.outf, "#define %s", node->name);
/* -dD or -g3 command line options. */
if (CPP_OPTION (pfile, debug_output)
|| CPP_OPTION (pfile, dump_macros) == dump_definitions)
cpp_dump_definition (pfile, parse_out.outf, hash);
putc ('\n', parse_out.outf);
parse_out.lineno++;
fputs ((const char *) cpp_macro_definition (pfile, node), print.outf);
putc ('\n', print.outf);
print.lineno++;
}
}
static void
cb_undef (pfile, hash)
cb_undef (pfile, node)
cpp_reader *pfile;
cpp_hashnode *hash;
cpp_hashnode *node;
{
if (pfile->done_initializing)
{
cpp_printf (pfile, &parse_out, "#undef %s\n", hash->name);
parse_out.lineno++;
maybe_print_line (cpp_get_line (pfile)->output_line);
fprintf (print.outf, "#undef %s\n", node->name);
print.lineno++;
}
}
static void
cb_include (pfile, dir, str, len, ab)
cpp_reader *pfile;
cb_include (pfile, dir, header)
cpp_reader *pfile ATTRIBUTE_UNUSED;
const unsigned char *dir;
const unsigned char *str;
unsigned int len;
int ab;
const cpp_token *header;
{
int l, r;
if (ab)
l = '<', r = '>';
else
l = '"', r = '"';
cpp_printf (pfile, &parse_out, "#%s %c%.*s%c\n", dir, l, (int) len, str, r);
parse_out.lineno++;
maybe_print_line (cpp_get_line (pfile)->output_line);
fprintf (print.outf, "#%s %s\n", dir, cpp_token_as_text (pfile, header));
print.lineno++;
}
static void
cb_enter_file (pfile)
cpp_reader *pfile;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
/* Bring current file to correct line (except main file). FIXME: we
may be using the same buffer via a # NUMBER "file" 1 directive. */
if (pfile->done_initializing && pfile->buffer->prev)
maybe_print_line (pfile->buffer->prev->lineno);
cpp_printf (pfile, &parse_out, "# 1 \"%s\"%s%s\n", ip->nominal_fname,
pfile->done_initializing ? " 1" : "",
cpp_syshdr_flags (pfile, ip));
parse_out.lineno = 1;
parse_out.last_fname = ip->nominal_fname;
move_printer (pfile, 1, pfile->done_initializing ? " 1": "");
}
static void
cb_leave_file (pfile)
cpp_reader *pfile;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
cpp_printf (pfile, &parse_out, "# %u \"%s\" 2%s\n", ip->lineno,
ip->nominal_fname, cpp_syshdr_flags (pfile, ip));
parse_out.lineno = ip->lineno;
parse_out.last_fname = ip->nominal_fname;
move_printer (pfile, pfile->buffer->lineno + 1, " 2");
}
static void
cb_rename_file (pfile)
cpp_reader *pfile;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
cpp_printf (pfile, &parse_out, "# %u \"%s\"%s\n", ip->lineno,
ip->nominal_fname, cpp_syshdr_flags (pfile, ip));
parse_out.lineno = ip->lineno;
parse_out.last_fname = ip->nominal_fname;
move_printer (pfile, pfile->buffer->lineno + 1, "");
}
static void
cb_def_pragma (pfile)
cpp_reader *pfile;
{
cpp_printf (pfile, &parse_out, "#pragma ");
cpp_output_list (pfile, parse_out.outf, &pfile->token_list,
pfile->first_directive_token + 2);
putc ('\n', parse_out.outf);
parse_out.lineno++;
maybe_print_line (cpp_get_line (pfile)->output_line);
fputs ("#pragma ", print.outf);
cpp_output_line (pfile, print.outf);
print.lineno++;
}
static void
@ -252,47 +392,54 @@ do_pragma_implementation (pfile)
{
/* Be quiet about `#pragma implementation' for a file only if it hasn't
been included yet. */
const cpp_token *tok = cpp_get_token (pfile);
char *copy;
cpp_token token;
if (tok->type != CPP_EOF)
cpp_start_lookahead (pfile);
cpp_get_token (pfile, &token);
cpp_stop_lookahead (pfile, 0);
/* If it's not a string, pass it through and let the front end complain. */
if (token.type == CPP_STRING)
{
if (tok->type != CPP_STRING || cpp_get_token (pfile)->type != CPP_EOF)
{
cpp_error (pfile, "malformed #pragma implementation");
return;
}
/* Make a NUL-terminated copy of the string. */
copy = alloca (tok->val.str.len + 1);
memcpy (copy, tok->val.str.text, tok->val.str.len);
copy[tok->val.str.len] = '\0';
if (cpp_included (pfile, copy))
/* Make a NUL-terminated copy of the string. */
char *filename = alloca (token.val.str.len + 1);
memcpy (filename, token.val.str.text, token.val.str.len);
filename[token.val.str.len] = '\0';
if (cpp_included (pfile, filename))
cpp_warning (pfile,
"#pragma implementation for %s appears after file is included",
copy);
"#pragma GCC implementation for \"%s\" appears after file is included",
filename);
}
else if (token.type != CPP_EOF)
{
cpp_error (pfile, "malformed #pragma GCC implementation");
return;
}
/* forward to default-pragma handler. */
/* Output? This is nasty, but we don't have [GCC] implementation in
the buffer. */
if (pfile->cb.def_pragma)
(*pfile->cb.def_pragma) (pfile);
{
maybe_print_line (cpp_get_line (pfile)->output_line);
fputs ("#pragma GCC implementation ", print.outf);
cpp_output_line (pfile, print.outf);
print.lineno++;
}
}
/* Dump out the hash table. */
static int
dump_macros_helper (pfile, hp)
dump_macro (pfile, node)
cpp_reader *pfile;
cpp_hashnode *hp;
cpp_hashnode *node;
{
if (hp->type == T_MACRO)
if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
{
cpp_printf (pfile, &parse_out, "#define %s", hp->name);
cpp_dump_definition (pfile, parse_out.outf, hp);
putc ('\n', parse_out.outf);
parse_out.lineno++;
fprintf (print.outf, "#define %s", node->name);
fputs ((const char *) cpp_macro_definition (pfile, node), print.outf);
putc ('\n', print.outf);
print.lineno++;
}
return 1;
}

View File

@ -1,390 +0,0 @@
/* CPP Library - non-diagnostic output.
Copyright (C) 2000 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
Broken out to separate file, Sep 2000
This program 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 2, or (at your option) any
later version.
This program 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 this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "intl.h"
#include "cpplib.h"
#include "cpphash.h"
static void output_line_command PARAMS ((cpp_reader *, cpp_printer *,
unsigned int));
static void output_token PARAMS ((cpp_reader *, FILE *, const cpp_token *,
const cpp_token *, int));
static void dump_macro_args PARAMS ((FILE *, const cpp_toklist *));
static void dump_param_spelling PARAMS ((FILE *, const cpp_toklist *,
unsigned int));
/* Scan until CPP_BUFFER (PFILE) is exhausted, discarding output. Used
for handling -imacros, -dM, -M and -MM. */
void
cpp_scan_buffer_nooutput (pfile)
cpp_reader *pfile;
{
cpp_buffer *stop = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
const cpp_token *token;
/* In no-output mode, we can ignore everything but directives. */
for (;;)
{
token = _cpp_get_token (pfile);
if (token->type == CPP_EOF)
{
cpp_pop_buffer (pfile);
if (CPP_BUFFER (pfile) == stop)
break;
}
if (token->type == CPP_HASH && token->flags & BOL
&& pfile->token_list.directive)
{
_cpp_process_directive (pfile, token);
continue;
}
_cpp_skip_rest_of_line (pfile);
}
}
/* Scan until CPP_BUFFER (pfile) is exhausted, writing output to PRINT. */
void
cpp_scan_buffer (pfile, print)
cpp_reader *pfile;
cpp_printer *print;
{
cpp_buffer *stop = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
const cpp_token *token, *prev = 0;
for (;;)
{
token = _cpp_get_token (pfile);
if (token->type == CPP_EOF)
{
cpp_pop_buffer (pfile);
if (CPP_BUFFER (pfile) == stop)
return;
prev = 0;
continue;
}
if (token->flags & BOL)
{
output_line_command (pfile, print, token->line);
prev = 0;
if (token->type == CPP_HASH && pfile->token_list.directive)
{
_cpp_process_directive (pfile, token);
continue;
}
}
if (token->type != CPP_PLACEMARKER)
{
output_token (pfile, print->outf, token, prev, 1);
pfile->need_newline = 1;
}
prev = token;
}
}
/* Notify the compiler proper that the current line number has jumped,
or the current file name has changed. */
static void
output_line_command (pfile, print, line)
cpp_reader *pfile;
cpp_printer *print;
unsigned int line;
{
cpp_buffer *ip = CPP_BUFFER (pfile);
if (line == 0)
return;
/* End the previous line of text. */
if (pfile->need_newline)
{
putc ('\n', print->outf);
print->lineno++;
}
pfile->need_newline = 0;
if (CPP_OPTION (pfile, no_line_commands))
return;
/* If the current file has not changed, we can output a few newlines
instead if we want to increase the line number by a small amount.
We cannot do this if print->lineno is zero, because that means we
haven't output any line commands yet. (The very first line
command output is a `same_file' command.)
'nominal_fname' values are unique, so they can be compared by
comparing pointers. */
if (ip->nominal_fname == print->last_fname && print->lineno > 0
&& line >= print->lineno && line < print->lineno + 8)
{
while (line > print->lineno)
{
putc ('\n', print->outf);
print->lineno++;
}
return;
}
fprintf (print->outf, "# %u \"%s\"%s\n", line, ip->nominal_fname,
cpp_syshdr_flags (pfile, ip));
print->last_fname = ip->nominal_fname;
print->lineno = line;
}
/* Output all the tokens of LIST, starting at TOKEN, to FP. */
void
cpp_output_list (pfile, fp, list, token)
cpp_reader *pfile;
FILE *fp;
const cpp_toklist *list;
const cpp_token *token;
{
const cpp_token *limit = list->tokens + list->tokens_used;
const cpp_token *prev = 0;
int white = 0;
while (token < limit)
{
/* XXX Find some way we can write macro args from inside
output_token/spell_token. */
if (token->type == CPP_MACRO_ARG)
{
if (white && token->flags & PREV_WHITE)
putc (' ', fp);
if (token->flags & STRINGIFY_ARG)
putc ('#', fp);
dump_param_spelling (fp, list, token->val.aux);
}
else
output_token (pfile, fp, token, prev, white);
if (token->flags & PASTE_LEFT)
fputs (" ##", fp);
prev = token;
token++;
white = 1;
}
}
/* Write the spelling of a token TOKEN, with any appropriate
whitespace before it, to FP. PREV is the previous token, which
is used to determine if we need to shove in an extra space in order
to avoid accidental token paste. If WHITE is 0, do not insert any
leading whitespace. */
static void
output_token (pfile, fp, token, prev, white)
cpp_reader *pfile;
FILE *fp;
const cpp_token *token, *prev;
int white;
{
if (white)
{
int dummy;
if (token->col && (token->flags & BOL))
{
/* Supply enough whitespace to put this token in its original
column. Don't bother trying to reconstruct tabs; we can't
get it right in general, and nothing ought to care. (Yes,
some things do care; the fault lies with them.) */
unsigned int spaces = token->col - 1;
while (spaces--)
putc (' ', fp);
}
else if (token->flags & PREV_WHITE)
putc (' ', fp);
else
/* Check for and prevent accidental token pasting.
In addition to the cases handled by _cpp_can_paste, consider
a + ++b - if there is not a space between the + and ++, it
will be misparsed as a++ + b. But + ## ++ doesn't produce
a valid token. */
if (prev
&& (_cpp_can_paste (pfile, prev, token, &dummy) != CPP_EOF
|| (prev->type == CPP_PLUS && token->type == CPP_PLUS_PLUS)
|| (prev->type == CPP_MINUS && token->type == CPP_MINUS_MINUS)))
putc (' ', fp);
}
switch (TOKEN_SPELL (token))
{
case SPELL_OPERATOR:
{
const unsigned char *spelling;
if (token->flags & DIGRAPH)
spelling = _cpp_digraph_spellings[token->type - CPP_FIRST_DIGRAPH];
else if (token->flags & NAMED_OP)
goto spell_ident;
else
spelling = TOKEN_NAME (token);
ufputs (spelling, fp);
}
break;
case SPELL_IDENT:
spell_ident:
ufputs (token->val.node->name, fp);
break;
case SPELL_STRING:
{
int left, right, tag;
switch (token->type)
{
case CPP_STRING: left = '"'; right = '"'; tag = '\0'; break;
case CPP_WSTRING: left = '"'; right = '"'; tag = 'L'; break;
case CPP_OSTRING: left = '"'; right = '"'; tag = '@'; break;
case CPP_CHAR: left = '\''; right = '\''; tag = '\0'; break;
case CPP_WCHAR: left = '\''; right = '\''; tag = 'L'; break;
case CPP_HEADER_NAME: left = '<'; right = '>'; tag = '\0'; break;
default: left = '\0'; right = '\0'; tag = '\0'; break;
}
if (tag) putc (tag, fp);
if (left) putc (left, fp);
fwrite (token->val.str.text, 1, token->val.str.len, fp);
if (right) putc (right, fp);
}
break;
case SPELL_CHAR:
putc (token->val.aux, fp);
break;
case SPELL_NONE:
/* Placemarker or EOF - no output. (Macro args are handled
elsewhere. */
break;
}
}
/* Dump the original user's spelling of argument index ARG_NO to the
macro whose expansion is LIST. */
static void
dump_param_spelling (fp, list, arg_no)
FILE *fp;
const cpp_toklist *list;
unsigned int arg_no;
{
const U_CHAR *param = list->namebuf;
while (arg_no--)
param += ustrlen (param) + 1;
ufputs (param, fp);
}
/* Dump the definition of macro MACRO on FP. The format is suitable
to be read back in again. Caller is expected to generate the
"#define NAME" bit. */
void
cpp_dump_definition (pfile, fp, hp)
cpp_reader *pfile;
FILE *fp;
const cpp_hashnode *hp;
{
const cpp_toklist *list = hp->value.expansion;
if (hp->type != T_MACRO)
{
cpp_ice (pfile, "invalid hash type %d in dump_definition", hp->type);
return;
}
if (list->paramc >= 0)
dump_macro_args (fp, list);
putc (' ', fp);
cpp_output_list (pfile, fp, list, list->tokens);
}
static void
dump_macro_args (fp, list)
FILE *fp;
const cpp_toklist *list;
{
int i;
const U_CHAR *param = list->namebuf;
putc ('(', fp);
for (i = 0; i++ < list->paramc;)
{
unsigned int len;
len = ustrlen (param);
if (!(list->flags & VAR_ARGS) || ustrcmp (param, U"__VA_ARGS__"))
ufputs (param, fp);
if (i < list->paramc)
fputs (", ", fp);
else if (list->flags & VAR_ARGS)
fputs ("...", fp);
param += len + 1;
}
putc (')', fp);
}
/* Like fprintf, but writes to a printer object. You should be sure
always to generate a complete line when you use this function. */
void
cpp_printf VPARAMS ((cpp_reader *pfile, cpp_printer *print,
const char *fmt, ...))
{
va_list ap;
#ifndef ANSI_PROTOTYPES
cpp_reader *pfile;
cpp_printer *print;
const char *fmt;
#endif
VA_START (ap, fmt);
#ifndef ANSI_PROTOTYPES
pfile = va_arg (ap, cpp_reader *);
print = va_arg (ap, cpp_printer *);
fmt = va_arg (ap, const char *);
#endif
/* End the previous line of text. */
if (pfile->need_newline)
{
putc ('\n', print->outf);
print->lineno++;
}
pfile->need_newline = 0;
vfprintf (print->outf, fmt, ap);
va_end (ap);
}

View File

@ -517,8 +517,9 @@ recognized_extern (name)
'f' for other function declarations. */
void
recognized_function (fname, kind, have_arg_list, file_seen)
recognized_function (fname, line, kind, have_arg_list, file_seen)
const cpp_token *fname;
unsigned int line;
int kind; /* One of 'f' 'F' or 'I' */
int have_arg_list;
const char *file_seen;
@ -566,7 +567,7 @@ recognized_function (fname, kind, have_arg_list, file_seen)
partial_count++;
partial = (struct partial_proto *)
obstack_alloc (&scan_file_obstack, sizeof (struct partial_proto));
partial->line_seen = fname->line;
partial->line_seen = line;
partial->fn = fn;
fn->partial = partial;
partial->next = partial_proto_list;
@ -622,7 +623,7 @@ read_scan_file (in_fname, argc, argv)
if (CPP_FATAL_ERRORS (&scan_in))
exit (FATAL_EXIT_CODE);
if (! cpp_start_read (&scan_in, 0, in_fname))
if (! cpp_start_read (&scan_in, in_fname))
exit (FATAL_EXIT_CODE);
/* We are scanning a system header, so mark it as such. */
@ -647,15 +648,16 @@ read_scan_file (in_fname, argc, argv)
/* Scan the macro expansion of "getchar();". */
for (;;)
{
const cpp_token *t = cpp_get_token (&scan_in);
cpp_token t;
if (t->type == CPP_EOF)
cpp_get_token (&scan_in, &t);
if (t.type == CPP_EOF)
{
cpp_pop_buffer (&scan_in);
if (CPP_BUFFER (&scan_in) == buf)
break;
}
else if (cpp_ideq (t, "_filbuf"))
else if (cpp_ideq (&t, "_filbuf"))
seen_filbuf++;
}
if (seen_filbuf)

View File

@ -582,7 +582,6 @@ cpplex.c
cpplib.c
cpplib.h
cppmain.c
cppoutput.c
cppspec.c
#crtstuff.c is part of the GCC library
cse.c

View File

@ -45,7 +45,11 @@ skip_to_closing_brace (pfile)
int nesting = 1;
for (;;)
{
enum cpp_ttype token = cpp_get_token (pfile)->type;
cpp_token tok;
enum cpp_ttype token;
cpp_get_token (pfile, &tok);
token = tok.type;
if (token == CPP_EOF)
break;
if (token == CPP_OPEN_BRACE)
@ -84,17 +88,16 @@ scan_decls (pfile, argc, argv)
char **argv ATTRIBUTE_UNUSED;
{
int saw_extern, saw_inline;
const cpp_token *prev_id;
const cpp_token *token;
cpp_token token, prev_id;
new_statement:
token = cpp_get_token (pfile);
cpp_get_token (pfile, &token);
handle_statement:
current_extern_C = 0;
saw_extern = 0;
saw_inline = 0;
if (token->type == CPP_OPEN_BRACE)
if (token.type == CPP_OPEN_BRACE)
{
/* Pop an 'extern "C"' nesting level, if appropriate. */
if (extern_C_braces_length
@ -103,12 +106,12 @@ scan_decls (pfile, argc, argv)
brace_nesting--;
goto new_statement;
}
if (token->type == CPP_OPEN_BRACE)
if (token.type == CPP_OPEN_BRACE)
{
brace_nesting++;
goto new_statement;
}
if (token->type == CPP_EOF)
if (token.type == CPP_EOF)
{
cpp_pop_buffer (pfile);
if (CPP_BUFFER (pfile) == NULL)
@ -116,15 +119,15 @@ scan_decls (pfile, argc, argv)
goto new_statement;
}
if (token->type == CPP_SEMICOLON)
if (token.type == CPP_SEMICOLON)
goto new_statement;
if (token->type != CPP_NAME)
if (token.type != CPP_NAME)
goto new_statement;
prev_id = 0;
prev_id.type = CPP_EOF;
for (;;)
{
switch (token->type)
switch (token.type)
{
default:
goto handle_statement;
@ -136,11 +139,11 @@ scan_decls (pfile, argc, argv)
case CPP_COMMA:
case CPP_SEMICOLON:
if (prev_id && saw_extern)
if (prev_id.type != CPP_EOF && saw_extern)
{
recognized_extern (prev_id);
recognized_extern (&prev_id);
}
if (token->type == CPP_COMMA)
if (token.type == CPP_COMMA)
break;
/* ... fall through ... */
case CPP_OPEN_BRACE: case CPP_CLOSE_BRACE:
@ -154,60 +157,61 @@ scan_decls (pfile, argc, argv)
case CPP_OPEN_PAREN:
/* Looks like this is the start of a formal parameter list. */
if (prev_id)
if (prev_id.type != CPP_EOF)
{
int nesting = 1;
int have_arg_list = 0;
for (;;)
{
token = cpp_get_token (pfile);
if (token->type == CPP_OPEN_PAREN)
cpp_get_token (pfile, &token);
if (token.type == CPP_OPEN_PAREN)
nesting++;
else if (token->type == CPP_CLOSE_PAREN)
else if (token.type == CPP_CLOSE_PAREN)
{
nesting--;
if (nesting == 0)
break;
}
else if (token->type == CPP_EOF)
else if (token.type == CPP_EOF)
break;
else if (token->type == CPP_NAME
|| token->type == CPP_ELLIPSIS)
else if (token.type == CPP_NAME
|| token.type == CPP_ELLIPSIS)
have_arg_list = 1;
}
recognized_function (prev_id,
recognized_function (&prev_id,
cpp_get_line (pfile)->line,
(saw_inline ? 'I'
: in_extern_C_brace || current_extern_C
? 'F' : 'f'), have_arg_list,
CPP_BUFFER (pfile)->nominal_fname);
token = cpp_get_token (pfile);
if (token->type == CPP_OPEN_BRACE)
cpp_get_token (pfile, &token);
if (token.type == CPP_OPEN_BRACE)
{
/* skip body of (normally) inline function */
skip_to_closing_brace (pfile);
goto new_statement;
}
if (token->type == CPP_SEMICOLON)
if (token.type == CPP_SEMICOLON)
goto new_statement;
}
break;
case CPP_NAME:
/* "inline" and "extern" are recognized but skipped */
if (cpp_ideq (token, "inline"))
if (cpp_ideq (&token, "inline"))
{
saw_inline = 1;
}
else if (cpp_ideq (token, "extern"))
else if (cpp_ideq (&token, "extern"))
{
saw_extern = 1;
token = cpp_get_token (pfile);
if (token->type == CPP_STRING
&& token->val.str.len == 1
&& token->val.str.text[0] == 'C')
cpp_get_token (pfile, &token);
if (token.type == CPP_STRING
&& token.val.str.len == 1
&& token.val.str.text[0] == 'C')
{
current_extern_C = 1;
token = cpp_get_token (pfile);
if (token->type == CPP_OPEN_BRACE)
cpp_get_token (pfile, &token);
if (token.type == CPP_OPEN_BRACE)
{
brace_nesting++;
extern_C_braces[extern_C_braces_length++]
@ -223,6 +227,6 @@ scan_decls (pfile, argc, argv)
prev_id = token;
break;
}
token = cpp_get_token (pfile);
cpp_get_token (pfile, &token);
}
}

View File

@ -60,7 +60,8 @@ extern int scan_ident _PARAMS((FILE *, sstring *, int));
extern int scan_string _PARAMS((FILE *, sstring *, int));
extern int read_upto _PARAMS((FILE *, sstring *, int));
extern unsigned long hash _PARAMS((const char *));
extern void recognized_function _PARAMS((const struct cpp_token *, int, int,
extern void recognized_function _PARAMS((const struct cpp_token *,
unsigned int, int, int,
const char *));
extern void recognized_extern _PARAMS((const struct cpp_token *));
extern unsigned int hashstr _PARAMS((const char *, unsigned int));