diff options
Diffstat (limited to 'gcc/fortran/cpp.c')
-rw-r--r-- | gcc/fortran/cpp.c | 1203 |
1 files changed, 0 insertions, 1203 deletions
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c deleted file mode 100644 index a655686..0000000 --- a/gcc/fortran/cpp.c +++ /dev/null @@ -1,1203 +0,0 @@ -/* Copyright (C) 2008-2022 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC 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 3, or (at your option) any later -version. - -GCC 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 GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" - -#define GCC_C_COMMON_C -#include "options.h" /* For cpp_reason_option_codes. */ -#undef GCC_C_COMMON_C - -#include "target.h" -#include "gfortran.h" -#include "diagnostic.h" - -#include "toplev.h" - -#include "../../libcpp/internal.h" -#include "cpp.h" -#include "incpath.h" -#include "cppbuiltin.h" -#include "mkdeps.h" - -#ifndef TARGET_SYSTEM_ROOT -# define TARGET_SYSTEM_ROOT NULL -#endif - -#ifndef TARGET_CPU_CPP_BUILTINS -# define TARGET_CPU_CPP_BUILTINS() -#endif - -#ifndef TARGET_OS_CPP_BUILTINS -# define TARGET_OS_CPP_BUILTINS() -#endif - -#ifndef TARGET_OBJFMT_CPP_BUILTINS -# define TARGET_OBJFMT_CPP_BUILTINS() -#endif - - -/* Holds switches parsed by gfc_cpp_handle_option (), but whose - handling is deferred to gfc_cpp_init (). */ -typedef struct -{ - enum opt_code code; - const char *arg; -} -gfc_cpp_deferred_opt_t; - - -/* Defined and undefined macros being queued for output with -dU at - the next newline. */ -typedef struct gfc_cpp_macro_queue -{ - struct gfc_cpp_macro_queue *next; /* Next macro in the list. */ - char *macro; /* The name of the macro if not - defined, the full definition if - defined. */ -} gfc_cpp_macro_queue; -static gfc_cpp_macro_queue *cpp_define_queue, *cpp_undefine_queue; - -struct gfc_cpp_option_data -{ - /* Argument of -cpp, implied by SPEC; - if NULL, preprocessing disabled. */ - const char *temporary_filename; - - const char *output_filename; /* -o <arg> */ - int preprocess_only; /* -E */ - int discard_comments; /* -C */ - int discard_comments_in_macro_exp; /* -CC */ - int print_include_names; /* -H */ - int no_line_commands; /* -P */ - char dump_macros; /* -d[DMNU] */ - int dump_includes; /* -dI */ - int working_directory; /* -fworking-directory */ - int no_predefined; /* -undef */ - int standard_include_paths; /* -nostdinc */ - int verbose; /* -v */ - int deps; /* -M */ - int deps_skip_system; /* -MM */ - const char *deps_filename; /* -M[M]D */ - const char *deps_filename_user; /* -MF <arg> */ - int deps_missing_are_generated; /* -MG */ - int deps_phony; /* -MP */ - int warn_date_time; /* -Wdate-time */ - - const char *multilib; /* -imultilib <dir> */ - const char *prefix; /* -iprefix <dir> */ - const char *sysroot; /* -isysroot <dir> */ - - /* Options whose handling needs to be deferred until the - appropriate cpp-objects are created: - -A predicate=answer - -D <macro>[=<val>] - -U <macro> */ - gfc_cpp_deferred_opt_t *deferred_opt; - int deferred_opt_count; -} -gfc_cpp_option; - -/* Structures used with libcpp: */ -static cpp_options *cpp_option = NULL; -static cpp_reader *cpp_in = NULL; - -/* Encapsulates state used to convert a stream of cpp-tokens into - a text file. */ -static struct -{ - FILE *outf; /* Stream to write to. */ - const cpp_token *prev; /* Previous token. */ - const cpp_token *source; /* Source token for spacing. */ - int src_line; /* Line number currently being written. */ - unsigned char printed; /* Nonzero if something output at line. */ - bool first_time; /* cb_file_change hasn't been called yet. */ -} print; - -/* General output routines. */ -static void scan_translation_unit (cpp_reader *); -static void scan_translation_unit_trad (cpp_reader *); - -/* Callback routines for the parser. Most of these are active only - in specific modes. */ -static void cb_file_change (cpp_reader *, const line_map_ordinary *); -static void cb_line_change (cpp_reader *, const cpp_token *, int); -static void cb_define (cpp_reader *, location_t, cpp_hashnode *); -static void cb_undef (cpp_reader *, location_t, cpp_hashnode *); -static void cb_def_pragma (cpp_reader *, location_t); -static void cb_include (cpp_reader *, location_t, const unsigned char *, - const char *, int, const cpp_token **); -static void cb_ident (cpp_reader *, location_t, const cpp_string *); -static void cb_used_define (cpp_reader *, location_t, cpp_hashnode *); -static void cb_used_undef (cpp_reader *, location_t, cpp_hashnode *); -static bool cb_cpp_diagnostic (cpp_reader *, enum cpp_diagnostic_level, - enum cpp_warning_reason, rich_location *, - const char *, va_list *) - ATTRIBUTE_GCC_DIAG(5,0); -void pp_dir_change (cpp_reader *, const char *); - -static int dump_macro (cpp_reader *, cpp_hashnode *, void *); -static void dump_queued_macros (cpp_reader *); - - -static void -cpp_define_builtins (cpp_reader *pfile) -{ - /* Initialize CPP built-ins; '1' corresponds to 'flag_hosted' - in C, defines __STDC_HOSTED__?! */ - cpp_init_builtins (pfile, 0); - - /* Initialize GFORTRAN specific builtins. - These are documented. */ - define_language_independent_builtin_macros (pfile); - cpp_define (pfile, "__GFORTRAN__=1"); - cpp_define (pfile, "_LANGUAGE_FORTRAN=1"); - - if (flag_openacc) - cpp_define (pfile, "_OPENACC=201711"); - - if (flag_openmp) - cpp_define (pfile, "_OPENMP=201511"); - - /* The defines below are necessary for the TARGET_* macros. - - FIXME: Note that builtin_define_std() actually is a function - in c-cppbuiltin.c which uses flags undefined for Fortran. - Let's skip this for now. If needed, one needs to look into it - once more. */ - -# define builtin_define(TXT) cpp_define (pfile, TXT) -# define builtin_define_std(TXT) -# define builtin_assert(TXT) cpp_assert (pfile, TXT) - - /* FIXME: Pandora's Box - Using the macros below results in multiple breakages: - - mingw will fail to compile this file as dependent macros - assume to be used in c-cppbuiltin.c only. Further, they use - flags only valid/defined in C (same as noted above). - [config/i386/mingw32.h, config/i386/cygming.h] - - other platforms (not as popular) break similarly - [grep for 'builtin_define_with_int_value' in gcc/config/] - - TARGET_CPU_CPP_BUILTINS (); - TARGET_OS_CPP_BUILTINS (); - TARGET_OBJFMT_CPP_BUILTINS (); */ - -#undef builtin_define -#undef builtin_define_std -#undef builtin_assert -} - -bool -gfc_cpp_enabled (void) -{ - return gfc_cpp_option.temporary_filename != NULL; -} - -bool -gfc_cpp_preprocess_only (void) -{ - return gfc_cpp_option.preprocess_only; -} - -bool -gfc_cpp_makedep (void) -{ - return gfc_cpp_option.deps; -} - -void -gfc_cpp_add_dep (const char *name, bool system) -{ - if (!gfc_cpp_option.deps_skip_system || !system) - if (mkdeps *deps = cpp_get_deps (cpp_in)) - deps_add_dep (deps, name); -} - -void -gfc_cpp_add_target (const char *name) -{ - if (mkdeps *deps = cpp_get_deps (cpp_in)) - deps_add_target (deps, name, 0); -} - - -const char * -gfc_cpp_temporary_file (void) -{ - return gfc_cpp_option.temporary_filename; -} - -static void -gfc_cpp_register_include_paths (bool verbose_missing_dir_warn) -{ - int cxx_stdinc = 0; - cpp_get_options (cpp_in)->warn_missing_include_dirs - = (global_options.x_cpp_warn_missing_include_dirs - && verbose_missing_dir_warn); - register_include_chains (cpp_in, gfc_cpp_option.sysroot, - gfc_cpp_option.prefix, gfc_cpp_option.multilib, - gfc_cpp_option.standard_include_paths, cxx_stdinc, - gfc_cpp_option.verbose); -} - -void -gfc_cpp_init_options (unsigned int decoded_options_count, - struct cl_decoded_option *decoded_options ATTRIBUTE_UNUSED) -{ - /* Do not create any objects from libcpp here. If no - preprocessing is requested, this would be wasted - time and effort. - - See gfc_cpp_post_options() instead. */ - - gfc_cpp_option.temporary_filename = NULL; - gfc_cpp_option.output_filename = NULL; - gfc_cpp_option.preprocess_only = 0; - gfc_cpp_option.discard_comments = 1; - gfc_cpp_option.discard_comments_in_macro_exp = 1; - gfc_cpp_option.print_include_names = 0; - gfc_cpp_option.no_line_commands = 0; - gfc_cpp_option.dump_macros = '\0'; - gfc_cpp_option.dump_includes = 0; - gfc_cpp_option.working_directory = -1; - gfc_cpp_option.no_predefined = 0; - gfc_cpp_option.standard_include_paths = 1; - gfc_cpp_option.verbose = 0; - gfc_cpp_option.warn_date_time = 0; - gfc_cpp_option.deps = 0; - gfc_cpp_option.deps_skip_system = 0; - gfc_cpp_option.deps_phony = 0; - gfc_cpp_option.deps_missing_are_generated = 0; - gfc_cpp_option.deps_filename = NULL; - gfc_cpp_option.deps_filename_user = NULL; - - gfc_cpp_option.multilib = NULL; - gfc_cpp_option.prefix = NULL; - gfc_cpp_option.sysroot = TARGET_SYSTEM_ROOT; - - gfc_cpp_option.deferred_opt = XNEWVEC (gfc_cpp_deferred_opt_t, - decoded_options_count); - gfc_cpp_option.deferred_opt_count = 0; -} - -int -gfc_cpp_handle_option (size_t scode, const char *arg, int value ATTRIBUTE_UNUSED) -{ - int result = 1; - enum opt_code code = (enum opt_code) scode; - - switch (code) - { - default: - result = 0; - break; - - case OPT_cpp_: - gfc_cpp_option.temporary_filename = arg; - break; - - case OPT_nocpp: - gfc_cpp_option.temporary_filename = 0L; - break; - - case OPT_d: - for ( ; *arg; ++arg) - switch (*arg) - { - case 'D': - case 'M': - case 'N': - case 'U': - gfc_cpp_option.dump_macros = *arg; - break; - - case 'I': - gfc_cpp_option.dump_includes = 1; - break; - } - break; - - case OPT_fworking_directory: - gfc_cpp_option.working_directory = value; - break; - - case OPT_idirafter: - gfc_cpp_add_include_path_after (xstrdup(arg), true); - break; - - case OPT_imultilib: - gfc_cpp_option.multilib = arg; - break; - - case OPT_iprefix: - gfc_cpp_option.prefix = arg; - break; - - case OPT_isysroot: - gfc_cpp_option.sysroot = arg; - break; - - case OPT_iquote: - case OPT_isystem: - gfc_cpp_add_include_path (xstrdup(arg), true); - break; - - case OPT_nostdinc: - gfc_cpp_option.standard_include_paths = value; - break; - - case OPT_o: - if (!gfc_cpp_option.output_filename) - gfc_cpp_option.output_filename = arg; - else - gfc_fatal_error ("output filename specified twice"); - break; - - case OPT_undef: - gfc_cpp_option.no_predefined = value; - break; - - case OPT_v: - gfc_cpp_option.verbose = value; - break; - - case OPT_Wdate_time: - gfc_cpp_option.warn_date_time = value; - break; - - case OPT_A: - case OPT_D: - case OPT_U: - gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].code = code; - gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].arg = arg; - gfc_cpp_option.deferred_opt_count++; - break; - - case OPT_C: - gfc_cpp_option.discard_comments = 0; - break; - - case OPT_CC: - gfc_cpp_option.discard_comments = 0; - gfc_cpp_option.discard_comments_in_macro_exp = 0; - break; - - case OPT_E: - gfc_cpp_option.preprocess_only = 1; - break; - - case OPT_H: - gfc_cpp_option.print_include_names = 1; - break; - - case OPT_MM: - gfc_cpp_option.deps_skip_system = 1; - /* fall through */ - - case OPT_M: - gfc_cpp_option.deps = 1; - break; - - case OPT_MMD: - gfc_cpp_option.deps_skip_system = 1; - /* fall through */ - - case OPT_MD: - gfc_cpp_option.deps = 1; - gfc_cpp_option.deps_filename = arg; - break; - - case OPT_MF: - /* If specified multiple times, last one wins. */ - gfc_cpp_option.deps_filename_user = arg; - break; - - case OPT_MG: - gfc_cpp_option.deps_missing_are_generated = 1; - break; - - case OPT_MP: - gfc_cpp_option.deps_phony = 1; - break; - - case OPT_MQ: - case OPT_MT: - gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].code = code; - gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].arg = arg; - gfc_cpp_option.deferred_opt_count++; - break; - - case OPT_P: - gfc_cpp_option.no_line_commands = 1; - break; - } - - return result; -} - -/* This function needs to be called before gfc_cpp_register_include_paths - as the latter may diagnose missing include directories. */ -static void -gfc_cpp_init_cb (void) -{ - struct cpp_callbacks *cb; - - cb = cpp_get_callbacks (cpp_in); - cb->file_change = cb_file_change; - cb->line_change = cb_line_change; - cb->ident = cb_ident; - cb->def_pragma = cb_def_pragma; - cb->diagnostic = cb_cpp_diagnostic; - - if (gfc_cpp_option.dump_includes) - cb->include = cb_include; - - if ((gfc_cpp_option.dump_macros == 'D') - || (gfc_cpp_option.dump_macros == 'N')) - { - cb->define = cb_define; - cb->undef = cb_undef; - } - - if (gfc_cpp_option.dump_macros == 'U') - { - cb->before_define = dump_queued_macros; - cb->used_define = cb_used_define; - cb->used_undef = cb_used_undef; - } -} - -void -gfc_cpp_post_options (bool verbose_missing_dir_warn) -{ - /* Any preprocessing-related option without '-cpp' is considered - an error. */ - if (!gfc_cpp_enabled () - && (gfc_cpp_preprocess_only () - || gfc_cpp_makedep () - || !gfc_cpp_option.discard_comments - || !gfc_cpp_option.discard_comments_in_macro_exp - || gfc_cpp_option.print_include_names - || gfc_cpp_option.no_line_commands - || gfc_cpp_option.dump_macros - || gfc_cpp_option.dump_includes)) - gfc_fatal_error ("To enable preprocessing, use %<-cpp%>"); - - if (!gfc_cpp_enabled ()) - return; - - cpp_in = cpp_create_reader (CLK_GNUC89, NULL, line_table); - gcc_assert (cpp_in); - - /* The cpp_options-structure defines far more flags than those set here. - If any other is implemented, see c-opt.c (sanitize_cpp_opts) for - inter-option dependencies that may need to be enforced. */ - cpp_option = cpp_get_options (cpp_in); - gcc_assert (cpp_option); - - /* TODO: allow non-traditional modes, e.g. by -cpp-std=...? */ - cpp_option->traditional = 1; - cpp_option->cplusplus_comments = 0; - - cpp_option->cpp_pedantic = pedantic; - - cpp_option->dollars_in_ident = flag_dollar_ok; - cpp_option->discard_comments = gfc_cpp_option.discard_comments; - cpp_option->discard_comments_in_macro_exp = gfc_cpp_option.discard_comments_in_macro_exp; - cpp_option->print_include_names = gfc_cpp_option.print_include_names; - cpp_option->preprocessed = gfc_option.flag_preprocessed; - cpp_option->warn_date_time = gfc_cpp_option.warn_date_time; - - if (gfc_cpp_makedep ()) - { - cpp_option->deps.style = DEPS_USER; - cpp_option->deps.phony_targets = gfc_cpp_option.deps_phony; - cpp_option->deps.missing_files = gfc_cpp_option.deps_missing_are_generated; - - /* -MF <arg> overrides -M[M]D. */ - if (gfc_cpp_option.deps_filename_user) - gfc_cpp_option.deps_filename = gfc_cpp_option.deps_filename_user; - } - - if (gfc_cpp_option.working_directory == -1) - gfc_cpp_option.working_directory = (debug_info_level != DINFO_LEVEL_NONE); - - cpp_post_options (cpp_in); - - - /* Let diagnostics infrastructure know how to convert input files the same - way libcpp will do it, namely, with no charset conversion but with - skipping of a UTF-8 BOM if present. */ - diagnostic_initialize_input_context (global_dc, nullptr, true); - gfc_cpp_init_cb (); - - gfc_cpp_register_include_paths (verbose_missing_dir_warn); -} - - -void -gfc_cpp_init_0 (void) -{ - /* Initialize the print structure. Setting print.src_line to -1 here is - a trick to guarantee that the first token of the file will cause - a linemarker to be output by maybe_print_line. */ - print.src_line = -1; - print.printed = 0; - print.prev = 0; - print.first_time = 1; - - if (gfc_cpp_preprocess_only ()) - { - if (gfc_cpp_option.output_filename) - { - /* This needs cheating: with "-E -o <file>", the user wants the - preprocessed output in <file>. However, if nothing is done - about it <file> is also used for assembler output. Hence, it - is necessary to redirect assembler output (actually nothing - as -E implies -fsyntax-only) to another file, otherwise the - output from preprocessing is lost. */ - asm_file_name = gfc_cpp_option.temporary_filename; - - print.outf = fopen (gfc_cpp_option.output_filename, "w"); - if (print.outf == NULL) - gfc_fatal_error ("opening output file %qs: %s", - gfc_cpp_option.output_filename, - xstrerror (errno)); - } - else - print.outf = stdout; - } - else - { - print.outf = fopen (gfc_cpp_option.temporary_filename, "w"); - if (print.outf == NULL) - gfc_fatal_error ("opening output file %qs: %s", - gfc_cpp_option.temporary_filename, xstrerror (errno)); - } - - gcc_assert(cpp_in); - if (!cpp_read_main_file (cpp_in, gfc_source_file)) - errorcount++; -} - -void -gfc_cpp_init (void) -{ - int i; - - if (gfc_option.flag_preprocessed) - return; - - cpp_change_file (cpp_in, LC_RENAME, _("<built-in>")); - if (!gfc_cpp_option.no_predefined) - { - /* Make sure all of the builtins about to be declared have - BUILTINS_LOCATION has their location_t. */ - cpp_force_token_locations (cpp_in, BUILTINS_LOCATION); - - cpp_define_builtins (cpp_in); - - cpp_stop_forcing_token_locations (cpp_in); - } - - /* Handle deferred options from command-line. */ - cpp_change_file (cpp_in, LC_RENAME, _("<command-line>")); - - for (i = 0; i < gfc_cpp_option.deferred_opt_count; i++) - { - gfc_cpp_deferred_opt_t *opt = &gfc_cpp_option.deferred_opt[i]; - - if (opt->code == OPT_D) - cpp_define (cpp_in, opt->arg); - else if (opt->code == OPT_U) - cpp_undef (cpp_in, opt->arg); - else if (opt->code == OPT_A) - { - if (opt->arg[0] == '-') - cpp_unassert (cpp_in, opt->arg + 1); - else - cpp_assert (cpp_in, opt->arg); - } - else if (opt->code == OPT_MT || opt->code == OPT_MQ) - if (mkdeps *deps = cpp_get_deps (cpp_in)) - deps_add_target (deps, opt->arg, opt->code == OPT_MQ); - } - - /* Pre-defined macros for non-required INTEGER kind types. */ - for (gfc_integer_info *itype = gfc_integer_kinds; itype->kind != 0; itype++) - { - if (itype->kind == 1) - cpp_define (cpp_in, "__GFC_INT_1__=1"); - if (itype->kind == 2) - cpp_define (cpp_in, "__GFC_INT_2__=1"); - if (itype->kind == 8) - cpp_define (cpp_in, "__GFC_INT_8__=1"); - if (itype->kind == 16) - cpp_define (cpp_in, "__GFC_INT_16__=1"); - } - - /* Pre-defined macros for non-required REAL kind types. */ - for (gfc_real_info *rtype = gfc_real_kinds; rtype->kind != 0; rtype++) - { - if (rtype->kind == 10) - cpp_define (cpp_in, "__GFC_REAL_10__=1"); - if (rtype->kind == 16) - cpp_define (cpp_in, "__GFC_REAL_16__=1"); - } - - if (gfc_cpp_option.working_directory - && gfc_cpp_option.preprocess_only && !gfc_cpp_option.no_line_commands) - pp_dir_change (cpp_in, get_src_pwd ()); -} - -bool -gfc_cpp_preprocess (const char *source_file) -{ - if (!gfc_cpp_enabled ()) - return false; - - cpp_change_file (cpp_in, LC_RENAME, source_file); - - if (cpp_option->traditional) - scan_translation_unit_trad (cpp_in); - else - scan_translation_unit (cpp_in); - - /* -dM command line option. */ - if (gfc_cpp_preprocess_only () && - gfc_cpp_option.dump_macros == 'M') - { - putc ('\n', print.outf); - cpp_forall_identifiers (cpp_in, dump_macro, NULL); - } - - putc ('\n', print.outf); - - if (!gfc_cpp_preprocess_only () - || (gfc_cpp_preprocess_only () && gfc_cpp_option.output_filename)) - fclose (print.outf); - - return true; -} - -void -gfc_cpp_done (void) -{ - if (!gfc_cpp_enabled ()) - return; - - gcc_assert (cpp_in); - - if (gfc_cpp_makedep ()) - { - if (gfc_cpp_option.deps_filename) - { - FILE *f = fopen (gfc_cpp_option.deps_filename, "w"); - if (f) - { - cpp_finish (cpp_in, f); - fclose (f); - } - else - gfc_fatal_error ("opening output file %qs: %s", - gfc_cpp_option.deps_filename, - xstrerror (errno)); - } - else - cpp_finish (cpp_in, stdout); - } - - cpp_undef_all (cpp_in); - cpp_clear_file_cache (cpp_in); -} - -/* PATH must be malloc-ed and NULL-terminated. */ -void -gfc_cpp_add_include_path (char *path, bool user_supplied) -{ - /* CHAIN sets cpp_dir->sysp which differs from 0 if PATH is a system - include path. Fortran does not define any system include paths. */ - int cxx_aware = 0; - - add_path (path, INC_BRACKET, cxx_aware, user_supplied); -} - -void -gfc_cpp_add_include_path_after (char *path, bool user_supplied) -{ - int cxx_aware = 0; - add_path (path, INC_AFTER, cxx_aware, user_supplied); -} - - -static void scan_translation_unit_trad (cpp_reader *); -static void account_for_newlines (const unsigned char *, size_t); -static int dump_macro (cpp_reader *, cpp_hashnode *, void *); - -static void print_line (location_t, const char *); -static void maybe_print_line (location_t); - - -/* Writes out the preprocessed file, handling spacing and paste - avoidance issues. */ -static void -scan_translation_unit (cpp_reader *pfile) -{ - bool avoid_paste = false; - - print.source = NULL; - for (;;) - { - const cpp_token *token = cpp_get_token (pfile); - - if (token->type == CPP_PADDING) - { - avoid_paste = true; - if (print.source == NULL - || (!(print.source->flags & PREV_WHITE) - && token->val.source == NULL)) - print.source = token->val.source; - continue; - } - - if (token->type == CPP_EOF) - break; - - /* Subtle logic to output a space if and only if necessary. */ - if (avoid_paste) - { - if (print.source == NULL) - print.source = token; - if (print.source->flags & PREV_WHITE - || (print.prev - && cpp_avoid_paste (pfile, print.prev, token)) - || (print.prev == NULL && token->type == CPP_HASH)) - putc (' ', print.outf); - } - else if (token->flags & PREV_WHITE) - putc (' ', print.outf); - - avoid_paste = false; - print.source = NULL; - print.prev = token; - cpp_output_token (token, print.outf); - - if (token->type == CPP_COMMENT) - account_for_newlines (token->val.str.text, token->val.str.len); - } -} - -/* Adjust print.src_line for newlines embedded in output. */ -static void -account_for_newlines (const unsigned char *str, size_t len) -{ - while (len--) - if (*str++ == '\n') - print.src_line++; -} - -/* Writes out a traditionally preprocessed file. */ -static void -scan_translation_unit_trad (cpp_reader *pfile) -{ - while (_cpp_read_logical_line_trad (pfile)) - { - size_t len = pfile->out.cur - pfile->out.base; - maybe_print_line (pfile->out.first_line); - fwrite (pfile->out.base, 1, len, print.outf); - print.printed = 1; - if (!CPP_OPTION (pfile, discard_comments)) - account_for_newlines (pfile->out.base, len); - } -} - -/* If the token read on logical line LINE needs to be output on a - different line to the current one, output the required newlines or - a line marker. */ -static void -maybe_print_line (location_t src_loc) -{ - const line_map_ordinary *map - = linemap_check_ordinary (linemap_lookup (line_table, src_loc)); - int src_line = SOURCE_LINE (map, src_loc); - - /* End the previous line of text. */ - if (print.printed) - { - putc ('\n', print.outf); - print.src_line++; - print.printed = 0; - } - - if (src_line >= print.src_line && src_line < print.src_line + 8) - { - while (src_line > print.src_line) - { - putc ('\n', print.outf); - print.src_line++; - } - } - else - print_line (src_loc, ""); -} - -/* Output a line marker for logical line LINE. Special flags are "1" - or "2" indicating entering or leaving a file. */ -static void -print_line (location_t src_loc, const char *special_flags) -{ - /* End any previous line of text. */ - if (print.printed) - putc ('\n', print.outf); - print.printed = 0; - - if (!gfc_cpp_option.no_line_commands) - { - expanded_location loc; - size_t to_file_len; - unsigned char *to_file_quoted; - unsigned char *p; - int sysp; - - loc = expand_location (src_loc); - to_file_len = strlen (loc.file); - to_file_quoted = (unsigned char *) alloca (to_file_len * 4 + 1); - - print.src_line = loc.line; - - /* cpp_quote_string does not nul-terminate, so we have to do it - ourselves. */ - p = cpp_quote_string (to_file_quoted, - (const unsigned char *) loc.file, to_file_len); - *p = '\0'; - fprintf (print.outf, "# %u \"%s\"%s", - print.src_line == 0 ? 1 : print.src_line, - to_file_quoted, special_flags); - - sysp = in_system_header_at (src_loc); - if (sysp == 2) - fputs (" 3 4", print.outf); - else if (sysp == 1) - fputs (" 3", print.outf); - - putc ('\n', print.outf); - } -} - -static void -cb_file_change (cpp_reader * ARG_UNUSED (pfile), const line_map_ordinary *map) -{ - const char *flags = ""; - - if (gfc_cpp_option.no_line_commands) - return; - - if (!map) - return; - - if (print.first_time) - { - /* Avoid printing foo.i when the main file is foo.c. */ - if (!cpp_get_options (cpp_in)->preprocessed) - print_line (map->start_location, flags); - print.first_time = 0; - } - else - { - /* Bring current file to correct line when entering a new file. */ - if (map->reason == LC_ENTER) - maybe_print_line (linemap_included_from (map)); - if (map->reason == LC_ENTER) - flags = " 1"; - else if (map->reason == LC_LEAVE) - flags = " 2"; - print_line (map->start_location, flags); - } - -} - -/* Called when a line of output is started. TOKEN is the first token - of the line, and at end of file will be CPP_EOF. */ -static void -cb_line_change (cpp_reader *pfile, const cpp_token *token, - int parsing_args) -{ - location_t src_loc = token->src_loc; - - if (token->type == CPP_EOF || parsing_args) - return; - - maybe_print_line (src_loc); - print.prev = 0; - print.source = 0; - - /* Supply enough spaces to put this token in its original column, - one space per column greater than 2, since scan_translation_unit - will provide a space if PREV_WHITE. Don't bother trying to - reconstruct tabs; we can't get it right in general, and nothing - ought to care. Some things do care; the fault lies with them. */ - if (!CPP_OPTION (pfile, traditional)) - { - const line_map_ordinary *map - = linemap_check_ordinary (linemap_lookup (line_table, src_loc)); - int spaces = SOURCE_COLUMN (map, src_loc) - 2; - print.printed = 1; - - while (-- spaces >= 0) - putc (' ', print.outf); - } -} - -static void -cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line, - const cpp_string *str) -{ - maybe_print_line (line); - fprintf (print.outf, "#ident %s\n", str->text); - print.src_line++; -} - -static void -cb_define (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line, - cpp_hashnode *node ATTRIBUTE_UNUSED) -{ - maybe_print_line (line); - fputs ("#define ", print.outf); - - /* 'D' is whole definition; 'N' is name only. */ - if (gfc_cpp_option.dump_macros == 'D') - fputs ((const char *) cpp_macro_definition (pfile, node), - print.outf); - else - fputs ((const char *) NODE_NAME (node), print.outf); - - putc ('\n', print.outf); - if (LOCATION_LINE (line) != 0) - print.src_line++; -} - -static void -cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line, - cpp_hashnode *node) -{ - maybe_print_line (line); - fprintf (print.outf, "#undef %s\n", NODE_NAME (node)); - print.src_line++; -} - -static void -cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line, - const unsigned char *dir, const char *header, int angle_brackets, - const cpp_token **comments) -{ - maybe_print_line (line); - if (angle_brackets) - fprintf (print.outf, "#%s <%s>", dir, header); - else - fprintf (print.outf, "#%s \"%s\"", dir, header); - - if (comments != NULL) - { - while (*comments != NULL) - { - if ((*comments)->flags & PREV_WHITE) - putc (' ', print.outf); - cpp_output_token (*comments, print.outf); - ++comments; - } - } - - putc ('\n', print.outf); - print.src_line++; -} - -/* Dump out the hash table. */ -static int -dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED) -{ - if (cpp_user_macro_p (node)) - { - fputs ("#define ", print.outf); - fputs ((const char *) cpp_macro_definition (pfile, node), - print.outf); - putc ('\n', print.outf); - print.src_line++; - } - - return 1; -} - -static void -cb_used_define (cpp_reader *pfile, location_t line ATTRIBUTE_UNUSED, - cpp_hashnode *node) -{ - gfc_cpp_macro_queue *q; - q = XNEW (gfc_cpp_macro_queue); - q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node)); - q->next = cpp_define_queue; - cpp_define_queue = q; -} - -/* Return the gcc option code associated with the reason for a cpp - message, or 0 if none. */ - -static int -cb_cpp_diagnostic_cpp_option (enum cpp_warning_reason reason) -{ - const struct cpp_reason_option_codes_t *entry; - - for (entry = cpp_reason_option_codes; entry->reason != CPP_W_NONE; entry++) - if (entry->reason == reason) - return entry->option_code; - return 0; -} - - -/* Callback from cpp_error for PFILE to print diagnostics from the - preprocessor. The diagnostic is of type LEVEL, with REASON set - to the reason code if LEVEL is represents a warning, at location - RICHLOC; MSG is the translated message and AP the arguments. - Returns true if a diagnostic was emitted, false otherwise. */ - -static bool -cb_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED, - enum cpp_diagnostic_level level, - enum cpp_warning_reason reason, - rich_location *richloc, - const char *msg, va_list *ap) -{ - diagnostic_info diagnostic; - diagnostic_t dlevel; - bool save_warn_system_headers = global_dc->dc_warn_system_headers; - bool ret; - - switch (level) - { - case CPP_DL_WARNING_SYSHDR: - global_dc->dc_warn_system_headers = 1; - /* Fall through. */ - case CPP_DL_WARNING: - dlevel = DK_WARNING; - break; - case CPP_DL_PEDWARN: - dlevel = DK_PEDWARN; - break; - case CPP_DL_ERROR: - dlevel = DK_ERROR; - break; - case CPP_DL_ICE: - dlevel = DK_ICE; - break; - case CPP_DL_NOTE: - dlevel = DK_NOTE; - break; - case CPP_DL_FATAL: - dlevel = DK_FATAL; - break; - default: - gcc_unreachable (); - } - diagnostic_set_info_translated (&diagnostic, msg, ap, - richloc, dlevel); - diagnostic_override_option_index (&diagnostic, - cb_cpp_diagnostic_cpp_option (reason)); - ret = diagnostic_report_diagnostic (global_dc, &diagnostic); - if (level == CPP_DL_WARNING_SYSHDR) - global_dc->dc_warn_system_headers = save_warn_system_headers; - return ret; -} - -/* Callback called when -fworking-director and -E to emit working - directory in cpp output file. */ - -void -pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir) -{ - size_t to_file_len = strlen (dir); - unsigned char *to_file_quoted = - (unsigned char *) alloca (to_file_len * 4 + 1); - unsigned char *p; - - /* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */ - p = cpp_quote_string (to_file_quoted, (const unsigned char *) dir, to_file_len); - *p = '\0'; - fprintf (print.outf, "# 1 \"%s//\"\n", to_file_quoted); -} - -/* Copy a #pragma directive to the preprocessed output. */ -static void -cb_def_pragma (cpp_reader *pfile, location_t line) -{ - maybe_print_line (line); - fputs ("#pragma ", print.outf); - cpp_output_line (pfile, print.outf); - print.src_line++; -} - -static void -cb_used_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, - location_t line ATTRIBUTE_UNUSED, - cpp_hashnode *node) -{ - gfc_cpp_macro_queue *q; - q = XNEW (gfc_cpp_macro_queue); - q->macro = xstrdup ((const char *) NODE_NAME (node)); - q->next = cpp_undefine_queue; - cpp_undefine_queue = q; -} - -static void -dump_queued_macros (cpp_reader *pfile ATTRIBUTE_UNUSED) -{ - gfc_cpp_macro_queue *q; - - /* End the previous line of text. */ - if (print.printed) - { - putc ('\n', print.outf); - print.src_line++; - print.printed = 0; - } - - for (q = cpp_define_queue; q;) - { - gfc_cpp_macro_queue *oq; - fputs ("#define ", print.outf); - fputs (q->macro, print.outf); - putc ('\n', print.outf); - print.src_line++; - oq = q; - q = q->next; - free (oq->macro); - free (oq); - } - cpp_define_queue = NULL; - for (q = cpp_undefine_queue; q;) - { - gfc_cpp_macro_queue *oq; - fprintf (print.outf, "#undef %s\n", q->macro); - print.src_line++; - oq = q; - q = q->next; - free (oq->macro); - free (oq); - } - cpp_undefine_queue = NULL; -} |