1*4c3eb207Smrg /* Copyright (C) 2008-2020 Free Software Foundation, Inc.
2627f7eb2Smrg
3627f7eb2Smrg This file is part of GCC.
4627f7eb2Smrg
5627f7eb2Smrg GCC is free software; you can redistribute it and/or modify it under
6627f7eb2Smrg the terms of the GNU General Public License as published by the Free
7627f7eb2Smrg Software Foundation; either version 3, or (at your option) any later
8627f7eb2Smrg version.
9627f7eb2Smrg
10627f7eb2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11627f7eb2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
12627f7eb2Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13627f7eb2Smrg for more details.
14627f7eb2Smrg
15627f7eb2Smrg You should have received a copy of the GNU General Public License
16627f7eb2Smrg along with GCC; see the file COPYING3. If not see
17627f7eb2Smrg <http://www.gnu.org/licenses/>. */
18627f7eb2Smrg
19627f7eb2Smrg #include "config.h"
20627f7eb2Smrg #include "system.h"
21627f7eb2Smrg #include "coretypes.h"
22627f7eb2Smrg #include "target.h"
23627f7eb2Smrg #include "gfortran.h"
24627f7eb2Smrg #include "diagnostic.h"
25627f7eb2Smrg
26627f7eb2Smrg
27627f7eb2Smrg #include "toplev.h"
28627f7eb2Smrg
29627f7eb2Smrg #include "../../libcpp/internal.h"
30627f7eb2Smrg #include "cpp.h"
31627f7eb2Smrg #include "incpath.h"
32627f7eb2Smrg #include "cppbuiltin.h"
33627f7eb2Smrg #include "mkdeps.h"
34627f7eb2Smrg
35627f7eb2Smrg #ifndef TARGET_SYSTEM_ROOT
36627f7eb2Smrg # define TARGET_SYSTEM_ROOT NULL
37627f7eb2Smrg #endif
38627f7eb2Smrg
39627f7eb2Smrg #ifndef TARGET_CPU_CPP_BUILTINS
40627f7eb2Smrg # define TARGET_CPU_CPP_BUILTINS()
41627f7eb2Smrg #endif
42627f7eb2Smrg
43627f7eb2Smrg #ifndef TARGET_OS_CPP_BUILTINS
44627f7eb2Smrg # define TARGET_OS_CPP_BUILTINS()
45627f7eb2Smrg #endif
46627f7eb2Smrg
47627f7eb2Smrg #ifndef TARGET_OBJFMT_CPP_BUILTINS
48627f7eb2Smrg # define TARGET_OBJFMT_CPP_BUILTINS()
49627f7eb2Smrg #endif
50627f7eb2Smrg
51627f7eb2Smrg
52627f7eb2Smrg /* Holds switches parsed by gfc_cpp_handle_option (), but whose
53627f7eb2Smrg handling is deferred to gfc_cpp_init (). */
54627f7eb2Smrg typedef struct
55627f7eb2Smrg {
56627f7eb2Smrg enum opt_code code;
57627f7eb2Smrg const char *arg;
58627f7eb2Smrg }
59627f7eb2Smrg gfc_cpp_deferred_opt_t;
60627f7eb2Smrg
61627f7eb2Smrg
62627f7eb2Smrg /* Defined and undefined macros being queued for output with -dU at
63627f7eb2Smrg the next newline. */
64627f7eb2Smrg typedef struct gfc_cpp_macro_queue
65627f7eb2Smrg {
66627f7eb2Smrg struct gfc_cpp_macro_queue *next; /* Next macro in the list. */
67627f7eb2Smrg char *macro; /* The name of the macro if not
68627f7eb2Smrg defined, the full definition if
69627f7eb2Smrg defined. */
70627f7eb2Smrg } gfc_cpp_macro_queue;
71627f7eb2Smrg static gfc_cpp_macro_queue *cpp_define_queue, *cpp_undefine_queue;
72627f7eb2Smrg
73627f7eb2Smrg struct gfc_cpp_option_data
74627f7eb2Smrg {
75627f7eb2Smrg /* Argument of -cpp, implied by SPEC;
76627f7eb2Smrg if NULL, preprocessing disabled. */
77627f7eb2Smrg const char *temporary_filename;
78627f7eb2Smrg
79627f7eb2Smrg const char *output_filename; /* -o <arg> */
80627f7eb2Smrg int preprocess_only; /* -E */
81627f7eb2Smrg int discard_comments; /* -C */
82627f7eb2Smrg int discard_comments_in_macro_exp; /* -CC */
83627f7eb2Smrg int print_include_names; /* -H */
84627f7eb2Smrg int no_line_commands; /* -P */
85627f7eb2Smrg char dump_macros; /* -d[DMNU] */
86627f7eb2Smrg int dump_includes; /* -dI */
87627f7eb2Smrg int working_directory; /* -fworking-directory */
88627f7eb2Smrg int no_predefined; /* -undef */
89627f7eb2Smrg int standard_include_paths; /* -nostdinc */
90627f7eb2Smrg int verbose; /* -v */
91627f7eb2Smrg int deps; /* -M */
92627f7eb2Smrg int deps_skip_system; /* -MM */
93627f7eb2Smrg const char *deps_filename; /* -M[M]D */
94627f7eb2Smrg const char *deps_filename_user; /* -MF <arg> */
95627f7eb2Smrg int deps_missing_are_generated; /* -MG */
96627f7eb2Smrg int deps_phony; /* -MP */
97627f7eb2Smrg int warn_date_time; /* -Wdate-time */
98627f7eb2Smrg
99627f7eb2Smrg const char *multilib; /* -imultilib <dir> */
100627f7eb2Smrg const char *prefix; /* -iprefix <dir> */
101627f7eb2Smrg const char *sysroot; /* -isysroot <dir> */
102627f7eb2Smrg
103627f7eb2Smrg /* Options whose handling needs to be deferred until the
104627f7eb2Smrg appropriate cpp-objects are created:
105627f7eb2Smrg -A predicate=answer
106627f7eb2Smrg -D <macro>[=<val>]
107627f7eb2Smrg -U <macro> */
108627f7eb2Smrg gfc_cpp_deferred_opt_t *deferred_opt;
109627f7eb2Smrg int deferred_opt_count;
110627f7eb2Smrg }
111627f7eb2Smrg gfc_cpp_option;
112627f7eb2Smrg
113627f7eb2Smrg /* Structures used with libcpp: */
114627f7eb2Smrg static cpp_options *cpp_option = NULL;
115627f7eb2Smrg static cpp_reader *cpp_in = NULL;
116627f7eb2Smrg
117627f7eb2Smrg /* Encapsulates state used to convert a stream of cpp-tokens into
118627f7eb2Smrg a text file. */
119627f7eb2Smrg static struct
120627f7eb2Smrg {
121627f7eb2Smrg FILE *outf; /* Stream to write to. */
122627f7eb2Smrg const cpp_token *prev; /* Previous token. */
123627f7eb2Smrg const cpp_token *source; /* Source token for spacing. */
124627f7eb2Smrg int src_line; /* Line number currently being written. */
125627f7eb2Smrg unsigned char printed; /* Nonzero if something output at line. */
126627f7eb2Smrg bool first_time; /* cb_file_change hasn't been called yet. */
127627f7eb2Smrg } print;
128627f7eb2Smrg
129627f7eb2Smrg /* General output routines. */
130627f7eb2Smrg static void scan_translation_unit (cpp_reader *);
131627f7eb2Smrg static void scan_translation_unit_trad (cpp_reader *);
132627f7eb2Smrg
133627f7eb2Smrg /* Callback routines for the parser. Most of these are active only
134627f7eb2Smrg in specific modes. */
135627f7eb2Smrg static void cb_file_change (cpp_reader *, const line_map_ordinary *);
136627f7eb2Smrg static void cb_line_change (cpp_reader *, const cpp_token *, int);
137627f7eb2Smrg static void cb_define (cpp_reader *, location_t, cpp_hashnode *);
138627f7eb2Smrg static void cb_undef (cpp_reader *, location_t, cpp_hashnode *);
139627f7eb2Smrg static void cb_def_pragma (cpp_reader *, location_t);
140627f7eb2Smrg static void cb_include (cpp_reader *, location_t, const unsigned char *,
141627f7eb2Smrg const char *, int, const cpp_token **);
142627f7eb2Smrg static void cb_ident (cpp_reader *, location_t, const cpp_string *);
143627f7eb2Smrg static void cb_used_define (cpp_reader *, location_t, cpp_hashnode *);
144627f7eb2Smrg static void cb_used_undef (cpp_reader *, location_t, cpp_hashnode *);
145627f7eb2Smrg static bool cb_cpp_diagnostic (cpp_reader *, enum cpp_diagnostic_level,
146627f7eb2Smrg enum cpp_warning_reason, rich_location *,
147627f7eb2Smrg const char *, va_list *)
148627f7eb2Smrg ATTRIBUTE_GCC_DIAG(5,0);
149627f7eb2Smrg void pp_dir_change (cpp_reader *, const char *);
150627f7eb2Smrg
151627f7eb2Smrg static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
152627f7eb2Smrg static void dump_queued_macros (cpp_reader *);
153627f7eb2Smrg
154627f7eb2Smrg
155627f7eb2Smrg static void
cpp_define_builtins(cpp_reader * pfile)156627f7eb2Smrg cpp_define_builtins (cpp_reader *pfile)
157627f7eb2Smrg {
158627f7eb2Smrg /* Initialize CPP built-ins; '1' corresponds to 'flag_hosted'
159627f7eb2Smrg in C, defines __STDC_HOSTED__?! */
160627f7eb2Smrg cpp_init_builtins (pfile, 0);
161627f7eb2Smrg
162627f7eb2Smrg /* Initialize GFORTRAN specific builtins.
163627f7eb2Smrg These are documented. */
164627f7eb2Smrg define_language_independent_builtin_macros (pfile);
165627f7eb2Smrg cpp_define (pfile, "__GFORTRAN__=1");
166627f7eb2Smrg cpp_define (pfile, "_LANGUAGE_FORTRAN=1");
167627f7eb2Smrg
168627f7eb2Smrg if (flag_openacc)
169*4c3eb207Smrg cpp_define (pfile, "_OPENACC=201711");
170627f7eb2Smrg
171627f7eb2Smrg if (flag_openmp)
172627f7eb2Smrg cpp_define (pfile, "_OPENMP=201511");
173627f7eb2Smrg
174627f7eb2Smrg /* The defines below are necessary for the TARGET_* macros.
175627f7eb2Smrg
176627f7eb2Smrg FIXME: Note that builtin_define_std() actually is a function
177627f7eb2Smrg in c-cppbuiltin.c which uses flags undefined for Fortran.
178627f7eb2Smrg Let's skip this for now. If needed, one needs to look into it
179627f7eb2Smrg once more. */
180627f7eb2Smrg
181627f7eb2Smrg # define builtin_define(TXT) cpp_define (pfile, TXT)
182627f7eb2Smrg # define builtin_define_std(TXT)
183627f7eb2Smrg # define builtin_assert(TXT) cpp_assert (pfile, TXT)
184627f7eb2Smrg
185627f7eb2Smrg /* FIXME: Pandora's Box
186627f7eb2Smrg Using the macros below results in multiple breakages:
187627f7eb2Smrg - mingw will fail to compile this file as dependent macros
188627f7eb2Smrg assume to be used in c-cppbuiltin.c only. Further, they use
189627f7eb2Smrg flags only valid/defined in C (same as noted above).
190627f7eb2Smrg [config/i386/mingw32.h, config/i386/cygming.h]
191627f7eb2Smrg - other platforms (not as popular) break similarly
192627f7eb2Smrg [grep for 'builtin_define_with_int_value' in gcc/config/]
193627f7eb2Smrg
194627f7eb2Smrg TARGET_CPU_CPP_BUILTINS ();
195627f7eb2Smrg TARGET_OS_CPP_BUILTINS ();
196627f7eb2Smrg TARGET_OBJFMT_CPP_BUILTINS (); */
197627f7eb2Smrg
198627f7eb2Smrg #undef builtin_define
199627f7eb2Smrg #undef builtin_define_std
200627f7eb2Smrg #undef builtin_assert
201627f7eb2Smrg }
202627f7eb2Smrg
203627f7eb2Smrg bool
gfc_cpp_enabled(void)204627f7eb2Smrg gfc_cpp_enabled (void)
205627f7eb2Smrg {
206627f7eb2Smrg return gfc_cpp_option.temporary_filename != NULL;
207627f7eb2Smrg }
208627f7eb2Smrg
209627f7eb2Smrg bool
gfc_cpp_preprocess_only(void)210627f7eb2Smrg gfc_cpp_preprocess_only (void)
211627f7eb2Smrg {
212627f7eb2Smrg return gfc_cpp_option.preprocess_only;
213627f7eb2Smrg }
214627f7eb2Smrg
215627f7eb2Smrg bool
gfc_cpp_makedep(void)216627f7eb2Smrg gfc_cpp_makedep (void)
217627f7eb2Smrg {
218627f7eb2Smrg return gfc_cpp_option.deps;
219627f7eb2Smrg }
220627f7eb2Smrg
221627f7eb2Smrg void
gfc_cpp_add_dep(const char * name,bool system)222627f7eb2Smrg gfc_cpp_add_dep (const char *name, bool system)
223627f7eb2Smrg {
224627f7eb2Smrg if (!gfc_cpp_option.deps_skip_system || !system)
225627f7eb2Smrg deps_add_dep (cpp_get_deps (cpp_in), name);
226627f7eb2Smrg }
227627f7eb2Smrg
228627f7eb2Smrg void
gfc_cpp_add_target(const char * name)229627f7eb2Smrg gfc_cpp_add_target (const char *name)
230627f7eb2Smrg {
231627f7eb2Smrg deps_add_target (cpp_get_deps (cpp_in), name, 0);
232627f7eb2Smrg }
233627f7eb2Smrg
234627f7eb2Smrg
235627f7eb2Smrg const char *
gfc_cpp_temporary_file(void)236627f7eb2Smrg gfc_cpp_temporary_file (void)
237627f7eb2Smrg {
238627f7eb2Smrg return gfc_cpp_option.temporary_filename;
239627f7eb2Smrg }
240627f7eb2Smrg
241627f7eb2Smrg void
gfc_cpp_init_options(unsigned int decoded_options_count,struct cl_decoded_option * decoded_options ATTRIBUTE_UNUSED)242627f7eb2Smrg gfc_cpp_init_options (unsigned int decoded_options_count,
243627f7eb2Smrg struct cl_decoded_option *decoded_options ATTRIBUTE_UNUSED)
244627f7eb2Smrg {
245627f7eb2Smrg /* Do not create any objects from libcpp here. If no
246627f7eb2Smrg preprocessing is requested, this would be wasted
247627f7eb2Smrg time and effort.
248627f7eb2Smrg
249627f7eb2Smrg See gfc_cpp_post_options() instead. */
250627f7eb2Smrg
251627f7eb2Smrg gfc_cpp_option.temporary_filename = NULL;
252627f7eb2Smrg gfc_cpp_option.output_filename = NULL;
253627f7eb2Smrg gfc_cpp_option.preprocess_only = 0;
254627f7eb2Smrg gfc_cpp_option.discard_comments = 1;
255627f7eb2Smrg gfc_cpp_option.discard_comments_in_macro_exp = 1;
256627f7eb2Smrg gfc_cpp_option.print_include_names = 0;
257627f7eb2Smrg gfc_cpp_option.no_line_commands = 0;
258627f7eb2Smrg gfc_cpp_option.dump_macros = '\0';
259627f7eb2Smrg gfc_cpp_option.dump_includes = 0;
260627f7eb2Smrg gfc_cpp_option.working_directory = -1;
261627f7eb2Smrg gfc_cpp_option.no_predefined = 0;
262627f7eb2Smrg gfc_cpp_option.standard_include_paths = 1;
263627f7eb2Smrg gfc_cpp_option.verbose = 0;
264627f7eb2Smrg gfc_cpp_option.warn_date_time = 0;
265627f7eb2Smrg gfc_cpp_option.deps = 0;
266627f7eb2Smrg gfc_cpp_option.deps_skip_system = 0;
267627f7eb2Smrg gfc_cpp_option.deps_phony = 0;
268627f7eb2Smrg gfc_cpp_option.deps_missing_are_generated = 0;
269627f7eb2Smrg gfc_cpp_option.deps_filename = NULL;
270627f7eb2Smrg gfc_cpp_option.deps_filename_user = NULL;
271627f7eb2Smrg
272627f7eb2Smrg gfc_cpp_option.multilib = NULL;
273627f7eb2Smrg gfc_cpp_option.prefix = NULL;
274627f7eb2Smrg gfc_cpp_option.sysroot = TARGET_SYSTEM_ROOT;
275627f7eb2Smrg
276627f7eb2Smrg gfc_cpp_option.deferred_opt = XNEWVEC (gfc_cpp_deferred_opt_t,
277627f7eb2Smrg decoded_options_count);
278627f7eb2Smrg gfc_cpp_option.deferred_opt_count = 0;
279627f7eb2Smrg }
280627f7eb2Smrg
281627f7eb2Smrg int
gfc_cpp_handle_option(size_t scode,const char * arg,int value ATTRIBUTE_UNUSED)282627f7eb2Smrg gfc_cpp_handle_option (size_t scode, const char *arg, int value ATTRIBUTE_UNUSED)
283627f7eb2Smrg {
284627f7eb2Smrg int result = 1;
285627f7eb2Smrg enum opt_code code = (enum opt_code) scode;
286627f7eb2Smrg
287627f7eb2Smrg switch (code)
288627f7eb2Smrg {
289627f7eb2Smrg default:
290627f7eb2Smrg result = 0;
291627f7eb2Smrg break;
292627f7eb2Smrg
293627f7eb2Smrg case OPT_cpp_:
294627f7eb2Smrg gfc_cpp_option.temporary_filename = arg;
295627f7eb2Smrg break;
296627f7eb2Smrg
297627f7eb2Smrg case OPT_nocpp:
298627f7eb2Smrg gfc_cpp_option.temporary_filename = 0L;
299627f7eb2Smrg break;
300627f7eb2Smrg
301627f7eb2Smrg case OPT_d:
302627f7eb2Smrg for ( ; *arg; ++arg)
303627f7eb2Smrg switch (*arg)
304627f7eb2Smrg {
305627f7eb2Smrg case 'D':
306627f7eb2Smrg case 'M':
307627f7eb2Smrg case 'N':
308627f7eb2Smrg case 'U':
309627f7eb2Smrg gfc_cpp_option.dump_macros = *arg;
310627f7eb2Smrg break;
311627f7eb2Smrg
312627f7eb2Smrg case 'I':
313627f7eb2Smrg gfc_cpp_option.dump_includes = 1;
314627f7eb2Smrg break;
315627f7eb2Smrg }
316627f7eb2Smrg break;
317627f7eb2Smrg
318627f7eb2Smrg case OPT_fworking_directory:
319627f7eb2Smrg gfc_cpp_option.working_directory = value;
320627f7eb2Smrg break;
321627f7eb2Smrg
322627f7eb2Smrg case OPT_idirafter:
323627f7eb2Smrg gfc_cpp_add_include_path_after (xstrdup(arg), true);
324627f7eb2Smrg break;
325627f7eb2Smrg
326627f7eb2Smrg case OPT_imultilib:
327627f7eb2Smrg gfc_cpp_option.multilib = arg;
328627f7eb2Smrg break;
329627f7eb2Smrg
330627f7eb2Smrg case OPT_iprefix:
331627f7eb2Smrg gfc_cpp_option.prefix = arg;
332627f7eb2Smrg break;
333627f7eb2Smrg
334627f7eb2Smrg case OPT_isysroot:
335627f7eb2Smrg gfc_cpp_option.sysroot = arg;
336627f7eb2Smrg break;
337627f7eb2Smrg
338627f7eb2Smrg case OPT_iquote:
339627f7eb2Smrg case OPT_isystem:
340627f7eb2Smrg gfc_cpp_add_include_path (xstrdup(arg), true);
341627f7eb2Smrg break;
342627f7eb2Smrg
343627f7eb2Smrg case OPT_nostdinc:
344627f7eb2Smrg gfc_cpp_option.standard_include_paths = value;
345627f7eb2Smrg break;
346627f7eb2Smrg
347627f7eb2Smrg case OPT_o:
348627f7eb2Smrg if (!gfc_cpp_option.output_filename)
349627f7eb2Smrg gfc_cpp_option.output_filename = arg;
350627f7eb2Smrg else
351627f7eb2Smrg gfc_fatal_error ("output filename specified twice");
352627f7eb2Smrg break;
353627f7eb2Smrg
354627f7eb2Smrg case OPT_undef:
355627f7eb2Smrg gfc_cpp_option.no_predefined = value;
356627f7eb2Smrg break;
357627f7eb2Smrg
358627f7eb2Smrg case OPT_v:
359627f7eb2Smrg gfc_cpp_option.verbose = value;
360627f7eb2Smrg break;
361627f7eb2Smrg
362627f7eb2Smrg case OPT_Wdate_time:
363627f7eb2Smrg gfc_cpp_option.warn_date_time = value;
364627f7eb2Smrg break;
365627f7eb2Smrg
366627f7eb2Smrg case OPT_A:
367627f7eb2Smrg case OPT_D:
368627f7eb2Smrg case OPT_U:
369627f7eb2Smrg gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].code = code;
370627f7eb2Smrg gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].arg = arg;
371627f7eb2Smrg gfc_cpp_option.deferred_opt_count++;
372627f7eb2Smrg break;
373627f7eb2Smrg
374627f7eb2Smrg case OPT_C:
375627f7eb2Smrg gfc_cpp_option.discard_comments = 0;
376627f7eb2Smrg break;
377627f7eb2Smrg
378627f7eb2Smrg case OPT_CC:
379627f7eb2Smrg gfc_cpp_option.discard_comments = 0;
380627f7eb2Smrg gfc_cpp_option.discard_comments_in_macro_exp = 0;
381627f7eb2Smrg break;
382627f7eb2Smrg
383627f7eb2Smrg case OPT_E:
384627f7eb2Smrg gfc_cpp_option.preprocess_only = 1;
385627f7eb2Smrg break;
386627f7eb2Smrg
387627f7eb2Smrg case OPT_H:
388627f7eb2Smrg gfc_cpp_option.print_include_names = 1;
389627f7eb2Smrg break;
390627f7eb2Smrg
391627f7eb2Smrg case OPT_MM:
392627f7eb2Smrg gfc_cpp_option.deps_skip_system = 1;
393627f7eb2Smrg /* fall through */
394627f7eb2Smrg
395627f7eb2Smrg case OPT_M:
396627f7eb2Smrg gfc_cpp_option.deps = 1;
397627f7eb2Smrg break;
398627f7eb2Smrg
399627f7eb2Smrg case OPT_MMD:
400627f7eb2Smrg gfc_cpp_option.deps_skip_system = 1;
401627f7eb2Smrg /* fall through */
402627f7eb2Smrg
403627f7eb2Smrg case OPT_MD:
404627f7eb2Smrg gfc_cpp_option.deps = 1;
405627f7eb2Smrg gfc_cpp_option.deps_filename = arg;
406627f7eb2Smrg break;
407627f7eb2Smrg
408627f7eb2Smrg case OPT_MF:
409627f7eb2Smrg /* If specified multiple times, last one wins. */
410627f7eb2Smrg gfc_cpp_option.deps_filename_user = arg;
411627f7eb2Smrg break;
412627f7eb2Smrg
413627f7eb2Smrg case OPT_MG:
414627f7eb2Smrg gfc_cpp_option.deps_missing_are_generated = 1;
415627f7eb2Smrg break;
416627f7eb2Smrg
417627f7eb2Smrg case OPT_MP:
418627f7eb2Smrg gfc_cpp_option.deps_phony = 1;
419627f7eb2Smrg break;
420627f7eb2Smrg
421627f7eb2Smrg case OPT_MQ:
422627f7eb2Smrg case OPT_MT:
423627f7eb2Smrg gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].code = code;
424627f7eb2Smrg gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].arg = arg;
425627f7eb2Smrg gfc_cpp_option.deferred_opt_count++;
426627f7eb2Smrg break;
427627f7eb2Smrg
428627f7eb2Smrg case OPT_P:
429627f7eb2Smrg gfc_cpp_option.no_line_commands = 1;
430627f7eb2Smrg break;
431627f7eb2Smrg }
432627f7eb2Smrg
433627f7eb2Smrg return result;
434627f7eb2Smrg }
435627f7eb2Smrg
436627f7eb2Smrg
437627f7eb2Smrg void
gfc_cpp_post_options(void)438627f7eb2Smrg gfc_cpp_post_options (void)
439627f7eb2Smrg {
440627f7eb2Smrg /* Any preprocessing-related option without '-cpp' is considered
441627f7eb2Smrg an error. */
442627f7eb2Smrg if (!gfc_cpp_enabled ()
443627f7eb2Smrg && (gfc_cpp_preprocess_only ()
444627f7eb2Smrg || gfc_cpp_makedep ()
445627f7eb2Smrg || !gfc_cpp_option.discard_comments
446627f7eb2Smrg || !gfc_cpp_option.discard_comments_in_macro_exp
447627f7eb2Smrg || gfc_cpp_option.print_include_names
448627f7eb2Smrg || gfc_cpp_option.no_line_commands
449627f7eb2Smrg || gfc_cpp_option.dump_macros
450627f7eb2Smrg || gfc_cpp_option.dump_includes))
451627f7eb2Smrg gfc_fatal_error ("To enable preprocessing, use %<-cpp%>");
452627f7eb2Smrg
453627f7eb2Smrg if (!gfc_cpp_enabled ())
454627f7eb2Smrg return;
455627f7eb2Smrg
456627f7eb2Smrg cpp_in = cpp_create_reader (CLK_GNUC89, NULL, line_table);
457627f7eb2Smrg gcc_assert (cpp_in);
458627f7eb2Smrg
459627f7eb2Smrg /* The cpp_options-structure defines far more flags than those set here.
460627f7eb2Smrg If any other is implemented, see c-opt.c (sanitize_cpp_opts) for
461627f7eb2Smrg inter-option dependencies that may need to be enforced. */
462627f7eb2Smrg cpp_option = cpp_get_options (cpp_in);
463627f7eb2Smrg gcc_assert (cpp_option);
464627f7eb2Smrg
465627f7eb2Smrg /* TODO: allow non-traditional modes, e.g. by -cpp-std=...? */
466627f7eb2Smrg cpp_option->traditional = 1;
467627f7eb2Smrg cpp_option->cplusplus_comments = 0;
468627f7eb2Smrg
469627f7eb2Smrg cpp_option->cpp_pedantic = pedantic;
470627f7eb2Smrg
471627f7eb2Smrg cpp_option->dollars_in_ident = flag_dollar_ok;
472627f7eb2Smrg cpp_option->discard_comments = gfc_cpp_option.discard_comments;
473627f7eb2Smrg cpp_option->discard_comments_in_macro_exp = gfc_cpp_option.discard_comments_in_macro_exp;
474627f7eb2Smrg cpp_option->print_include_names = gfc_cpp_option.print_include_names;
475627f7eb2Smrg cpp_option->preprocessed = gfc_option.flag_preprocessed;
476627f7eb2Smrg cpp_option->warn_date_time = gfc_cpp_option.warn_date_time;
477627f7eb2Smrg
478627f7eb2Smrg if (gfc_cpp_makedep ())
479627f7eb2Smrg {
480627f7eb2Smrg cpp_option->deps.style = DEPS_USER;
481627f7eb2Smrg cpp_option->deps.phony_targets = gfc_cpp_option.deps_phony;
482627f7eb2Smrg cpp_option->deps.missing_files = gfc_cpp_option.deps_missing_are_generated;
483627f7eb2Smrg
484627f7eb2Smrg /* -MF <arg> overrides -M[M]D. */
485627f7eb2Smrg if (gfc_cpp_option.deps_filename_user)
486627f7eb2Smrg gfc_cpp_option.deps_filename = gfc_cpp_option.deps_filename_user;
487627f7eb2Smrg }
488627f7eb2Smrg
489627f7eb2Smrg if (gfc_cpp_option.working_directory == -1)
490627f7eb2Smrg gfc_cpp_option.working_directory = (debug_info_level != DINFO_LEVEL_NONE);
491627f7eb2Smrg
492627f7eb2Smrg cpp_post_options (cpp_in);
493627f7eb2Smrg
494627f7eb2Smrg gfc_cpp_register_include_paths ();
495627f7eb2Smrg }
496627f7eb2Smrg
497627f7eb2Smrg
498627f7eb2Smrg void
gfc_cpp_init_0(void)499627f7eb2Smrg gfc_cpp_init_0 (void)
500627f7eb2Smrg {
501627f7eb2Smrg struct cpp_callbacks *cb;
502627f7eb2Smrg
503627f7eb2Smrg cb = cpp_get_callbacks (cpp_in);
504627f7eb2Smrg cb->file_change = cb_file_change;
505627f7eb2Smrg cb->line_change = cb_line_change;
506627f7eb2Smrg cb->ident = cb_ident;
507627f7eb2Smrg cb->def_pragma = cb_def_pragma;
508627f7eb2Smrg cb->diagnostic = cb_cpp_diagnostic;
509627f7eb2Smrg
510627f7eb2Smrg if (gfc_cpp_option.dump_includes)
511627f7eb2Smrg cb->include = cb_include;
512627f7eb2Smrg
513627f7eb2Smrg if ((gfc_cpp_option.dump_macros == 'D')
514627f7eb2Smrg || (gfc_cpp_option.dump_macros == 'N'))
515627f7eb2Smrg {
516627f7eb2Smrg cb->define = cb_define;
517627f7eb2Smrg cb->undef = cb_undef;
518627f7eb2Smrg }
519627f7eb2Smrg
520627f7eb2Smrg if (gfc_cpp_option.dump_macros == 'U')
521627f7eb2Smrg {
522627f7eb2Smrg cb->before_define = dump_queued_macros;
523627f7eb2Smrg cb->used_define = cb_used_define;
524627f7eb2Smrg cb->used_undef = cb_used_undef;
525627f7eb2Smrg }
526627f7eb2Smrg
527627f7eb2Smrg /* Initialize the print structure. Setting print.src_line to -1 here is
528627f7eb2Smrg a trick to guarantee that the first token of the file will cause
529627f7eb2Smrg a linemarker to be output by maybe_print_line. */
530627f7eb2Smrg print.src_line = -1;
531627f7eb2Smrg print.printed = 0;
532627f7eb2Smrg print.prev = 0;
533627f7eb2Smrg print.first_time = 1;
534627f7eb2Smrg
535627f7eb2Smrg if (gfc_cpp_preprocess_only ())
536627f7eb2Smrg {
537627f7eb2Smrg if (gfc_cpp_option.output_filename)
538627f7eb2Smrg {
539627f7eb2Smrg /* This needs cheating: with "-E -o <file>", the user wants the
540627f7eb2Smrg preprocessed output in <file>. However, if nothing is done
541627f7eb2Smrg about it <file> is also used for assembler output. Hence, it
542627f7eb2Smrg is necessary to redirect assembler output (actually nothing
543627f7eb2Smrg as -E implies -fsyntax-only) to another file, otherwise the
544627f7eb2Smrg output from preprocessing is lost. */
545627f7eb2Smrg asm_file_name = gfc_cpp_option.temporary_filename;
546627f7eb2Smrg
547627f7eb2Smrg print.outf = fopen (gfc_cpp_option.output_filename, "w");
548627f7eb2Smrg if (print.outf == NULL)
549627f7eb2Smrg gfc_fatal_error ("opening output file %qs: %s",
550627f7eb2Smrg gfc_cpp_option.output_filename,
551627f7eb2Smrg xstrerror (errno));
552627f7eb2Smrg }
553627f7eb2Smrg else
554627f7eb2Smrg print.outf = stdout;
555627f7eb2Smrg }
556627f7eb2Smrg else
557627f7eb2Smrg {
558627f7eb2Smrg print.outf = fopen (gfc_cpp_option.temporary_filename, "w");
559627f7eb2Smrg if (print.outf == NULL)
560627f7eb2Smrg gfc_fatal_error ("opening output file %qs: %s",
561627f7eb2Smrg gfc_cpp_option.temporary_filename, xstrerror (errno));
562627f7eb2Smrg }
563627f7eb2Smrg
564627f7eb2Smrg gcc_assert(cpp_in);
565627f7eb2Smrg if (!cpp_read_main_file (cpp_in, gfc_source_file))
566627f7eb2Smrg errorcount++;
567627f7eb2Smrg }
568627f7eb2Smrg
569627f7eb2Smrg void
gfc_cpp_init(void)570627f7eb2Smrg gfc_cpp_init (void)
571627f7eb2Smrg {
572627f7eb2Smrg int i;
573627f7eb2Smrg
574627f7eb2Smrg if (gfc_option.flag_preprocessed)
575627f7eb2Smrg return;
576627f7eb2Smrg
577627f7eb2Smrg cpp_change_file (cpp_in, LC_RENAME, _("<built-in>"));
578627f7eb2Smrg if (!gfc_cpp_option.no_predefined)
579627f7eb2Smrg {
580627f7eb2Smrg /* Make sure all of the builtins about to be declared have
581627f7eb2Smrg BUILTINS_LOCATION has their location_t. */
582627f7eb2Smrg cpp_force_token_locations (cpp_in, BUILTINS_LOCATION);
583627f7eb2Smrg
584627f7eb2Smrg cpp_define_builtins (cpp_in);
585627f7eb2Smrg
586627f7eb2Smrg cpp_stop_forcing_token_locations (cpp_in);
587627f7eb2Smrg }
588627f7eb2Smrg
589627f7eb2Smrg /* Handle deferred options from command-line. */
590627f7eb2Smrg cpp_change_file (cpp_in, LC_RENAME, _("<command-line>"));
591627f7eb2Smrg
592627f7eb2Smrg for (i = 0; i < gfc_cpp_option.deferred_opt_count; i++)
593627f7eb2Smrg {
594627f7eb2Smrg gfc_cpp_deferred_opt_t *opt = &gfc_cpp_option.deferred_opt[i];
595627f7eb2Smrg
596627f7eb2Smrg if (opt->code == OPT_D)
597627f7eb2Smrg cpp_define (cpp_in, opt->arg);
598627f7eb2Smrg else if (opt->code == OPT_U)
599627f7eb2Smrg cpp_undef (cpp_in, opt->arg);
600627f7eb2Smrg else if (opt->code == OPT_A)
601627f7eb2Smrg {
602627f7eb2Smrg if (opt->arg[0] == '-')
603627f7eb2Smrg cpp_unassert (cpp_in, opt->arg + 1);
604627f7eb2Smrg else
605627f7eb2Smrg cpp_assert (cpp_in, opt->arg);
606627f7eb2Smrg }
607627f7eb2Smrg else if (opt->code == OPT_MT || opt->code == OPT_MQ)
608627f7eb2Smrg deps_add_target (cpp_get_deps (cpp_in),
609627f7eb2Smrg opt->arg, opt->code == OPT_MQ);
610627f7eb2Smrg }
611627f7eb2Smrg
612627f7eb2Smrg /* Pre-defined macros for non-required INTEGER kind types. */
613627f7eb2Smrg for (gfc_integer_info *itype = gfc_integer_kinds; itype->kind != 0; itype++)
614627f7eb2Smrg {
615627f7eb2Smrg if (itype->kind == 1)
616627f7eb2Smrg cpp_define (cpp_in, "__GFC_INT_1__=1");
617627f7eb2Smrg if (itype->kind == 2)
618627f7eb2Smrg cpp_define (cpp_in, "__GFC_INT_2__=1");
619627f7eb2Smrg if (itype->kind == 8)
620627f7eb2Smrg cpp_define (cpp_in, "__GFC_INT_8__=1");
621627f7eb2Smrg if (itype->kind == 16)
622627f7eb2Smrg cpp_define (cpp_in, "__GFC_INT_16__=1");
623627f7eb2Smrg }
624627f7eb2Smrg
625627f7eb2Smrg /* Pre-defined macros for non-required REAL kind types. */
626627f7eb2Smrg for (gfc_real_info *rtype = gfc_real_kinds; rtype->kind != 0; rtype++)
627627f7eb2Smrg {
628627f7eb2Smrg if (rtype->kind == 10)
629627f7eb2Smrg cpp_define (cpp_in, "__GFC_REAL_10__=1");
630627f7eb2Smrg if (rtype->kind == 16)
631627f7eb2Smrg cpp_define (cpp_in, "__GFC_REAL_16__=1");
632627f7eb2Smrg }
633627f7eb2Smrg
634627f7eb2Smrg if (gfc_cpp_option.working_directory
635627f7eb2Smrg && gfc_cpp_option.preprocess_only && !gfc_cpp_option.no_line_commands)
636627f7eb2Smrg pp_dir_change (cpp_in, get_src_pwd ());
637627f7eb2Smrg }
638627f7eb2Smrg
639627f7eb2Smrg bool
gfc_cpp_preprocess(const char * source_file)640627f7eb2Smrg gfc_cpp_preprocess (const char *source_file)
641627f7eb2Smrg {
642627f7eb2Smrg if (!gfc_cpp_enabled ())
643627f7eb2Smrg return false;
644627f7eb2Smrg
645627f7eb2Smrg cpp_change_file (cpp_in, LC_RENAME, source_file);
646627f7eb2Smrg
647627f7eb2Smrg if (cpp_option->traditional)
648627f7eb2Smrg scan_translation_unit_trad (cpp_in);
649627f7eb2Smrg else
650627f7eb2Smrg scan_translation_unit (cpp_in);
651627f7eb2Smrg
652627f7eb2Smrg /* -dM command line option. */
653627f7eb2Smrg if (gfc_cpp_preprocess_only () &&
654627f7eb2Smrg gfc_cpp_option.dump_macros == 'M')
655627f7eb2Smrg {
656627f7eb2Smrg putc ('\n', print.outf);
657627f7eb2Smrg cpp_forall_identifiers (cpp_in, dump_macro, NULL);
658627f7eb2Smrg }
659627f7eb2Smrg
660627f7eb2Smrg putc ('\n', print.outf);
661627f7eb2Smrg
662627f7eb2Smrg if (!gfc_cpp_preprocess_only ()
663627f7eb2Smrg || (gfc_cpp_preprocess_only () && gfc_cpp_option.output_filename))
664627f7eb2Smrg fclose (print.outf);
665627f7eb2Smrg
666627f7eb2Smrg return true;
667627f7eb2Smrg }
668627f7eb2Smrg
669627f7eb2Smrg void
gfc_cpp_done(void)670627f7eb2Smrg gfc_cpp_done (void)
671627f7eb2Smrg {
672627f7eb2Smrg if (!gfc_cpp_enabled ())
673627f7eb2Smrg return;
674627f7eb2Smrg
675627f7eb2Smrg gcc_assert (cpp_in);
676627f7eb2Smrg
677627f7eb2Smrg if (gfc_cpp_makedep ())
678627f7eb2Smrg {
679627f7eb2Smrg if (gfc_cpp_option.deps_filename)
680627f7eb2Smrg {
681627f7eb2Smrg FILE *f = fopen (gfc_cpp_option.deps_filename, "w");
682627f7eb2Smrg if (f)
683627f7eb2Smrg {
684627f7eb2Smrg cpp_finish (cpp_in, f);
685627f7eb2Smrg fclose (f);
686627f7eb2Smrg }
687627f7eb2Smrg else
688627f7eb2Smrg gfc_fatal_error ("opening output file %qs: %s",
689627f7eb2Smrg gfc_cpp_option.deps_filename,
690627f7eb2Smrg xstrerror (errno));
691627f7eb2Smrg }
692627f7eb2Smrg else
693627f7eb2Smrg cpp_finish (cpp_in, stdout);
694627f7eb2Smrg }
695627f7eb2Smrg
696627f7eb2Smrg cpp_undef_all (cpp_in);
697627f7eb2Smrg cpp_clear_file_cache (cpp_in);
698627f7eb2Smrg }
699627f7eb2Smrg
700627f7eb2Smrg /* PATH must be malloc-ed and NULL-terminated. */
701627f7eb2Smrg void
gfc_cpp_add_include_path(char * path,bool user_supplied)702627f7eb2Smrg gfc_cpp_add_include_path (char *path, bool user_supplied)
703627f7eb2Smrg {
704627f7eb2Smrg /* CHAIN sets cpp_dir->sysp which differs from 0 if PATH is a system
705627f7eb2Smrg include path. Fortran does not define any system include paths. */
706627f7eb2Smrg int cxx_aware = 0;
707627f7eb2Smrg
708627f7eb2Smrg add_path (path, INC_BRACKET, cxx_aware, user_supplied);
709627f7eb2Smrg }
710627f7eb2Smrg
711627f7eb2Smrg void
gfc_cpp_add_include_path_after(char * path,bool user_supplied)712627f7eb2Smrg gfc_cpp_add_include_path_after (char *path, bool user_supplied)
713627f7eb2Smrg {
714627f7eb2Smrg int cxx_aware = 0;
715627f7eb2Smrg add_path (path, INC_AFTER, cxx_aware, user_supplied);
716627f7eb2Smrg }
717627f7eb2Smrg
718627f7eb2Smrg void
gfc_cpp_register_include_paths(void)719627f7eb2Smrg gfc_cpp_register_include_paths (void)
720627f7eb2Smrg {
721627f7eb2Smrg int cxx_stdinc = 0;
722627f7eb2Smrg register_include_chains (cpp_in, gfc_cpp_option.sysroot,
723627f7eb2Smrg gfc_cpp_option.prefix, gfc_cpp_option.multilib,
724627f7eb2Smrg gfc_cpp_option.standard_include_paths, cxx_stdinc,
725627f7eb2Smrg gfc_cpp_option.verbose);
726627f7eb2Smrg }
727627f7eb2Smrg
728627f7eb2Smrg
729627f7eb2Smrg
730627f7eb2Smrg static void scan_translation_unit_trad (cpp_reader *);
731627f7eb2Smrg static void account_for_newlines (const unsigned char *, size_t);
732627f7eb2Smrg static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
733627f7eb2Smrg
734627f7eb2Smrg static void print_line (location_t, const char *);
735627f7eb2Smrg static void maybe_print_line (location_t);
736627f7eb2Smrg
737627f7eb2Smrg
738627f7eb2Smrg /* Writes out the preprocessed file, handling spacing and paste
739627f7eb2Smrg avoidance issues. */
740627f7eb2Smrg static void
scan_translation_unit(cpp_reader * pfile)741627f7eb2Smrg scan_translation_unit (cpp_reader *pfile)
742627f7eb2Smrg {
743627f7eb2Smrg bool avoid_paste = false;
744627f7eb2Smrg
745627f7eb2Smrg print.source = NULL;
746627f7eb2Smrg for (;;)
747627f7eb2Smrg {
748627f7eb2Smrg const cpp_token *token = cpp_get_token (pfile);
749627f7eb2Smrg
750627f7eb2Smrg if (token->type == CPP_PADDING)
751627f7eb2Smrg {
752627f7eb2Smrg avoid_paste = true;
753627f7eb2Smrg if (print.source == NULL
754627f7eb2Smrg || (!(print.source->flags & PREV_WHITE)
755627f7eb2Smrg && token->val.source == NULL))
756627f7eb2Smrg print.source = token->val.source;
757627f7eb2Smrg continue;
758627f7eb2Smrg }
759627f7eb2Smrg
760627f7eb2Smrg if (token->type == CPP_EOF)
761627f7eb2Smrg break;
762627f7eb2Smrg
763627f7eb2Smrg /* Subtle logic to output a space if and only if necessary. */
764627f7eb2Smrg if (avoid_paste)
765627f7eb2Smrg {
766627f7eb2Smrg if (print.source == NULL)
767627f7eb2Smrg print.source = token;
768627f7eb2Smrg if (print.source->flags & PREV_WHITE
769627f7eb2Smrg || (print.prev
770627f7eb2Smrg && cpp_avoid_paste (pfile, print.prev, token))
771627f7eb2Smrg || (print.prev == NULL && token->type == CPP_HASH))
772627f7eb2Smrg putc (' ', print.outf);
773627f7eb2Smrg }
774627f7eb2Smrg else if (token->flags & PREV_WHITE)
775627f7eb2Smrg putc (' ', print.outf);
776627f7eb2Smrg
777627f7eb2Smrg avoid_paste = false;
778627f7eb2Smrg print.source = NULL;
779627f7eb2Smrg print.prev = token;
780627f7eb2Smrg cpp_output_token (token, print.outf);
781627f7eb2Smrg
782627f7eb2Smrg if (token->type == CPP_COMMENT)
783627f7eb2Smrg account_for_newlines (token->val.str.text, token->val.str.len);
784627f7eb2Smrg }
785627f7eb2Smrg }
786627f7eb2Smrg
787627f7eb2Smrg /* Adjust print.src_line for newlines embedded in output. */
788627f7eb2Smrg static void
account_for_newlines(const unsigned char * str,size_t len)789627f7eb2Smrg account_for_newlines (const unsigned char *str, size_t len)
790627f7eb2Smrg {
791627f7eb2Smrg while (len--)
792627f7eb2Smrg if (*str++ == '\n')
793627f7eb2Smrg print.src_line++;
794627f7eb2Smrg }
795627f7eb2Smrg
796627f7eb2Smrg /* Writes out a traditionally preprocessed file. */
797627f7eb2Smrg static void
scan_translation_unit_trad(cpp_reader * pfile)798627f7eb2Smrg scan_translation_unit_trad (cpp_reader *pfile)
799627f7eb2Smrg {
800627f7eb2Smrg while (_cpp_read_logical_line_trad (pfile))
801627f7eb2Smrg {
802627f7eb2Smrg size_t len = pfile->out.cur - pfile->out.base;
803627f7eb2Smrg maybe_print_line (pfile->out.first_line);
804627f7eb2Smrg fwrite (pfile->out.base, 1, len, print.outf);
805627f7eb2Smrg print.printed = 1;
806627f7eb2Smrg if (!CPP_OPTION (pfile, discard_comments))
807627f7eb2Smrg account_for_newlines (pfile->out.base, len);
808627f7eb2Smrg }
809627f7eb2Smrg }
810627f7eb2Smrg
811627f7eb2Smrg /* If the token read on logical line LINE needs to be output on a
812627f7eb2Smrg different line to the current one, output the required newlines or
813627f7eb2Smrg a line marker. */
814627f7eb2Smrg static void
maybe_print_line(location_t src_loc)815627f7eb2Smrg maybe_print_line (location_t src_loc)
816627f7eb2Smrg {
817627f7eb2Smrg const line_map_ordinary *map
818627f7eb2Smrg = linemap_check_ordinary (linemap_lookup (line_table, src_loc));
819627f7eb2Smrg int src_line = SOURCE_LINE (map, src_loc);
820627f7eb2Smrg
821627f7eb2Smrg /* End the previous line of text. */
822627f7eb2Smrg if (print.printed)
823627f7eb2Smrg {
824627f7eb2Smrg putc ('\n', print.outf);
825627f7eb2Smrg print.src_line++;
826627f7eb2Smrg print.printed = 0;
827627f7eb2Smrg }
828627f7eb2Smrg
829627f7eb2Smrg if (src_line >= print.src_line && src_line < print.src_line + 8)
830627f7eb2Smrg {
831627f7eb2Smrg while (src_line > print.src_line)
832627f7eb2Smrg {
833627f7eb2Smrg putc ('\n', print.outf);
834627f7eb2Smrg print.src_line++;
835627f7eb2Smrg }
836627f7eb2Smrg }
837627f7eb2Smrg else
838627f7eb2Smrg print_line (src_loc, "");
839627f7eb2Smrg }
840627f7eb2Smrg
841627f7eb2Smrg /* Output a line marker for logical line LINE. Special flags are "1"
842627f7eb2Smrg or "2" indicating entering or leaving a file. */
843627f7eb2Smrg static void
print_line(location_t src_loc,const char * special_flags)844627f7eb2Smrg print_line (location_t src_loc, const char *special_flags)
845627f7eb2Smrg {
846627f7eb2Smrg /* End any previous line of text. */
847627f7eb2Smrg if (print.printed)
848627f7eb2Smrg putc ('\n', print.outf);
849627f7eb2Smrg print.printed = 0;
850627f7eb2Smrg
851627f7eb2Smrg if (!gfc_cpp_option.no_line_commands)
852627f7eb2Smrg {
853627f7eb2Smrg expanded_location loc;
854627f7eb2Smrg size_t to_file_len;
855627f7eb2Smrg unsigned char *to_file_quoted;
856627f7eb2Smrg unsigned char *p;
857627f7eb2Smrg int sysp;
858627f7eb2Smrg
859627f7eb2Smrg loc = expand_location (src_loc);
860627f7eb2Smrg to_file_len = strlen (loc.file);
861627f7eb2Smrg to_file_quoted = (unsigned char *) alloca (to_file_len * 4 + 1);
862627f7eb2Smrg
863627f7eb2Smrg print.src_line = loc.line;
864627f7eb2Smrg
865627f7eb2Smrg /* cpp_quote_string does not nul-terminate, so we have to do it
866627f7eb2Smrg ourselves. */
867627f7eb2Smrg p = cpp_quote_string (to_file_quoted,
868627f7eb2Smrg (const unsigned char *) loc.file, to_file_len);
869627f7eb2Smrg *p = '\0';
870627f7eb2Smrg fprintf (print.outf, "# %u \"%s\"%s",
871627f7eb2Smrg print.src_line == 0 ? 1 : print.src_line,
872627f7eb2Smrg to_file_quoted, special_flags);
873627f7eb2Smrg
874627f7eb2Smrg sysp = in_system_header_at (src_loc);
875627f7eb2Smrg if (sysp == 2)
876627f7eb2Smrg fputs (" 3 4", print.outf);
877627f7eb2Smrg else if (sysp == 1)
878627f7eb2Smrg fputs (" 3", print.outf);
879627f7eb2Smrg
880627f7eb2Smrg putc ('\n', print.outf);
881627f7eb2Smrg }
882627f7eb2Smrg }
883627f7eb2Smrg
884627f7eb2Smrg static void
cb_file_change(cpp_reader * ARG_UNUSED (pfile),const line_map_ordinary * map)885627f7eb2Smrg cb_file_change (cpp_reader * ARG_UNUSED (pfile), const line_map_ordinary *map)
886627f7eb2Smrg {
887627f7eb2Smrg const char *flags = "";
888627f7eb2Smrg
889627f7eb2Smrg if (gfc_cpp_option.no_line_commands)
890627f7eb2Smrg return;
891627f7eb2Smrg
892627f7eb2Smrg if (!map)
893627f7eb2Smrg return;
894627f7eb2Smrg
895627f7eb2Smrg if (print.first_time)
896627f7eb2Smrg {
897627f7eb2Smrg /* Avoid printing foo.i when the main file is foo.c. */
898627f7eb2Smrg if (!cpp_get_options (cpp_in)->preprocessed)
899627f7eb2Smrg print_line (map->start_location, flags);
900627f7eb2Smrg print.first_time = 0;
901627f7eb2Smrg }
902627f7eb2Smrg else
903627f7eb2Smrg {
904627f7eb2Smrg /* Bring current file to correct line when entering a new file. */
905627f7eb2Smrg if (map->reason == LC_ENTER)
906627f7eb2Smrg maybe_print_line (linemap_included_from (map));
907627f7eb2Smrg if (map->reason == LC_ENTER)
908627f7eb2Smrg flags = " 1";
909627f7eb2Smrg else if (map->reason == LC_LEAVE)
910627f7eb2Smrg flags = " 2";
911627f7eb2Smrg print_line (map->start_location, flags);
912627f7eb2Smrg }
913627f7eb2Smrg
914627f7eb2Smrg }
915627f7eb2Smrg
916627f7eb2Smrg /* Called when a line of output is started. TOKEN is the first token
917627f7eb2Smrg of the line, and at end of file will be CPP_EOF. */
918627f7eb2Smrg static void
cb_line_change(cpp_reader * pfile,const cpp_token * token,int parsing_args)919627f7eb2Smrg cb_line_change (cpp_reader *pfile, const cpp_token *token,
920627f7eb2Smrg int parsing_args)
921627f7eb2Smrg {
922627f7eb2Smrg location_t src_loc = token->src_loc;
923627f7eb2Smrg
924627f7eb2Smrg if (token->type == CPP_EOF || parsing_args)
925627f7eb2Smrg return;
926627f7eb2Smrg
927627f7eb2Smrg maybe_print_line (src_loc);
928627f7eb2Smrg print.prev = 0;
929627f7eb2Smrg print.source = 0;
930627f7eb2Smrg
931627f7eb2Smrg /* Supply enough spaces to put this token in its original column,
932627f7eb2Smrg one space per column greater than 2, since scan_translation_unit
933627f7eb2Smrg will provide a space if PREV_WHITE. Don't bother trying to
934627f7eb2Smrg reconstruct tabs; we can't get it right in general, and nothing
935627f7eb2Smrg ought to care. Some things do care; the fault lies with them. */
936627f7eb2Smrg if (!CPP_OPTION (pfile, traditional))
937627f7eb2Smrg {
938627f7eb2Smrg const line_map_ordinary *map
939627f7eb2Smrg = linemap_check_ordinary (linemap_lookup (line_table, src_loc));
940627f7eb2Smrg int spaces = SOURCE_COLUMN (map, src_loc) - 2;
941627f7eb2Smrg print.printed = 1;
942627f7eb2Smrg
943627f7eb2Smrg while (-- spaces >= 0)
944627f7eb2Smrg putc (' ', print.outf);
945627f7eb2Smrg }
946627f7eb2Smrg }
947627f7eb2Smrg
948627f7eb2Smrg static void
cb_ident(cpp_reader * pfile ATTRIBUTE_UNUSED,location_t line,const cpp_string * str)949627f7eb2Smrg cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
950627f7eb2Smrg const cpp_string *str)
951627f7eb2Smrg {
952627f7eb2Smrg maybe_print_line (line);
953627f7eb2Smrg fprintf (print.outf, "#ident %s\n", str->text);
954627f7eb2Smrg print.src_line++;
955627f7eb2Smrg }
956627f7eb2Smrg
957627f7eb2Smrg static void
cb_define(cpp_reader * pfile ATTRIBUTE_UNUSED,location_t line,cpp_hashnode * node ATTRIBUTE_UNUSED)958627f7eb2Smrg cb_define (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
959627f7eb2Smrg cpp_hashnode *node ATTRIBUTE_UNUSED)
960627f7eb2Smrg {
961627f7eb2Smrg maybe_print_line (line);
962627f7eb2Smrg fputs ("#define ", print.outf);
963627f7eb2Smrg
964627f7eb2Smrg /* 'D' is whole definition; 'N' is name only. */
965627f7eb2Smrg if (gfc_cpp_option.dump_macros == 'D')
966627f7eb2Smrg fputs ((const char *) cpp_macro_definition (pfile, node),
967627f7eb2Smrg print.outf);
968627f7eb2Smrg else
969627f7eb2Smrg fputs ((const char *) NODE_NAME (node), print.outf);
970627f7eb2Smrg
971627f7eb2Smrg putc ('\n', print.outf);
972627f7eb2Smrg if (LOCATION_LINE (line) != 0)
973627f7eb2Smrg print.src_line++;
974627f7eb2Smrg }
975627f7eb2Smrg
976627f7eb2Smrg static void
cb_undef(cpp_reader * pfile ATTRIBUTE_UNUSED,location_t line,cpp_hashnode * node)977627f7eb2Smrg cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
978627f7eb2Smrg cpp_hashnode *node)
979627f7eb2Smrg {
980627f7eb2Smrg maybe_print_line (line);
981627f7eb2Smrg fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
982627f7eb2Smrg print.src_line++;
983627f7eb2Smrg }
984627f7eb2Smrg
985627f7eb2Smrg 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)986627f7eb2Smrg cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
987627f7eb2Smrg const unsigned char *dir, const char *header, int angle_brackets,
988627f7eb2Smrg const cpp_token **comments)
989627f7eb2Smrg {
990627f7eb2Smrg maybe_print_line (line);
991627f7eb2Smrg if (angle_brackets)
992627f7eb2Smrg fprintf (print.outf, "#%s <%s>", dir, header);
993627f7eb2Smrg else
994627f7eb2Smrg fprintf (print.outf, "#%s \"%s\"", dir, header);
995627f7eb2Smrg
996627f7eb2Smrg if (comments != NULL)
997627f7eb2Smrg {
998627f7eb2Smrg while (*comments != NULL)
999627f7eb2Smrg {
1000627f7eb2Smrg if ((*comments)->flags & PREV_WHITE)
1001627f7eb2Smrg putc (' ', print.outf);
1002627f7eb2Smrg cpp_output_token (*comments, print.outf);
1003627f7eb2Smrg ++comments;
1004627f7eb2Smrg }
1005627f7eb2Smrg }
1006627f7eb2Smrg
1007627f7eb2Smrg putc ('\n', print.outf);
1008627f7eb2Smrg print.src_line++;
1009627f7eb2Smrg }
1010627f7eb2Smrg
1011627f7eb2Smrg /* Dump out the hash table. */
1012627f7eb2Smrg static int
dump_macro(cpp_reader * pfile,cpp_hashnode * node,void * v ATTRIBUTE_UNUSED)1013627f7eb2Smrg dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED)
1014627f7eb2Smrg {
1015627f7eb2Smrg if (cpp_user_macro_p (node))
1016627f7eb2Smrg {
1017627f7eb2Smrg fputs ("#define ", print.outf);
1018627f7eb2Smrg fputs ((const char *) cpp_macro_definition (pfile, node),
1019627f7eb2Smrg print.outf);
1020627f7eb2Smrg putc ('\n', print.outf);
1021627f7eb2Smrg print.src_line++;
1022627f7eb2Smrg }
1023627f7eb2Smrg
1024627f7eb2Smrg return 1;
1025627f7eb2Smrg }
1026627f7eb2Smrg
1027627f7eb2Smrg static void
cb_used_define(cpp_reader * pfile,location_t line ATTRIBUTE_UNUSED,cpp_hashnode * node)1028627f7eb2Smrg cb_used_define (cpp_reader *pfile, location_t line ATTRIBUTE_UNUSED,
1029627f7eb2Smrg cpp_hashnode *node)
1030627f7eb2Smrg {
1031627f7eb2Smrg gfc_cpp_macro_queue *q;
1032627f7eb2Smrg q = XNEW (gfc_cpp_macro_queue);
1033627f7eb2Smrg q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node));
1034627f7eb2Smrg q->next = cpp_define_queue;
1035627f7eb2Smrg cpp_define_queue = q;
1036627f7eb2Smrg }
1037627f7eb2Smrg
1038627f7eb2Smrg /* Callback from cpp_error for PFILE to print diagnostics from the
1039627f7eb2Smrg preprocessor. The diagnostic is of type LEVEL, with REASON set
1040627f7eb2Smrg to the reason code if LEVEL is represents a warning, at location
1041627f7eb2Smrg RICHLOC; MSG is the translated message and AP the arguments.
1042627f7eb2Smrg Returns true if a diagnostic was emitted, false otherwise. */
1043627f7eb2Smrg
1044627f7eb2Smrg 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)1045627f7eb2Smrg cb_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED,
1046627f7eb2Smrg enum cpp_diagnostic_level level,
1047627f7eb2Smrg enum cpp_warning_reason reason,
1048627f7eb2Smrg rich_location *richloc,
1049627f7eb2Smrg const char *msg, va_list *ap)
1050627f7eb2Smrg {
1051627f7eb2Smrg diagnostic_info diagnostic;
1052627f7eb2Smrg diagnostic_t dlevel;
1053627f7eb2Smrg bool save_warn_system_headers = global_dc->dc_warn_system_headers;
1054627f7eb2Smrg bool ret;
1055627f7eb2Smrg
1056627f7eb2Smrg switch (level)
1057627f7eb2Smrg {
1058627f7eb2Smrg case CPP_DL_WARNING_SYSHDR:
1059627f7eb2Smrg global_dc->dc_warn_system_headers = 1;
1060627f7eb2Smrg /* Fall through. */
1061627f7eb2Smrg case CPP_DL_WARNING:
1062627f7eb2Smrg dlevel = DK_WARNING;
1063627f7eb2Smrg break;
1064627f7eb2Smrg case CPP_DL_PEDWARN:
1065627f7eb2Smrg dlevel = DK_PEDWARN;
1066627f7eb2Smrg break;
1067627f7eb2Smrg case CPP_DL_ERROR:
1068627f7eb2Smrg dlevel = DK_ERROR;
1069627f7eb2Smrg break;
1070627f7eb2Smrg case CPP_DL_ICE:
1071627f7eb2Smrg dlevel = DK_ICE;
1072627f7eb2Smrg break;
1073627f7eb2Smrg case CPP_DL_NOTE:
1074627f7eb2Smrg dlevel = DK_NOTE;
1075627f7eb2Smrg break;
1076627f7eb2Smrg case CPP_DL_FATAL:
1077627f7eb2Smrg dlevel = DK_FATAL;
1078627f7eb2Smrg break;
1079627f7eb2Smrg default:
1080627f7eb2Smrg gcc_unreachable ();
1081627f7eb2Smrg }
1082627f7eb2Smrg diagnostic_set_info_translated (&diagnostic, msg, ap,
1083627f7eb2Smrg richloc, dlevel);
1084627f7eb2Smrg if (reason == CPP_W_WARNING_DIRECTIVE)
1085627f7eb2Smrg diagnostic_override_option_index (&diagnostic, OPT_Wcpp);
1086627f7eb2Smrg ret = diagnostic_report_diagnostic (global_dc, &diagnostic);
1087627f7eb2Smrg if (level == CPP_DL_WARNING_SYSHDR)
1088627f7eb2Smrg global_dc->dc_warn_system_headers = save_warn_system_headers;
1089627f7eb2Smrg return ret;
1090627f7eb2Smrg }
1091627f7eb2Smrg
1092627f7eb2Smrg /* Callback called when -fworking-director and -E to emit working
1093627f7eb2Smrg directory in cpp output file. */
1094627f7eb2Smrg
1095627f7eb2Smrg void
pp_dir_change(cpp_reader * pfile ATTRIBUTE_UNUSED,const char * dir)1096627f7eb2Smrg pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
1097627f7eb2Smrg {
1098627f7eb2Smrg size_t to_file_len = strlen (dir);
1099627f7eb2Smrg unsigned char *to_file_quoted =
1100627f7eb2Smrg (unsigned char *) alloca (to_file_len * 4 + 1);
1101627f7eb2Smrg unsigned char *p;
1102627f7eb2Smrg
1103627f7eb2Smrg /* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */
1104627f7eb2Smrg p = cpp_quote_string (to_file_quoted, (const unsigned char *) dir, to_file_len);
1105627f7eb2Smrg *p = '\0';
1106627f7eb2Smrg fprintf (print.outf, "# 1 \"%s//\"\n", to_file_quoted);
1107627f7eb2Smrg }
1108627f7eb2Smrg
1109627f7eb2Smrg /* Copy a #pragma directive to the preprocessed output. */
1110627f7eb2Smrg static void
cb_def_pragma(cpp_reader * pfile,location_t line)1111627f7eb2Smrg cb_def_pragma (cpp_reader *pfile, location_t line)
1112627f7eb2Smrg {
1113627f7eb2Smrg maybe_print_line (line);
1114627f7eb2Smrg fputs ("#pragma ", print.outf);
1115627f7eb2Smrg cpp_output_line (pfile, print.outf);
1116627f7eb2Smrg print.src_line++;
1117627f7eb2Smrg }
1118627f7eb2Smrg
1119627f7eb2Smrg static void
cb_used_undef(cpp_reader * pfile ATTRIBUTE_UNUSED,location_t line ATTRIBUTE_UNUSED,cpp_hashnode * node)1120627f7eb2Smrg cb_used_undef (cpp_reader *pfile ATTRIBUTE_UNUSED,
1121627f7eb2Smrg location_t line ATTRIBUTE_UNUSED,
1122627f7eb2Smrg cpp_hashnode *node)
1123627f7eb2Smrg {
1124627f7eb2Smrg gfc_cpp_macro_queue *q;
1125627f7eb2Smrg q = XNEW (gfc_cpp_macro_queue);
1126627f7eb2Smrg q->macro = xstrdup ((const char *) NODE_NAME (node));
1127627f7eb2Smrg q->next = cpp_undefine_queue;
1128627f7eb2Smrg cpp_undefine_queue = q;
1129627f7eb2Smrg }
1130627f7eb2Smrg
1131627f7eb2Smrg static void
dump_queued_macros(cpp_reader * pfile ATTRIBUTE_UNUSED)1132627f7eb2Smrg dump_queued_macros (cpp_reader *pfile ATTRIBUTE_UNUSED)
1133627f7eb2Smrg {
1134627f7eb2Smrg gfc_cpp_macro_queue *q;
1135627f7eb2Smrg
1136627f7eb2Smrg /* End the previous line of text. */
1137627f7eb2Smrg if (print.printed)
1138627f7eb2Smrg {
1139627f7eb2Smrg putc ('\n', print.outf);
1140627f7eb2Smrg print.src_line++;
1141627f7eb2Smrg print.printed = 0;
1142627f7eb2Smrg }
1143627f7eb2Smrg
1144627f7eb2Smrg for (q = cpp_define_queue; q;)
1145627f7eb2Smrg {
1146627f7eb2Smrg gfc_cpp_macro_queue *oq;
1147627f7eb2Smrg fputs ("#define ", print.outf);
1148627f7eb2Smrg fputs (q->macro, print.outf);
1149627f7eb2Smrg putc ('\n', print.outf);
1150627f7eb2Smrg print.src_line++;
1151627f7eb2Smrg oq = q;
1152627f7eb2Smrg q = q->next;
1153627f7eb2Smrg free (oq->macro);
1154627f7eb2Smrg free (oq);
1155627f7eb2Smrg }
1156627f7eb2Smrg cpp_define_queue = NULL;
1157627f7eb2Smrg for (q = cpp_undefine_queue; q;)
1158627f7eb2Smrg {
1159627f7eb2Smrg gfc_cpp_macro_queue *oq;
1160627f7eb2Smrg fprintf (print.outf, "#undef %s\n", q->macro);
1161627f7eb2Smrg print.src_line++;
1162627f7eb2Smrg oq = q;
1163627f7eb2Smrg q = q->next;
1164627f7eb2Smrg free (oq->macro);
1165627f7eb2Smrg free (oq);
1166627f7eb2Smrg }
1167627f7eb2Smrg cpp_undefine_queue = NULL;
1168627f7eb2Smrg }
1169