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:
parent
de48b52da8
commit
93c80368d9
158
gcc/ChangeLog
158
gcc/ChangeLog
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
187
gcc/cppexp.c
187
gcc/cppexp.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
237
gcc/cpphash.h
237
gcc/cpphash.h
|
@ -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
|
||||
|
|
222
gcc/cppinit.c
222
gcc/cppinit.c
|
@ -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);
|
||||
|
|
2472
gcc/cpplex.c
2472
gcc/cpplex.c
File diff suppressed because it is too large
Load Diff
1470
gcc/cpplib.c
1470
gcc/cpplib.c
File diff suppressed because it is too large
Load Diff
443
gcc/cpplib.h
443
gcc/cpplib.h
|
@ -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
|
||||
|
|
2003
gcc/cppmacro.c
2003
gcc/cppmacro.c
File diff suppressed because it is too large
Load Diff
357
gcc/cppmain.c
357
gcc/cppmain.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
390
gcc/cppoutput.c
390
gcc/cppoutput.c
|
@ -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);
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue