From 670637ee80cf6a86884d3ac1317992e991482a1e Mon Sep 17 00:00:00 2001 From: Daniel Franke Date: Sun, 25 May 2008 18:37:41 -0400 Subject: [PATCH] re PR fortran/18428 (No preprocessing option -cpp for gfortran) gcc: 2008-05-26 Daniel Franke PR fortran/18428 * c.opt: Removed undocumented option '-lang-fortran'. * c-common.h: Removed global variable 'lang_fortran'. * c-opts.c (c_common_handle_option): Removed code to handle option '-lang-fortran'. Updated includes. * c-cppbuiltin.c (c_cpp_builtins): Removed conditional definition of '__GFORTRAN__'. (define__GNUC__): Reimplemented to use BASEVER and cpp_define_formatted. (builtin_define_with_value_n): Removed. * c-incpath.h: Renamed to ... * incpath.h: ... this. * c-incpath.c: Renamed to ... * incpath.c: ... this. Updated includes. * fix-header.c: Updated includes. * Makefile.in: Replaced c-incpath.[ch] by incpath.[ch]. (c-cppbuiltin.o): Added dependency on and definition of BASEVER. (OBJ-archive): Added cppdefault.o, incpath.o and prefix.o. gcc/cp: 2008-05-26 Daniel Franke * Makefile.in: Adjusted dependencies on c-incpath.o. gcc/fortran: 2008-05-26 Daniel Franke PR fortran/18428 * lang.opt (A, C, CC, D, E, H, P, U, cpp, d, fworking-directory, imultilib, iprefix, iquote, isysroot, isystem, nocpp, nostdinc, o, undef, v): New options. * options.c (gfc_init_options): Also initialize preprocessor options. (gfc_post_options): Also handle post-initialization of preprocessor options. (gfc_handle_option): Check if option is a preprocessor option. If yes, let gfc_cpp_handle_option() handle the option. * lang-specs.h: Reorganized to handle new options. * scanner.c (gfc_new_file): Read temporary file instead of input source if preprocessing is enabled. * f95-lang.c (gfc_init): Initialize preprocessor. (gfc_finish): Clean up preprocessor. * cpp.c: New. * cpp.h: New. * Make-lang.in: Added new objects and dependencies. * gfortran.texi: Updated section "Preprocessing and conditional compilation". * invoke.texi: Added new section "Preprocessing Options", listed and documented the preprocessing options handled by gfortran. From-SVN: r135882 --- gcc/ChangeLog | 21 + gcc/Makefile.in | 17 +- gcc/c-common.h | 2 - gcc/c-cppbuiltin.c | 59 +- gcc/c-opts.c | 22 +- gcc/c.opt | 3 - gcc/cp/ChangeLog | 4 + gcc/cp/Make-lang.in | 2 +- gcc/fix-header.c | 2 +- gcc/fortran/ChangeLog | 26 + gcc/fortran/Make-lang.in | 15 +- gcc/fortran/cpp.c | 1000 ++++++++++++++++++++++++++++++++ gcc/fortran/cpp.h | 29 + gcc/fortran/f95-lang.c | 17 +- gcc/fortran/gfortran.texi | 10 +- gcc/fortran/invoke.texi | 242 ++++++++ gcc/fortran/lang-specs.h | 44 +- gcc/fortran/lang.opt | 83 +++ gcc/fortran/options.c | 21 +- gcc/fortran/scanner.c | 11 +- gcc/{c-incpath.c => incpath.c} | 2 +- gcc/{c-incpath.h => incpath.h} | 0 22 files changed, 1509 insertions(+), 123 deletions(-) create mode 100644 gcc/fortran/cpp.c create mode 100644 gcc/fortran/cpp.h rename gcc/{c-incpath.c => incpath.c} (99%) rename gcc/{c-incpath.h => incpath.h} (100%) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b6c22de3c8a..633b9defffd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2008-05-26 Daniel Franke + + PR fortran/18428 + * c.opt: Removed undocumented option '-lang-fortran'. + * c-common.h: Removed global variable 'lang_fortran'. + * c-opts.c (c_common_handle_option): Removed code to handle + option '-lang-fortran'. Updated includes. + * c-cppbuiltin.c (c_cpp_builtins): Removed conditional + definition of '__GFORTRAN__'. + (define__GNUC__): Reimplemented to use BASEVER and + cpp_define_formatted. + (builtin_define_with_value_n): Removed. + * c-incpath.h: Renamed to ... + * incpath.h: ... this. + * c-incpath.c: Renamed to ... + * incpath.c: ... this. Updated includes. + * fix-header.c: Updated includes. + * Makefile.in: Replaced c-incpath.[ch] by incpath.[ch]. + (c-cppbuiltin.o): Added dependency on and definition of BASEVER. + (OBJ-archive): Added cppdefault.o, incpath.o and prefix.o. + 2008-05-25 Eric Botcazou * tree.h: Update the table of flags used on tree nodes. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 0d88228f99c..64ea8cd834a 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -976,7 +976,7 @@ GCC_OBJS = gcc.o opts-common.o gcc-options.o # Language-specific object files for C and Objective C. C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \ c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \ - c-incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \ + c-ppoutput.o c-cppbuiltin.o \ c-objc-common.o c-dump.o c-pch.o c-parser.o $(C_TARGET_OBJS) \ c-gimplify.o tree-mudflap.o c-pretty-print.o c-omp.o @@ -1234,6 +1234,8 @@ OBJS-archive = \ cgraph.o \ cgraphbuild.o \ cgraphunit.o \ + cppdefault.o \ + incpath.o \ ipa-cp.o \ ipa-inline.o \ ipa-prop.o \ @@ -1244,6 +1246,7 @@ OBJS-archive = \ ipa-utils.o \ ipa.o \ matrix-reorg.o \ + prefix.o \ tree-inline.o \ tree-nomudflap.o \ varpool.o @@ -1733,7 +1736,7 @@ srcextra: gcc.srcextra lang.srcextra gcc.srcextra: gengtype-lex.c -cp -p $^ $(srcdir) -c-incpath.o: c-incpath.c c-incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \ +incpath.o: incpath.c incpath.h $(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) \ intl.h prefix.h coretypes.h $(TM_H) cppdefault.h $(TARGET_H) \ $(MACHMODE_H) @@ -1816,13 +1819,15 @@ c-pretty-print.o : c-pretty-print.c $(C_PRETTY_PRINT_H) \ c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(C_PRAGMA_H) $(FLAGS_H) toplev.h langhooks.h \ $(TREE_INLINE_H) $(DIAGNOSTIC_H) intl.h debug.h $(C_COMMON_H) \ - opts.h options.h $(MKDEPS_H) c-incpath.h cppdefault.h $(TM_P_H) + opts.h options.h $(MKDEPS_H) incpath.h cppdefault.h $(TM_P_H) $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) \ $< $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@ c-cppbuiltin.o : c-cppbuiltin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) version.h $(C_COMMON_H) $(C_PRAGMA_H) $(FLAGS_H) toplev.h \ - output.h except.h $(REAL_H) $(TARGET_H) $(TM_P_H) + output.h except.h $(REAL_H) $(TARGET_H) $(TM_P_H) $(BASEVER) + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) -DBASEVER=$(BASEVER_s) \ + $< $(OUTPUT_OPTION) # A file used by all variants of C and some other languages. @@ -3590,10 +3595,10 @@ xsys-protos.h: $(GCC_PASSES) $(srcdir)/sys-protos.h deduced.h \ # This is nominally a 'build' program, but it's run only when host==build, # so we can (indeed, must) use $(LIBDEPS) and $(LIBS). build/fix-header$(build_exeext): build/fix-header.o build/scan-decls.o \ - build/scan.o xsys-protos.h c-incpath.o cppdefault.o prefix.o \ + build/scan.o xsys-protos.h \ $(BUILD_ERRORS) $(LIBDEPS) $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \ - build/fix-header.o c-incpath.o cppdefault.o build/scan-decls.o prefix.o \ + build/fix-header.o incpath.o cppdefault.o build/scan-decls.o prefix.o \ build/scan.o $(BUILD_ERRORS) $(LIBS) build/fix-header.o: fix-header.c $(OBSTACK_H) scan.h errors.h \ diff --git a/gcc/c-common.h b/gcc/c-common.h index ea692230bf0..7ad0be5a425 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -262,8 +262,6 @@ extern c_language_kind c_language; #define c_dialect_cxx() (c_language & clk_cxx) #define c_dialect_objc() (c_language & clk_objc) -extern bool lang_fortran; - /* Information about a statement tree. */ struct stmt_tree_s GTY(()) { diff --git a/gcc/c-cppbuiltin.c b/gcc/c-cppbuiltin.c index 86c3f9cfff2..2f2033de537 100644 --- a/gcc/c-cppbuiltin.c +++ b/gcc/c-cppbuiltin.c @@ -48,8 +48,6 @@ along with GCC; see the file COPYING3. If not see /* Non-static as some targets don't use it. */ void builtin_define_std (const char *) ATTRIBUTE_UNUSED; -static void builtin_define_with_value_n (const char *, const char *, - size_t); static void builtin_define_with_int_value (const char *, HOST_WIDE_INT); static void builtin_define_with_hex_fp_value (const char *, tree, int, const char *, @@ -375,40 +373,17 @@ builtin_define_fixed_point_constants (const char *name_prefix, static void define__GNUC__ (void) { - /* The format of the version string, enforced below, is - ([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */ - const char *q, *v = version_string; - - while (*v && !ISDIGIT (*v)) - v++; - gcc_assert (*v && (v <= version_string || v[-1] == '-')); - - q = v; - while (ISDIGIT (*v)) - v++; - builtin_define_with_value_n ("__GNUC__", q, v - q); - if (c_dialect_cxx ()) - builtin_define_with_value_n ("__GNUG__", q, v - q); - - gcc_assert (*v == '.' && ISDIGIT (v[1])); + int major, minor, patchlevel; - q = ++v; - while (ISDIGIT (*v)) - v++; - builtin_define_with_value_n ("__GNUC_MINOR__", q, v - q); - - if (*v == '.') + if (sscanf (BASEVER, "%d.%d.%d", &major, &minor, &patchlevel) != 3) { - gcc_assert (ISDIGIT (v[1])); - q = ++v; - while (ISDIGIT (*v)) - v++; - builtin_define_with_value_n ("__GNUC_PATCHLEVEL__", q, v - q); + sscanf (BASEVER, "%d.%d", &major, &minor); + patchlevel = 0; } - else - builtin_define_with_value_n ("__GNUC_PATCHLEVEL__", "0", 1); + cpp_define_formatted (parse_in, "__GNUC__=%d", major); + cpp_define_formatted (parse_in, "__GNUC_MINOR__=%d", minor); + cpp_define_formatted (parse_in, "__GNUC_PATCHLEVEL__=%d", patchlevel); - gcc_assert (!*v || *v == ' ' || *v == '-'); } /* Define macros used by . Currently only defines limits @@ -684,9 +659,6 @@ c_cpp_builtins (cpp_reader *pfile) if (flag_openmp) cpp_define (pfile, "_OPENMP=200505"); - if (lang_fortran) - cpp_define (pfile, "__GFORTRAN__=1"); - builtin_define_type_sizeof ("__SIZEOF_INT__", integer_type_node); builtin_define_type_sizeof ("__SIZEOF_LONG__", long_integer_type_node); builtin_define_type_sizeof ("__SIZEOF_LONG_LONG__", @@ -799,23 +771,6 @@ builtin_define_with_value (const char *macro, const char *expansion, int is_str) cpp_define (parse_in, buf); } -/* Pass an object-like macro and a value to define it to. The third - parameter is the length of the expansion. */ -static void -builtin_define_with_value_n (const char *macro, const char *expansion, size_t elen) -{ - char *buf; - size_t mlen = strlen (macro); - - /* Space for an = and a NUL. */ - buf = (char *) alloca (mlen + elen + 2); - memcpy (buf, macro, mlen); - buf[mlen] = '='; - memcpy (buf + mlen + 1, expansion, elen); - buf[mlen + elen + 1] = '\0'; - - cpp_define (parse_in, buf); -} /* Pass an object-like macro and an integer value to define it to. */ static void diff --git a/gcc/c-opts.c b/gcc/c-opts.c index eda0f48f949..2eef789978d 100644 --- a/gcc/c-opts.c +++ b/gcc/c-opts.c @@ -33,7 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "intl.h" #include "cppdefault.h" -#include "c-incpath.h" +#include "incpath.h" #include "debug.h" /* For debug_hooks. */ #include "opts.h" #include "options.h" @@ -72,9 +72,6 @@ static bool deps_seen; /* If -v seen. */ static bool verbose; -/* If -lang-fortran seen. */ -bool lang_fortran = false; - /* Dependency output file. */ static const char *deps_file; @@ -249,15 +246,6 @@ c_common_init_options (unsigned int argc, const char **argv) result |= CL_C | CL_ObjC | CL_CXX | CL_ObjCXX; break; } - -#ifdef CL_Fortran - for (i = 1; i < argc; i++) - if (! strcmp (argv[i], "-lang-fortran")) - { - result |= CL_Fortran; - break; - } -#endif } return result; @@ -288,10 +276,6 @@ c_common_handle_option (size_t scode, const char *arg, int value) result = 0; break; } -#ifdef CL_Fortran - if (lang_fortran && (cl_options[code].flags & (CL_Fortran))) - break; -#endif result = 0; break; @@ -891,10 +875,6 @@ c_common_handle_option (size_t scode, const char *arg, int value) cpp_opts->dollars_in_ident = false; break; - case OPT_lang_fortran: - lang_fortran = true; - break; - case OPT_lang_objc: cpp_opts->objc = 1; break; diff --git a/gcc/c.opt b/gcc/c.opt index 1df0666f660..18ce852dc86 100644 --- a/gcc/c.opt +++ b/gcc/c.opt @@ -864,9 +864,6 @@ C ObjC C++ ObjC++ Joined Separate lang-asm C Undocumented -lang-fortran -C Undocumented - lang-objc C ObjC C++ ObjC++ Undocumented diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b4cf3d40460..4b1c7dbc32c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,7 @@ +2008-05-26 Daniel Franke + + * Makefile.in: Adjusted dependencies on c-incpath.o. + 2008-05-23 Jakub Jelinek PR c++/36237 diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index e1447b02e1e..c1336df2e8e 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -72,7 +72,7 @@ g++-cross$(exeext): g++$(exeext) # Shared with C front end: CXX_C_OBJS = attribs.o c-common.o c-format.o c-pragma.o c-semantics.o c-lex.o \ c-dump.o $(CXX_TARGET_OBJS) c-pretty-print.o c-opts.o c-pch.o \ - c-incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \ + incpath.o cppdefault.o c-ppoutput.o c-cppbuiltin.o prefix.o \ c-gimplify.o c-omp.o tree-inline.o # Language-specific object files for C++ and Objective C++. diff --git a/gcc/fix-header.c b/gcc/fix-header.c index ac8a9bb0034..f691e4eae70 100644 --- a/gcc/fix-header.c +++ b/gcc/fix-header.c @@ -78,7 +78,7 @@ #include "obstack.h" #include "scan.h" #include "cpplib.h" -#include "c-incpath.h" +#include "incpath.h" #include "errors.h" #ifdef TARGET_EXTRA_INCLUDES diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 5c85a65eeec..9e4cb23583e 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,29 @@ +2008-05-26 Daniel Franke + + PR fortran/18428 + * lang.opt (A, C, CC, D, E, H, P, U, cpp, d, fworking-directory, + imultilib, iprefix, iquote, isysroot, isystem, nocpp, nostdinc, + o, undef, v): New options. + * options.c (gfc_init_options): Also initialize preprocessor + options. + (gfc_post_options): Also handle post-initialization of preprocessor + options. + (gfc_handle_option): Check if option is a preprocessor option. + If yes, let gfc_cpp_handle_option() handle the option. + * lang-specs.h: Reorganized to handle new options. + * scanner.c (gfc_new_file): Read temporary file instead of + input source if preprocessing is enabled. + * f95-lang.c (gfc_init): Initialize preprocessor. + (gfc_finish): Clean up preprocessor. + * cpp.c: New. + * cpp.h: New. + * Make-lang.in: Added new objects and dependencies. + * gfortran.texi: Updated section "Preprocessing and + conditional compilation". + * invoke.texi: Added new section "Preprocessing Options", + listed and documented the preprocessing options handled + by gfortran. + 2008-05-25 Tobias Burnus PR fortran/32600 diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in index bc9947b3942..dbbed88bd60 100644 --- a/gcc/fortran/Make-lang.in +++ b/gcc/fortran/Make-lang.in @@ -53,9 +53,9 @@ fortran-warn = $(STRICT_WARN) # from the parse tree to GENERIC F95_PARSER_OBJS = fortran/arith.o fortran/array.o fortran/bbt.o \ - fortran/check.o fortran/data.o fortran/decl.o fortran/dump-parse-tree.o \ - fortran/error.o fortran/expr.o fortran/interface.o \ - fortran/intrinsic.o fortran/io.o fortran/iresolve.o \ + fortran/check.o fortran/cpp.o fortran/data.o fortran/decl.o \ + fortran/dump-parse-tree.o fortran/error.o fortran/expr.o \ + fortran/interface.o fortran/intrinsic.o fortran/io.o fortran/iresolve.o \ fortran/match.o fortran/matchexp.o fortran/misc.o fortran/module.o \ fortran/openmp.o fortran/options.o fortran/parse.o fortran/primary.o \ fortran/resolve.o fortran/scanner.o fortran/simplify.o fortran/st.o \ @@ -306,9 +306,9 @@ GFORTRAN_TRANS_DEPS = fortran/gfortran.h fortran/libgfortran.h \ $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) coretypes.h $(GGC_H) fortran/f95-lang.o: $(GFORTRAN_TRANS_DEPS) fortran/mathbuiltins.def \ - gt-fortran-f95-lang.h gtype-fortran.h $(CGRAPH_H) $(TARGET_H) \ + gt-fortran-f95-lang.h gtype-fortran.h $(CGRAPH_H) $(TARGET_H) fortran/cpp.h \ $(BUILTINS_DEF) fortran/types.def -fortran/scanner.o: toplev.h +fortran/scanner.o: toplev.h fortran/cpp.h fortran/convert.o: $(GFORTRAN_TRANS_DEPS) fortran/trans.o: $(GFORTRAN_TRANS_DEPS) fortran/trans-decl.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-decl.h \ @@ -329,4 +329,7 @@ fortran/dependency.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h fortran/trans-common.o: $(GFORTRAN_TRANS_DEPS) $(TARGET_H) $(RTL_H) fortran/resolve.o: fortran/dependency.h fortran/data.h fortran/target-memory.h fortran/data.o: fortran/data.h -fortran/options.o: $(PARAMS_H) $(TARGET_H) +fortran/options.o: $(PARAMS_H) $(TARGET_H) fortran/cpp.h +fortran/cpp.o: fortran/cpp.c $(BASEVER) incpath.h incpath.o + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) -DBASEVER=$(BASEVER_s) \ + $< $(OUTPUT_OPTION) diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c new file mode 100644 index 00000000000..3260d26c49a --- /dev/null +++ b/gcc/fortran/cpp.c @@ -0,0 +1,1000 @@ +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "version.h" +#include "flags.h" + + +#include "options.h" +#include "gfortran.h" +#include "target.h" +#include "toplev.h" +#include "diagnostic.h" + +#include "../../libcpp/internal.h" +#include "cpp.h" +#include "incpath.h" + +#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 +{ + /* Argument of -cpp, implied by SPEC; + if NULL, preprocessing disabled. */ + const char *temporary_filename; + + const char *output_filename; /* -o */ + 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 */ + + const char *multilib; /* -imultilib */ + const char *prefix; /* -iprefix */ + const char *sysroot; /* -isysroot */ + + /* Options whose handling needs to be deferred until the + appropriate cpp-objects are created: + -A predicate=answer + -D [=] + -U */ + 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; + +/* Defined in toplev.c. */ +extern const char *asm_file_name; + + + + +/* 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 struct line_map *); +static void cb_line_change (cpp_reader *, const cpp_token *, int); +static void cb_define (cpp_reader *, source_location, cpp_hashnode *); +static void cb_undef (cpp_reader *, source_location, cpp_hashnode *); +static void cb_def_pragma (cpp_reader *, source_location); +static void cb_include (cpp_reader *, source_location, const unsigned char *, + const char *, int, const cpp_token **); +static void cb_ident (cpp_reader *, source_location, const cpp_string *); +static void cb_used_define (cpp_reader *, source_location, cpp_hashnode *); +static void cb_used_undef (cpp_reader *, source_location, cpp_hashnode *); +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) +{ + int major, minor, patchlevel; + + /* 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. */ + if (sscanf (BASEVER, "%d.%d.%d", &major, &minor, &patchlevel) != 3) + { + sscanf (BASEVER, "%d.%d", &major, &minor); + patchlevel = 0; + } + cpp_define_formatted (pfile, "__GNUC__=%d", major); + cpp_define_formatted (pfile, "__GNUC_MINOR__=%d", minor); + cpp_define_formatted (pfile, "__GNUC_PATCHLEVEL__=%d", patchlevel); + + cpp_define (pfile, "__GFORTRAN__=1"); + cpp_define (pfile, "_LANGUAGE_FORTRAN=1"); + + if (gfc_option.flag_openmp) + cpp_define (pfile, "_OPENMP=200505"); + + + /* More builtins that might be useful, but are not documented + (in no particular order). */ + cpp_define_formatted (pfile, "__VERSION__=\"%s\"", version_string); + + if (flag_pic) + { + cpp_define_formatted (pfile, "__pic__=%d", flag_pic); + cpp_define_formatted (pfile, "__PIC__=%d", flag_pic); + } + if (flag_pie) + { + cpp_define_formatted (pfile, "__pie__=%d", flag_pie); + cpp_define_formatted (pfile, "__PIE__=%d", flag_pie); + } + + if (optimize_size) + cpp_define (pfile, "__OPTIMIZE_SIZE__"); + if (optimize) + cpp_define (pfile, "__OPTIMIZE__"); + + if (fast_math_flags_set_p ()) + cpp_define (pfile, "__FAST_MATH__"); + if (flag_signaling_nans) + cpp_define (pfile, "__SUPPORT_SNAN__"); + + cpp_define_formatted (pfile, "__FINITE_MATH_ONLY__=%d", flag_finite_math_only); + + /* Definitions for LP64 model. */ + if (TYPE_PRECISION (long_integer_type_node) == 64 + && POINTER_SIZE == 64 + && TYPE_PRECISION (integer_type_node) == 32) + { + cpp_define (pfile, "_LP64"); + cpp_define (pfile, "__LP64__"); + } + + /* Define NAME with value TYPE size_unit. + The C-side also defines __SIZEOF_WCHAR_T__, __SIZEOF_WINT_T__ + __SIZEOF_PTRDIFF_T__, however, fortran seems to lack the + appropriate type nodes. */ + +#define define_type_sizeof(NAME, TYPE) \ + cpp_define_formatted (pfile, NAME"="HOST_WIDE_INT_PRINT_DEC, \ + tree_low_cst (TYPE_SIZE_UNIT (TYPE), 1)) + + define_type_sizeof ("__SIZEOF_INT__", integer_type_node); + define_type_sizeof ("__SIZEOF_LONG__", long_integer_type_node); + define_type_sizeof ("__SIZEOF_LONG_LONG__", long_long_integer_type_node); + define_type_sizeof ("__SIZEOF_SHORT__", short_integer_type_node); + define_type_sizeof ("__SIZEOF_FLOAT__", float_type_node); + define_type_sizeof ("__SIZEOF_DOUBLE__", double_type_node); + define_type_sizeof ("__SIZEOF_LONG_DOUBLE__", long_double_type_node); + define_type_sizeof ("__SIZEOF_SIZE_T__", size_type_node); + +#undef define_type_sizeof + + /* 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) + + 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; +} + +const char * +gfc_cpp_temporary_file (void) +{ + return gfc_cpp_option.temporary_filename; +} + +void +gfc_cpp_init_options (unsigned int argc, + const char **argv 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.multilib = NULL; + gfc_cpp_option.prefix = NULL; + gfc_cpp_option.sysroot = NULL; + + gfc_cpp_option.deferred_opt = XNEWVEC (gfc_cpp_deferred_opt_t, argc); + 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_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_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_P: + gfc_cpp_option.no_line_commands = 1; + break; + } + + return result; +} + + +void +gfc_cpp_post_options (void) +{ + /* Any preprocessing-related option without '-cpp' is considered + an error. */ + if (!gfc_cpp_enabled () + && (gfc_cpp_preprocess_only () + || !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"); + + cpp_in = cpp_create_reader (CLK_GNUC89, NULL, line_table); + if (!gfc_cpp_enabled()) + return; + + 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->pedantic = pedantic; + cpp_option->inhibit_warnings = inhibit_warnings; + + cpp_option->dollars_in_ident = gfc_option.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; + + if (gfc_cpp_option.working_directory == -1) + gfc_cpp_option.working_directory = (debug_info_level != DINFO_LEVEL_NONE); + + cpp_post_options (cpp_in); + + /* If an error has occurred in cpplib, note it so we fail immediately. */ + errorcount += cpp_errors (cpp_in); + + gfc_cpp_register_include_paths (); +} + + +void +gfc_cpp_init_0 (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; + + 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; + } + + /* 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 ", the user wants the + preprocessed output in . However, if nothing is done + about it 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 %s: %s", + gfc_cpp_option.output_filename, strerror(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 %s: %s", + gfc_cpp_option.temporary_filename, strerror(errno)); + } + + gcc_assert(cpp_in); + if (!cpp_read_main_file (cpp_in, gfc_source_file)) + errorcount++; +} + +void +gfc_cpp_init (void) +{ + int i; + + cpp_change_file (cpp_in, LC_RENAME, _("")); + if (!gfc_cpp_option.no_predefined) + cpp_define_builtins (cpp_in); + + /* Handle deferred options from command-line. */ + cpp_change_file (cpp_in, LC_RENAME, _("")); + + 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); + } + } + + 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 ()); +} + +try +gfc_cpp_preprocess (const char *source_file) +{ + if (!gfc_cpp_enabled ()) + return FAILURE; + + 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); + } + + if (!gfc_cpp_preprocess_only () + || (gfc_cpp_preprocess_only () && gfc_cpp_option.output_filename)) + fclose (print.outf); + + return SUCCESS; +} + +void +gfc_cpp_done (void) +{ + if (!gfc_cpp_enabled ()) + return; + + /* TODO: if dependency tracking was enabled, call + cpp_finish() here to write dependencies. + + Use cpp_get_deps() to access the current source's + dependencies during parsing. Add dependencies using + the mkdeps-interface (defined in libcpp). */ + + gcc_assert (cpp_in); + 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 chain = 0; + int cxx_aware = 0; + + add_path (path, chain, cxx_aware, user_supplied); +} + +void +gfc_cpp_register_include_paths (void) +{ + int cxx_stdinc = 0; + 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); +} + + + +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 (source_location, const char *); +static void maybe_print_line (source_location); + + +/* 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 (source_location src_loc) +{ + const struct line_map *map = 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 (source_location 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) + { + const struct line_map *map = linemap_lookup (line_table, src_loc); + + size_t to_file_len = strlen (map->to_file); + unsigned char *to_file_quoted = + (unsigned char *) alloca (to_file_len * 4 + 1); + unsigned char *p; + + print.src_line = SOURCE_LINE (map, src_loc); + + /* cpp_quote_string does not nul-terminate, so we have to do it + ourselves. */ + p = cpp_quote_string (to_file_quoted, + (const unsigned char *) map->to_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); + + if (map->sysp == 2) + fputs (" 3 4", print.outf); + else if (map->sysp == 1) + fputs (" 3", print.outf); + + putc ('\n', print.outf); + } +} + +static void +cb_file_change (cpp_reader * ARG_UNUSED (pfile), const struct line_map *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) + { + const struct line_map *from = INCLUDED_FROM (line_table, map); + maybe_print_line (LAST_SOURCE_LINE_LOCATION (from)); + } + 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) +{ + source_location 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 struct line_map *map = 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, source_location 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, source_location 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 (linemap_lookup (line_table, line)->to_line != 0) + print.src_line++; +} + +static void +cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location 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, source_location 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 (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)) + { + 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, source_location 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; +} + + +/* 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, source_location 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, + source_location 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; + gfc_free (oq->macro); + gfc_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; + gfc_free (oq->macro); + gfc_free (oq); + } + cpp_undefine_queue = NULL; +} + + diff --git a/gcc/fortran/cpp.h b/gcc/fortran/cpp.h new file mode 100644 index 00000000000..e82b3cd1d43 --- /dev/null +++ b/gcc/fortran/cpp.h @@ -0,0 +1,29 @@ +#ifndef GFC_CPP_H +#define GFC_CPP_H + +/* Returns true if preprocessing is enabled, false otherwise. */ +bool gfc_cpp_enabled (void); + +bool gfc_cpp_preprocess_only (void); + +const char *gfc_cpp_temporary_file (void); + + +void gfc_cpp_init_0 (void); +void gfc_cpp_init (void); + +void gfc_cpp_init_options (unsigned int argc, const char **argv); + +int gfc_cpp_handle_option(size_t scode, const char *arg, int value); + +void gfc_cpp_post_options (void); + +try gfc_cpp_preprocess (const char *source_file); + +void gfc_cpp_done (void); + +void gfc_cpp_add_include_path (char *path, bool user_supplied); + +void gfc_cpp_register_include_paths (void); + +#endif /* GFC_CPP_H */ diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index 58e31279156..63c380b61ea 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "gfortran.h" +#include "cpp.h" #include "trans.h" #include "trans-types.h" #include "trans-const.h" @@ -275,18 +276,25 @@ gfc_be_parse_file (int set_yydebug ATTRIBUTE_UNUSED) static bool gfc_init (void) { - linemap_add (line_table, LC_ENTER, false, gfc_source_file, 1); - linemap_add (line_table, LC_RENAME, false, "", 0); + if (!gfc_cpp_enabled ()) + { + linemap_add (line_table, LC_ENTER, false, gfc_source_file, 1); + linemap_add (line_table, LC_RENAME, false, "", 0); + } + else + gfc_cpp_init_0 (); - /* First initialize the backend. */ gfc_init_decl_processing (); gfc_static_ctors = NULL_TREE; - /* Then the frontend. */ + if (gfc_cpp_enabled ()) + gfc_cpp_init (); + gfc_init_1 (); if (gfc_new_file () != SUCCESS) fatal_error ("can't open input file: %s", gfc_source_file); + return true; } @@ -294,6 +302,7 @@ gfc_init (void) static void gfc_finish (void) { + gfc_cpp_done (); gfc_done_1 (); gfc_release_include_path (); return; diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index 085de7668da..c47f22fcfa0 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -408,11 +408,11 @@ through a C preprocessor (CPP; sometimes also called the Fortran preprocessor, FPP) to allow for conditional compilation. In the case of GNU Fortran, this is the GNU C Preprocessor in the traditional mode. On systems with case-preserving file names, the preprocessor is automatically invoked if the -file extension is @code{.F}, @code{.FOR}, @code{.FTN}, @code{.F90}, -@code{.F95}, @code{.F03} or @code{.F08}; otherwise use for fixed-format -code the option @code{-x f77-cpp-input} and for free-format code @code{-x -f95-cpp-input}. Invocation of the preprocessor can be suppressed using -@code{-x f77} or @code{-x f95}. +filename extension is @code{.F}, @code{.FOR}, @code{.FTN}, @code{.fpp}, +@code{.FPP}, @code{.F90}, @code{.F95}, @code{.F03} or @code{.F08}. To manually +invoke the preprocessor on any file, use @option{-cpp}, to disable +preprocessing on files where the preprocessor is run automatically, use +@option{-nocpp}. If the GNU Fortran invoked the preprocessor, @code{__GFORTRAN__} is defined and @code{__GNUC__}, @code{__GNUC_MINOR__} and diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi index 88ede3b2a13..1494c04013e 100644 --- a/gcc/fortran/invoke.texi +++ b/gcc/fortran/invoke.texi @@ -94,6 +94,7 @@ one is not the default. without explanations. * Fortran Dialect Options:: Controlling the variant of Fortran language compiled. +* Preprocessing Options:: Enable and customize preprocessing. * Error and Warning Options:: How picky should the compiler be? * Debugging Options:: Symbol tables, measurements, and debugging dumps. * Directory Options:: Where to find module files @@ -123,6 +124,14 @@ by type. Explanations are in the following sections. -fdefault-double-8 -fdefault-integer-8 -fdefault-real-8 @gol -fcray-pointer -fopenmp -fno-range-check -fbackslash -fmodule-private} +@item Preprocessing Options +@xref{Preprocessing Options,,Enable and customize preprocessing}. +@gccoptlist{-cpp -dD -dI -dM -dN -dU -fworking-directory @gol +-imultilib @var{dir} -iprefix @var{file} -isysroot @var{dir} @gol +-iquote -isystem @var{dir} -nocpp -nostdinc -undef @gol +-A@var{question}=@var{answer} -A-@var{question}@r{[}=@var{answer}@r{]} @gol +-C -CC -D@var{macro}@r{[}=@var{defn}@r{]} -U@var{macro} -H -P} + @item Error and Warning Options @xref{Error and Warning Options,,Options to request or suppress errors and warnings}. @@ -164,6 +173,7 @@ and warnings}. @menu * Fortran Dialect Options:: Controlling the variant of Fortran language compiled. +* Preprocessing Options:: Enable and customize preprocessing. * Error and Warning Options:: How picky should the compiler be? * Debugging Options:: Symbol tables, measurements, and debugging dumps. * Directory Options:: Where to find module files @@ -341,6 +351,238 @@ that are permitted but obsolescent in later standards. @end table +@node Preprocessing Options +@section Enable and customize preprocessing +@cindex preprocessor +@cindex options, preprocessor +@cindex CPP + +Preprocessor related options. See section +@ref{Preprocessing and conditional compilation} for more detailed +information on preprocessing in @command{gfortran}. + +@table @gcctabopt +@item -cpp +@item -nocpp +@opindex @code{cpp} +@opindex @code{fpp} +@cindex preprocessor, enable +@cindex preprocessor, disable +Enable preprocessing. The preprocessor is automatically invoked if +the file extension is @file{.fpp}, @file{.FPP}, @file{.F}, @file{.FOR}, +@file{.FTN}, @file{.F90}, @file{.F95}, @file{.F03} or @file{.F08}. Use +this option to manually enable preprocessing of any kind of Fortran file. + +To disable preprocessing of files with any of the above listed extensions, +use the negative form: @option{-nocpp}. + +The preprocessor is run in traditional mode, be aware that any +restrictions of the file-format, e.g. fixed-form line width, +apply for preprocessed output as well. + +@item -dM +@opindex @code{dM} +@cindex preprocessor, debugging +@cindex debugging, preprocessor +Instead of the normal output, generate a list of @code{'#define'} +directives for all the macros defined during the execution of the +preprocessor, including predefined macros. This gives you a way +of finding out what is predefined in your version of the preprocessor. +Assuming you have no file @file{foo.f90}, the command +@smallexample + touch foo.f90; gfortran -cpp -dM foo.f90 +@end smallexample +will show all the predefined macros. + +@item -dD +@opindex @code{dD} +@cindex preprocessor, debugging +@cindex debugging, preprocessor +Like @option{-dM} except in two respects: it does not include the +predefined macros, and it outputs both the @code{#define} directives +and the result of preprocessing. Both kinds of output go to the +standard output file. + +@item -dN +@opindex @code{dN} +@cindex preprocessor, debugging +@cindex debugging, preprocessor +Like @option{-dD}, but emit only the macro names, not their expansions. + +@item -dU +@opindex @code{dU} +@cindex preprocessor, debugging +@cindex debugging, preprocessor +Like @option{dD} except that only macros that are expanded, or whose +definedness is tested in preprocessor directives, are output; the +output is delayed until the use or test of the macro; and @code{'#undef'} +directives are also output for macros tested but undefined at the time. + +@item -dI +@opindex @code{dI} +@cindex preprocessor, debugging +@cindex debugging, preprocessor +Output @code{'#include'} directives in addition to the result +of preprocessing. + +@item -fworking-directory +@opindex @code{fworking-directory} +@cindex preprocessor, working directory +Enable generation of linemarkers in the preprocessor output that will +let the compiler know the current working directory at the time of +preprocessing. When this option is enabled, the preprocessor will emit, +after the initial linemarker, a second linemarker with the current +working directory followed by two slashes. GCC will use this directory, +when it's present in the preprocessed input, as the directory emitted +as the current working directory in some debugging information formats. +This option is implicitly enabled if debugging information is enabled, +but this can be inhibited with the negated form +@option{-fno-working-directory}. If the @option{-P} flag is present +in the command line, this option has no effect, since no @code{#line} +directives are emitted whatsoever. + +@item -imultilib @var{dir} +@opindex @code{imultilib @var{dir}} +@cindex preprocessing, include path +Use @var{dir} as a subdirectory of the directory containing target-specific +C++ headers. + +@item -iprefix @var{prefix} +@opindex @code{iprefix @var{prefix}} +@cindex preprocessing, include path +Specify @var{prefix} as the prefix for subsequent @option{-iwithprefix} +options. If the @var{prefix} represents a directory, you should include +the final @code{'/'}. + +@item -isysroot @var{dir} +@opindex @code{isysroot @var{dir}} +@cindex preprocessing, include path +This option is like the @option{--sysroot} option, but applies only to +header files. See the @option{--sysroot} option for more information. + +@item -iquote @var{dir} +@opindex @code{iquote @var{dir}} +@cindex preprocessing, include path +Search @var{dir} only for header files requested with @code{#include "file"}; +they are not searched for @code{#include }, before all directories +specified by @option{-I} and before the standard system directories. If +@var{dir} begins with @code{=}, then the @code{=} will be replaced by the +sysroot prefix; see @option{--sysroot} and @option{-isysroot}. + +@item -isystem @var{dir} +@opindex @code{isystem @var{dir}} +@cindex preprocessing, include path +Search @var{dir} for header files, after all directories specified by +@option{-I} but before the standard system directories. Mark it as a +system directory, so that it gets the same special treatment as is +applied to the standard system directories. If @var{dir} begins with +@code{=}, then the @code{=} will be replaced by the sysroot prefix; +see @option{--sysroot} and @option{-isysroot}. + +@item -nostdinc +@opindex @code{nostdinc} +Do not search the standard system directories for header files. Only +the directories you have specified with @option{-I} options (and the +directory of the current file, if appropriate) are searched. + +@item -undef +@opindex @code{undef} +Do not predefine any system-specific or GCC-specific macros. +The standard predefined macros remain defined. + +@item -A@var{predicate}=@var{answer} +@opindex @code{A@var{predicate}=@var{answer}} +@cindex preprocessing, assertation +Make an assertion with the predicate @var{predicate} and answer @var{answer}. +This form is preferred to the older form -A predicate(answer), which is still +supported, because it does not use shell special characters. + +@item -A-@var{predicate}=@var{answer} +@opindex @code{A-@var{predicate}=@var{answer}} +@cindex preprocessing, assertation +Cancel an assertion with the predicate @var{predicate} and answer @var{answer}. + +@item -C +@opindex @code{C} +@cindex preprocessing, keep comments +Do not discard comments. All comments are passed through to the output +file, except for comments in processed directives, which are deleted +along with the directive. + +You should be prepared for side effects when using @option{-C}; it causes +the preprocessor to treat comments as tokens in their own right. For example, +comments appearing at the start of what would be a directive line have the +effect of turning that line into an ordinary source line, since the first +token on the line is no longer a @code{'#'}. + +Warning: this currently handles C-Style comments only. The preprocessor +does not yet recognize Fortran-style comments. + +@item -CC +@opindex @code{CC} +@cindex preprocessing, keep comments +Do not discard comments, including during macro expansion. This is like +@option{-C}, except that comments contained within macros are also passed +through to the output file where the macro is expanded. + +In addition to the side-effects of the @option{-C} option, the @option{-CC} +option causes all C++-style comments inside a macro to be converted to C-style +comments. This is to prevent later use of that macro from inadvertently +commenting out the remainder of the source line. The @option{-CC} option +is generally used to support lint comments. + +Warning: this currently handles C- and C++-Style comments only. The +preprocessor does not yet recognize Fortran-style comments. + +@item -D@var{name} +@opindex @code{D@var{name}} +@cindex preprocessing, define macros +Predefine name as a macro, with definition @code{1}. + +@item -D@var{name}=@var{definition} +@opindex @code{D@var{name}=@var{definition}} +@cindex preprocessing, define macros +The contents of @var{definition} are tokenized and processed as if they +appeared during translation phase three in a @code{'#define'} directive. +In particular, the definition will be truncated by embedded newline +characters. + +If you are invoking the preprocessor from a shell or shell-like program +you may need to use the shell's quoting syntax to protect characters such +as spaces that have a meaning in the shell syntax. + +If you wish to define a function-like macro on the command line, write +its argument list with surrounding parentheses before the equals sign +(if any). Parentheses are meaningful to most shells, so you will need +to quote the option. With sh and csh, @code{-D'name(args...)=definition'} +works. + +@option{-D} and @option{-U} options are processed in the order they are +given on the command line. All -imacros file and -include file options +are processed after all -D and -U options. + +@item -H +@opindex @code{H} +Print the name of each header file used, in addition to other normal +activities. Each name is indented to show how deep in the @code{'#include'} +stack it is. + +@item -P +@opindex @code{P} +@cindex preprocessing, no linemarkers +Inhibit generation of linemarkers in the output from the preprocessor. +This might be useful when running the preprocessor on something that +is not C code, and will be sent to a program which might be confused +by the linemarkers. + +@item -U@var{name} +@opindex @code{U@var{name}} +@cindex preprocessing, undefine macros +Cancel any previous definition of @var{name}, either built in or provided +with a @option{-D} option. +@end table + + @node Error and Warning Options @section Options to request or suppress errors and warnings @cindex options, warnings diff --git a/gcc/fortran/lang-specs.h b/gcc/fortran/lang-specs.h index e5c54ae0011..e4bd0509c8b 100644 --- a/gcc/fortran/lang-specs.h +++ b/gcc/fortran/lang-specs.h @@ -20,35 +20,45 @@ /* This is the contribution to the `default_compilers' array in gcc.c for the f95 language. */ + +#define F951_CPP_OPTIONS "%{!nocpp: -cpp %g.f90 %(cpp_options)\ + %{E|M|MM:%(cpp_debug_options) -fsyntax-only} %{E}}" +#define F951_OPTIONS "%(cc1_options) %{J*} %{I*}\ + %{!nostdinc:-fintrinsic-modules-path finclude%s}\ + %{!fsyntax-only:%(invoke_as)}" +#define F951_SOURCE_FORM "%{!ffree-form:-ffixed-form}" + + {".F", "@f77-cpp-input", 0, 0, 0}, {".FOR", "@f77-cpp-input", 0, 0, 0}, {".FTN", "@f77-cpp-input", 0, 0, 0}, {".fpp", "@f77-cpp-input", 0, 0, 0}, {".FPP", "@f77-cpp-input", 0, 0, 0}, {"@f77-cpp-input", - "cc1 -E -lang-fortran -traditional-cpp -D_LANGUAGE_FORTRAN %(cpp_options) \ - %{E|M|MM:%(cpp_debug_options)}\ - %{!M:%{!MM:%{!E: -o %|.f |\n\ - f951 %|.f %{!ffree-form:-ffixed-form} %(cc1_options) %{J*} %{I*}\ - -fpreprocessed %{!nostdinc:-fintrinsic-modules-path finclude%s} %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, + "f951 %i " F951_SOURCE_FORM " " \ + F951_CPP_OPTIONS " %{!E:" F951_OPTIONS "}", 0, 0, 0}, +{".f", "@f77", 0, 0, 0}, +{".for", "@f77", 0, 0, 0}, +{".ftn", "@f77", 0, 0, 0}, +{"@f77", + "f951 %i " F951_SOURCE_FORM " \ + %{E:%{!cpp:%egfortran does not support -E without -cpp}} \ + %{cpp:" F951_CPP_OPTIONS "} %{!E:" F951_OPTIONS "}", 0, 0, 0}, {".F90", "@f95-cpp-input", 0, 0, 0}, {".F95", "@f95-cpp-input", 0, 0, 0}, {".F03", "@f95-cpp-input", 0, 0, 0}, {".F08", "@f95-cpp-input", 0, 0, 0}, {"@f95-cpp-input", - "cc1 -E -lang-fortran -traditional-cpp -D_LANGUAGE_FORTRAN %(cpp_options) \ - %{E|M|MM:%(cpp_debug_options)}\ - %{!M:%{!MM:%{!E: -o %|.f95 |\n\ - f951 %|.f95 %{!ffixed-form:-ffree-form} %(cc1_options) %{J*} %{I*}\ - -fpreprocessed %{!nostdinc:-fintrinsic-modules-path finclude%s} %{!fsyntax-only:%(invoke_as)}}}}", 0, 0, 0}, + "f951 %i " F951_CPP_OPTIONS " %{!E:" F951_OPTIONS "}", 0, 0, 0}, {".f90", "@f95", 0, 0, 0}, {".f95", "@f95", 0, 0, 0}, {".f03", "@f95", 0, 0, 0}, {".f08", "@f95", 0, 0, 0}, -{"@f95", "%{!E:f951 %i %(cc1_options) %{J*} %{I*}\ - %{!nostdinc:-fintrinsic-modules-path finclude%s} %{!fsyntax-only:%(invoke_as)}}", 0, 0, 0}, -{".f", "@f77", 0, 0, 0}, -{".for", "@f77", 0, 0, 0}, -{".ftn", "@f77", 0, 0, 0}, -{"@f77", "%{!E:f951 %i %{!ffree-form:-ffixed-form} %(cc1_options) %{J*} %{I*}\ - %{!nostdinc:-fintrinsic-modules-path finclude%s} %{!fsyntax-only:%(invoke_as)}}", 0, 0, 0}, +{"@f95", + "f951 %i %{E:%{!cpp:%egfortran does not support -E without -cpp}}\ + %{cpp:" F951_CPP_OPTIONS "} %{!E:" F951_OPTIONS "}", 0, 0, 0}, + + +#undef F951_SOURCE_FORM +#undef F951_CPP_OPTIONS +#undef F951_OPTIONS diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt index a3761925f01..f0f6c6a756d 100644 --- a/gcc/fortran/lang.opt +++ b/gcc/fortran/lang.opt @@ -25,6 +25,29 @@ Language Fortran +A +Fortran Joined Separate +; Documented in C + +C +Fortran +; Documented in C + +CC +Fortran +; Documented in C + +D +Fortran Joined Separate +; Documented in C + +E +Fortran Undocumented + +H +Fortran +; Documented in C + I Fortran Joined Separate -I Add a directory for INCLUDE and MODULE searching @@ -33,6 +56,14 @@ J Fortran Joined Separate -J Put MODULE files in 'directory' +P +Fortran +; Documented in C + +U +Fortran Joined Separate +; Documented in C + Wall Fortran ; Documented in C @@ -81,6 +112,18 @@ Wunderflow Fortran Warning Warn about underflow of numerical constant expressions +cpp +Fortran Joined Separate Negative(nocpp) +Enable preprocessing + +nocpp +Fortran Negative(cpp) +Disable preprocessing + +d +Fortran Joined +-d[DIMNU] Dump details about macro names and definitions during preprocessing + fall-intrinsics Fortran RejectNegative All intrinsics procedures are available regardless of selected standard @@ -289,6 +332,38 @@ funderscoring Fortran Append underscores to externally visible names +fworking-directory +Fortran +; Documented in C + +imultilib +Fortran Joined Separate +; Documented in C + +iprefix +Fortran Joined Separate +; Documented in C + +iquote +Fortran Joined Separate +; Documented in C + +isysroot +Fortran Joined Separate +; Documented in C + +isystem +Fortran Joined Separate +; Documented in C + +nostdinc +Fortran +; Documented in C + +o +Fortran Joined Separate +; Documented in common.opt + static-libgfortran Fortran Statically link the GNU Fortran helper library (libgfortran) @@ -313,4 +388,12 @@ std=legacy Fortran Accept extensions to support legacy code +undef +Fortran +; Documented in C + +v +Fortran +; Documented in C + ; This comment is to ensure we retain the blank line above. diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c index a1020bf35d4..e653ac92843 100644 --- a/gcc/fortran/options.c +++ b/gcc/fortran/options.c @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-inline.h" #include "gfortran.h" #include "target.h" +#include "cpp.h" gfc_option_t gfc_option; @@ -50,8 +51,7 @@ set_default_std_flags (void) /* Get ready for options handling. */ unsigned int -gfc_init_options (unsigned int argc ATTRIBUTE_UNUSED, - const char **argv ATTRIBUTE_UNUSED) +gfc_init_options (unsigned int argc, const char **argv) { gfc_source_file = NULL; gfc_option.module_dir = NULL; @@ -128,6 +128,9 @@ gfc_init_options (unsigned int argc ATTRIBUTE_UNUSED, /* -fshort-enums can be default on some targets. */ gfc_option.fshort_enums = targetm.default_short_enums (); + /* Initialize cpp-related options. */ + gfc_cpp_init_options(argc, argv); + return CL_Fortran; } @@ -354,6 +357,15 @@ gfc_post_options (const char **pfilename) if (gfc_option.flag_all_intrinsics) gfc_option.warn_nonstd_intrinsics = 0; + gfc_cpp_post_options (); + +/* FIXME: return gfc_cpp_preprocess_only (); + + The return value of this function indicates whether the + backend needs to be initialized. On -E, we don't need + the backend. However, if we return 'true' here, an + ICE occurs. Initializing the backend doesn't hurt much, + hence, for now we can live with it as is. */ return false; } @@ -452,6 +464,9 @@ gfc_handle_option (size_t scode, const char *arg, int value) if (code == N_OPTS) return 1; + if (gfc_cpp_handle_option (scode, arg, value) == 1) + return 1; + switch (code) { default: @@ -692,7 +707,7 @@ gfc_handle_option (size_t scode, const char *arg, int value) else gfc_fatal_error ("Unrecognized option to -finit-real: %s", arg); - break; + break; case OPT_finit_integer_: gfc_option.flag_init_integer = GFC_INIT_INTEGER_ON; diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c index 13e06155283..4c4a8b40670 100644 --- a/gcc/fortran/scanner.c +++ b/gcc/fortran/scanner.c @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" #include "debug.h" #include "flags.h" +#include "cpp.h" /* Structure for holding module and include file search path. */ typedef struct gfc_directorylist @@ -340,6 +341,7 @@ void gfc_add_include_path (const char *path, bool use_for_modules) { add_path_to_list (&include_dirs, path, use_for_modules); + gfc_cpp_add_include_path (xstrdup(path), true); } @@ -1909,7 +1911,14 @@ gfc_new_file (void) { try result; - result = load_file (gfc_source_file, true); + if (gfc_cpp_enabled ()) + { + result = gfc_cpp_preprocess (gfc_source_file); + if (!gfc_cpp_preprocess_only ()) + result = load_file (gfc_cpp_temporary_file (), true); + } + else + result = load_file (gfc_source_file, true); gfc_current_locus.lb = line_head; gfc_current_locus.nextc = (line_head == NULL) ? NULL : line_head->line; diff --git a/gcc/c-incpath.c b/gcc/incpath.c similarity index 99% rename from gcc/c-incpath.c rename to gcc/incpath.c index 4d055542820..e5fe8db23ca 100644 --- a/gcc/c-incpath.c +++ b/gcc/incpath.c @@ -28,7 +28,7 @@ #include "cpplib.h" #include "prefix.h" #include "intl.h" -#include "c-incpath.h" +#include "incpath.h" #include "cppdefault.h" /* Windows does not natively support inodes, and neither does MSDOS. diff --git a/gcc/c-incpath.h b/gcc/incpath.h similarity index 100% rename from gcc/c-incpath.h rename to gcc/incpath.h -- 2.30.2