1/* Preprocess only, using cpplib.
2 Copyright (C) 1995-2024 Free Software Foundation, Inc.
3 Written by Per Bothner, 1994-95.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 3, or (at your option) any
8 later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING3. If not see
17 <http://www.gnu.org/licenses/>. */
18
19#include "config.h"
20#include "system.h"
21#include "coretypes.h"
22#include "c-common.h" /* For flags. */
23#include "../libcpp/internal.h"
24#include "langhooks.h"
25#include "c-pragma.h" /* For parse_in. */
26#include "file-prefix-map.h" /* remap_macro_filename() */
27
28class token_streamer;
29
30/* Encapsulates state used to convert a stream of tokens into a text
31 file. */
32static struct
33{
34 FILE *outf; /* Stream to write to. */
35 const cpp_token *prev; /* Previous token. */
36 const cpp_token *source; /* Source token for spacing. */
37 unsigned src_line; /* Line number currently being written. */
38 bool printed; /* True if something output at line. */
39 bool first_time; /* pp_file_change hasn't been called yet. */
40 bool prev_was_system_token; /* True if the previous token was a
41 system token.*/
42 const char *src_file; /* Current source file. */
43 token_streamer *streamer; /* Instance of class token_streamer using this
44 object. */
45} print;
46
47/* Defined and undefined macros being queued for output with -dU at
48 the next newline. */
49struct macro_queue
50{
51 struct macro_queue *next; /* Next macro in the list. */
52 char *macro; /* The name of the macro if not
53 defined, the full definition if
54 defined. */
55};
56static macro_queue *define_queue, *undef_queue;
57
58/* General output routines. */
59static void scan_translation_unit (cpp_reader *);
60static void scan_translation_unit_directives_only (cpp_reader *);
61static void scan_translation_unit_trad (cpp_reader *);
62static void account_for_newlines (const unsigned char *, size_t);
63static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
64static void dump_queued_macros (cpp_reader *);
65
66static bool print_line_1 (location_t, const char*, FILE *);
67static bool print_line (location_t, const char *);
68static bool maybe_print_line_1 (location_t, FILE *);
69static bool maybe_print_line (location_t);
70static bool do_line_change (cpp_reader *, const cpp_token *,
71 location_t, int);
72
73/* Callback routines for the parser. Most of these are active only
74 in specific modes. */
75static void cb_line_change (cpp_reader *, const cpp_token *, int);
76static void cb_define (cpp_reader *, location_t, cpp_hashnode *);
77static void cb_undef (cpp_reader *, location_t, cpp_hashnode *);
78static void cb_used_define (cpp_reader *, location_t, cpp_hashnode *);
79static void cb_used_undef (cpp_reader *, location_t, cpp_hashnode *);
80static void cb_include (cpp_reader *, location_t, const unsigned char *,
81 const char *, int, const cpp_token **);
82static void cb_ident (cpp_reader *, location_t, const cpp_string *);
83static void cb_def_pragma (cpp_reader *, location_t);
84static void cb_read_pch (cpp_reader *pfile, const char *name,
85 int fd, const char *orig_name);
86
87/* Preprocess and output. */
88void
89preprocess_file (cpp_reader *pfile)
90{
91 /* A successful cpp_read_main_file guarantees that we can call
92 cpp_scan_nooutput or cpp_get_token next. */
93 if (flag_no_output && pfile->buffer)
94 {
95 /* Scan -included buffers, then the main file. */
96 while (pfile->buffer->prev)
97 cpp_scan_nooutput (pfile);
98 cpp_scan_nooutput (pfile);
99 }
100 else if (cpp_get_options (pfile)->traditional)
101 scan_translation_unit_trad (pfile);
102 else if (cpp_get_options (pfile)->directives_only
103 && !cpp_get_options (pfile)->preprocessed)
104 scan_translation_unit_directives_only (pfile);
105 else
106 scan_translation_unit (pfile);
107
108 /* -dM command line option. Should this be elsewhere? */
109 if (flag_dump_macros == 'M')
110 cpp_forall_identifiers (pfile, dump_macro, NULL);
111
112 /* Flush any pending output. */
113 if (print.printed)
114 putc (c: '\n', stream: print.outf);
115}
116
117/* Don't emit #pragma or #ident directives if we are processing
118 assembly language; the assembler may choke on them. */
119static bool
120should_output_pragmas ()
121{
122 return cpp_get_options (parse_in)->lang != CLK_ASM;
123}
124
125/* Set up the callbacks as appropriate. */
126void
127init_pp_output (FILE *out_stream)
128{
129 cpp_callbacks *cb = cpp_get_callbacks (parse_in);
130
131 if (!flag_no_output)
132 {
133 cb->line_change = cb_line_change;
134 if (should_output_pragmas ())
135 {
136 cb->ident = cb_ident;
137 cb->def_pragma = cb_def_pragma;
138 }
139 }
140
141 if (flag_dump_includes)
142 cb->include = cb_include;
143
144 if (flag_pch_preprocess)
145 {
146 cb->valid_pch = c_common_valid_pch;
147 cb->read_pch = cb_read_pch;
148 }
149
150 if (flag_dump_macros == 'N' || flag_dump_macros == 'D')
151 {
152 cb->define = cb_define;
153 cb->undef = cb_undef;
154 }
155
156 if (flag_dump_macros == 'U')
157 {
158 cb->before_define = dump_queued_macros;
159 cb->used_define = cb_used_define;
160 cb->used_undef = cb_used_undef;
161 }
162
163 cb->has_attribute = c_common_has_attribute;
164 cb->has_builtin = c_common_has_builtin;
165 cb->has_feature = c_common_has_feature;
166 cb->get_source_date_epoch = cb_get_source_date_epoch;
167 cb->remap_filename = remap_macro_filename;
168
169 /* Initialize the print structure. */
170 print.src_line = 1;
171 print.printed = false;
172 print.prev = 0;
173 print.outf = out_stream;
174 print.first_time = 1;
175 print.src_file = "";
176 print.prev_was_system_token = false;
177 print.streamer = nullptr;
178}
179
180// FIXME: Ideally we'd just turn the entirety of the print struct into
181// an encapsulated streamer ...
182
183class token_streamer
184{
185 bool avoid_paste;
186 bool do_line_adjustments;
187 bool in_pragma;
188
189 public:
190 token_streamer (cpp_reader *pfile)
191 :avoid_paste (false),
192 do_line_adjustments (cpp_get_options (pfile)->lang != CLK_ASM
193 && !flag_no_line_commands),
194 in_pragma (false)
195 {
196 gcc_assert (!print.streamer);
197 print.streamer = this;
198 }
199
200 void begin_pragma ()
201 {
202 in_pragma = true;
203 }
204
205 void stream (cpp_reader *pfile, const cpp_token *tok, location_t);
206};
207
208void
209token_streamer::stream (cpp_reader *pfile, const cpp_token *token,
210 location_t loc)
211{
212 /* Keep input_location up to date, since it is needed for processing early
213 pragmas such as #pragma GCC diagnostic. */
214 input_location = loc;
215
216 if (token->type == CPP_PADDING)
217 {
218 avoid_paste = true;
219 if (print.source == NULL
220 || (!(print.source->flags & PREV_WHITE)
221 && token->val.source == NULL))
222 print.source = token->val.source;
223 return;
224 }
225
226 if (token->type == CPP_EOF)
227 return;
228
229 /* Keep track when we move into and out of system locations. */
230 const bool is_system_token = in_system_header_at (loc);
231 const bool system_state_changed
232 = (is_system_token != print.prev_was_system_token);
233 print.prev_was_system_token = is_system_token;
234
235 /* Subtle logic to output a space if and only if necessary. */
236 bool line_marker_emitted = false;
237 if (avoid_paste)
238 {
239 unsigned src_line = LOCATION_LINE (loc);
240
241 if (print.source == NULL)
242 print.source = token;
243
244 if (src_line != print.src_line
245 && do_line_adjustments
246 && !in_pragma)
247 {
248 line_marker_emitted = do_line_change (pfile, token, loc, false);
249 putc (c: ' ', stream: print.outf);
250 print.printed = true;
251 }
252 else if (print.source->flags & PREV_WHITE
253 || (print.prev
254 && cpp_avoid_paste (pfile, print.prev, token))
255 || (print.prev == NULL && token->type == CPP_HASH))
256 {
257 putc (c: ' ', stream: print.outf);
258 print.printed = true;
259 }
260 }
261 else if (token->flags & PREV_WHITE && token->type != CPP_PRAGMA)
262 {
263 unsigned src_line = LOCATION_LINE (loc);
264
265 if (src_line != print.src_line
266 && do_line_adjustments
267 && !in_pragma)
268 line_marker_emitted = do_line_change (pfile, token, loc, false);
269 putc (c: ' ', stream: print.outf);
270 print.printed = true;
271 }
272
273 avoid_paste = false;
274 print.source = NULL;
275 print.prev = token;
276 if (token->type == CPP_PRAGMA)
277 {
278 in_pragma = true;
279 if (should_output_pragmas ())
280 {
281 const char *space;
282 const char *name;
283
284 line_marker_emitted = maybe_print_line (token->src_loc);
285 fputs (s: "#pragma ", stream: print.outf);
286 c_pp_lookup_pragma (token->val.pragma, &space, &name);
287 if (space)
288 fprintf (stream: print.outf, format: "%s %s", space, name);
289 else
290 fprintf (stream: print.outf, format: "%s", name);
291 print.printed = true;
292 }
293 if (token->val.pragma >= PRAGMA_FIRST_EXTERNAL)
294 c_pp_invoke_early_pragma_handler (token->val.pragma);
295 }
296 else if (token->type == CPP_PRAGMA_EOL)
297 {
298 if (should_output_pragmas ())
299 maybe_print_line (UNKNOWN_LOCATION);
300 in_pragma = false;
301 }
302 else
303 {
304 if (cpp_get_options (parse_in)->debug)
305 linemap_dump_location (line_table, token->src_loc, print.outf);
306
307 if (do_line_adjustments
308 && !in_pragma
309 && !line_marker_emitted
310 && system_state_changed
311 && !is_location_from_builtin_token (loc))
312 /* The system-ness of this token is different from the one of
313 the previous token. Let's emit a line change to mark the
314 new system-ness before we emit the token. */
315 {
316 line_marker_emitted = do_line_change (pfile, token, loc, false);
317 }
318 if (!in_pragma || should_output_pragmas ())
319 {
320 cpp_output_token (token, print.outf);
321 print.printed = true;
322 }
323 }
324
325 /* CPP_COMMENT tokens and raw-string literal tokens can have
326 embedded new-line characters. Rather than enumerating all the
327 possible token types just check if token uses val.str union
328 member. */
329 if (cpp_token_val_index (tok: token) == CPP_TOKEN_FLD_STR)
330 account_for_newlines (token->val.str.text, token->val.str.len);
331}
332
333/* Writes out the preprocessed file, handling spacing and paste
334 avoidance issues. */
335
336static void
337scan_translation_unit (cpp_reader *pfile)
338{
339 token_streamer streamer (pfile);
340 uintptr_t filter = 0;
341
342 if (lang_hooks.preprocess_token)
343 filter = lang_hooks.preprocess_token (pfile, NULL, filter);
344
345 print.source = NULL;
346 for (;;)
347 {
348 location_t spelling_loc;
349 const cpp_token *token
350 = cpp_get_token_with_location (pfile, &spelling_loc);
351
352 streamer.stream (pfile, token, loc: spelling_loc);
353 if (filter)
354 {
355 unsigned flags = lang_hooks.preprocess_token (pfile, token, filter);
356 if (flags & lang_hooks::PT_begin_pragma)
357 streamer.begin_pragma ();
358 }
359 if (token->type == CPP_EOF)
360 break;
361 }
362
363 if (filter)
364 lang_hooks.preprocess_token (pfile, NULL, filter);
365}
366
367class do_streamer : public token_streamer
368{
369 public:
370 uintptr_t filter;
371
372 do_streamer (cpp_reader *pfile, uintptr_t filter)
373 :token_streamer (pfile), filter (filter)
374 {
375 }
376};
377
378static void
379directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
380{
381 va_list args;
382 va_start (args, data_);
383
384 do_streamer *streamer = reinterpret_cast <do_streamer *> (data_);
385 switch (task)
386 {
387 default:
388 gcc_unreachable ();
389
390 case CPP_DO_print:
391 {
392 print.src_line += va_arg (args, unsigned);
393
394 const void *buf = va_arg (args, const void *);
395 size_t size = va_arg (args, size_t);
396 fwrite (ptr: buf, size: 1, n: size, s: print.outf);
397 }
398 break;
399
400 case CPP_DO_location:
401 maybe_print_line (va_arg (args, location_t));
402 break;
403
404 case CPP_DO_token:
405 {
406 const cpp_token *token = va_arg (args, const cpp_token *);
407 location_t spelling_loc = va_arg (args, location_t);
408 streamer->stream (pfile, token, loc: spelling_loc);
409 if (streamer->filter)
410 {
411 unsigned flags = lang_hooks.preprocess_token
412 (pfile, token, streamer->filter);
413 if (flags & lang_hooks::PT_begin_pragma)
414 streamer->begin_pragma ();
415 }
416 }
417 break;
418 }
419
420 va_end (args);
421}
422
423/* Writes out the preprocessed file, handling spacing and paste
424 avoidance issues. */
425static void
426scan_translation_unit_directives_only (cpp_reader *pfile)
427{
428 uintptr_t filter = 0;
429 if (lang_hooks.preprocess_token)
430 filter = lang_hooks.preprocess_token (pfile, NULL, filter);
431 do_streamer streamer (pfile, filter);
432 cpp_directive_only_process (pfile, data: &streamer, cb: directives_only_cb);
433 if (streamer.filter)
434 lang_hooks.preprocess_token (pfile, NULL, streamer.filter);
435}
436
437/* Adjust print.src_line for newlines embedded in output. For example, if a raw
438 string literal contains newlines, then we need to increment our notion of the
439 current line to keep in sync and avoid outputting a line marker
440 unnecessarily. If a raw string literal containing newlines is the result of
441 macro expansion, then we have the opposite problem, where the token takes up
442 more lines in the output than it did in the input, and hence a line marker is
443 needed to restore the correct state for subsequent lines. In this case,
444 incrementing print.src_line still does the job, because it will cause us to
445 emit the line marker the next time a token is streamed. */
446static void
447account_for_newlines (const unsigned char *str, size_t len)
448{
449 while (len--)
450 if (*str++ == '\n')
451 print.src_line++;
452}
453
454/* Writes out a traditionally preprocessed file. */
455static void
456scan_translation_unit_trad (cpp_reader *pfile)
457{
458 while (_cpp_read_logical_line_trad (pfile))
459 {
460 size_t len = pfile->out.cur - pfile->out.base;
461 maybe_print_line (pfile->out.first_line);
462 fwrite (ptr: pfile->out.base, size: 1, n: len, s: print.outf);
463 print.printed = true;
464 if (!CPP_OPTION (pfile, discard_comments))
465 account_for_newlines (str: pfile->out.base, len);
466 }
467}
468
469/* If the token read on logical line LINE needs to be output on a
470 different line to the current one, output the required newlines or
471 a line marker. If a line marker was emitted, return TRUE otherwise
472 return FALSE. */
473
474static bool
475maybe_print_line_1 (location_t src_loc, FILE *stream)
476{
477 bool emitted_line_marker = false;
478 unsigned src_line = LOCATION_LINE (src_loc);
479 const char *src_file = LOCATION_FILE (src_loc);
480
481 /* End the previous line of text. */
482 if (print.printed)
483 {
484 putc (c: '\n', stream: stream);
485 print.src_line++;
486 print.printed = false;
487 }
488
489 if (!flag_no_line_commands
490 && src_line >= print.src_line
491 && src_line < print.src_line + 8
492 && src_loc != UNKNOWN_LOCATION
493 && strcmp (s1: src_file, s2: print.src_file) == 0)
494 {
495 while (src_line > print.src_line)
496 {
497 putc (c: '\n', stream: stream);
498 print.src_line++;
499 }
500 }
501 else
502 emitted_line_marker = print_line_1 (src_loc, "", stream);
503
504 return emitted_line_marker;
505}
506
507/* If the token read on logical line LINE needs to be output on a
508 different line to the current one, output the required newlines or
509 a line marker. If a line marker was emitted, return TRUE otherwise
510 return FALSE. */
511
512static bool
513maybe_print_line (location_t src_loc)
514{
515 if (cpp_get_options (parse_in)->debug)
516 linemap_dump_location (line_table, src_loc,
517 print.outf);
518 return maybe_print_line_1 (src_loc, stream: print.outf);
519}
520
521/* Output a line marker for logical line LINE. Special flags are "1"
522 or "2" indicating entering or leaving a file. If the line marker
523 was effectively emitted, return TRUE otherwise return FALSE. */
524
525static bool
526print_line_1 (location_t src_loc, const char *special_flags, FILE *stream)
527{
528 bool emitted_line_marker = false;
529
530 /* End any previous line of text. */
531 if (print.printed)
532 putc (c: '\n', stream: stream);
533 print.printed = false;
534
535 if (src_loc != UNKNOWN_LOCATION && !flag_no_line_commands)
536 {
537 const char *file_path = LOCATION_FILE (src_loc);
538 size_t to_file_len = strlen (s: file_path);
539 unsigned char *to_file_quoted =
540 (unsigned char *) alloca (to_file_len * 4 + 1);
541
542 /* cpp_quote_string does not nul-terminate, so we have to do it
543 ourselves. */
544 unsigned char *p = cpp_quote_string (to_file_quoted,
545 (const unsigned char *) file_path,
546 to_file_len);
547 *p = '\0';
548
549 print.src_line = LOCATION_LINE (src_loc);
550 print.src_file = file_path;
551
552 fprintf (stream: stream, format: "# %u \"%s\"%s",
553 print.src_line, to_file_quoted, special_flags);
554
555 int sysp = in_system_header_at (loc: src_loc);
556 if (sysp == 2)
557 fputs (s: " 3 4", stream: stream);
558 else if (sysp == 1)
559 fputs (s: " 3", stream: stream);
560
561 putc (c: '\n', stream: stream);
562 emitted_line_marker = true;
563 }
564
565 return emitted_line_marker;
566}
567
568/* Output a line marker for logical line LINE. Special flags are "1"
569 or "2" indicating entering or leaving a file. Return TRUE if a
570 line marker was effectively emitted, FALSE otherwise. */
571
572static bool
573print_line (location_t src_loc, const char *special_flags)
574{
575 if (cpp_get_options (parse_in)->debug)
576 linemap_dump_location (line_table, src_loc,
577 print.outf);
578 return print_line_1 (src_loc, special_flags, stream: print.outf);
579}
580
581/* Helper function for cb_line_change and scan_translation_unit.
582 Return TRUE if a line marker is emitted, FALSE otherwise. */
583static bool
584do_line_change (cpp_reader *pfile, const cpp_token *token,
585 location_t src_loc, int parsing_args)
586{
587 bool emitted_line_marker = false;
588 if (define_queue || undef_queue)
589 dump_queued_macros (pfile);
590
591 if (token->type == CPP_EOF || parsing_args)
592 return false;
593
594 emitted_line_marker = maybe_print_line (src_loc);
595 print.prev = 0;
596 print.source = 0;
597
598 /* Supply enough spaces to put this token in its original column,
599 one space per column greater than 2, since scan_translation_unit
600 will provide a space if PREV_WHITE. Don't bother trying to
601 reconstruct tabs; we can't get it right in general, and nothing
602 ought to care. Some things do care; the fault lies with them.
603
604 Also do not output the spaces if this is a CPP_PRAGMA token. In this
605 case, libcpp has provided the location of the first token after #pragma,
606 so we would start at the wrong column. */
607 if (!CPP_OPTION (pfile, traditional) && token->type != CPP_PRAGMA)
608 {
609 int spaces = LOCATION_COLUMN (src_loc) - 2;
610 print.printed = true;
611
612 while (-- spaces >= 0)
613 putc (c: ' ', stream: print.outf);
614 }
615
616 return emitted_line_marker;
617}
618
619/* Called when a line of output is started. TOKEN is the first token
620 of the line, and at end of file will be CPP_EOF. */
621static void
622cb_line_change (cpp_reader *pfile, const cpp_token *token,
623 int parsing_args)
624{
625 do_line_change (pfile, token, src_loc: token->src_loc, parsing_args);
626}
627
628static void
629cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
630 const cpp_string *str)
631{
632 maybe_print_line (src_loc: line);
633 fprintf (stream: print.outf, format: "#ident %s\n", str->text);
634 print.src_line++;
635}
636
637static void
638cb_define (cpp_reader *pfile, location_t line, cpp_hashnode *node)
639{
640 const line_map_ordinary *map;
641
642 maybe_print_line (src_loc: line);
643 fputs (s: "#define ", stream: print.outf);
644
645 /* 'D' is whole definition; 'N' is name only. */
646 if (flag_dump_macros == 'D')
647 fputs (s: (const char *) cpp_macro_definition (pfile, node),
648 stream: print.outf);
649 else
650 fputs (s: (const char *) NODE_NAME (node), stream: print.outf);
651
652 putc (c: '\n', stream: print.outf);
653 print.printed = false;
654 linemap_resolve_location (line_table, loc: line,
655 lrk: LRK_MACRO_DEFINITION_LOCATION,
656 loc_map: &map);
657 print.src_line++;
658}
659
660static void
661cb_undef (cpp_reader *pfile, location_t line, cpp_hashnode *node)
662{
663 if (lang_hooks.preprocess_undef)
664 lang_hooks.preprocess_undef (pfile, line, node);
665 maybe_print_line (src_loc: line);
666 fprintf (stream: print.outf, format: "#undef %s\n", NODE_NAME (node));
667 print.src_line++;
668}
669
670static void
671cb_used_define (cpp_reader *pfile, location_t line ATTRIBUTE_UNUSED,
672 cpp_hashnode *node)
673{
674 if (cpp_user_macro_p (node))
675 {
676 macro_queue *q;
677 q = XNEW (macro_queue);
678 q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node));
679 q->next = define_queue;
680 define_queue = q;
681 }
682}
683
684static void
685cb_used_undef (cpp_reader *pfile ATTRIBUTE_UNUSED,
686 location_t line ATTRIBUTE_UNUSED,
687 cpp_hashnode *node)
688{
689 macro_queue *q;
690 q = XNEW (macro_queue);
691 q->macro = xstrdup ((const char *) NODE_NAME (node));
692 q->next = undef_queue;
693 undef_queue = q;
694}
695
696static void
697dump_queued_macros (cpp_reader *pfile ATTRIBUTE_UNUSED)
698{
699 macro_queue *q;
700
701 /* End the previous line of text. */
702 if (print.printed)
703 {
704 putc (c: '\n', stream: print.outf);
705 print.src_line++;
706 print.printed = false;
707 }
708
709 for (q = define_queue; q;)
710 {
711 macro_queue *oq;
712 fputs (s: "#define ", stream: print.outf);
713 fputs (s: q->macro, stream: print.outf);
714 putc (c: '\n', stream: print.outf);
715 print.printed = false;
716 print.src_line++;
717 oq = q;
718 q = q->next;
719 free (ptr: oq->macro);
720 free (ptr: oq);
721 }
722 define_queue = NULL;
723 for (q = undef_queue; q;)
724 {
725 macro_queue *oq;
726 fprintf (stream: print.outf, format: "#undef %s\n", q->macro);
727 print.src_line++;
728 oq = q;
729 q = q->next;
730 free (ptr: oq->macro);
731 free (ptr: oq);
732 }
733 undef_queue = NULL;
734}
735
736static void
737cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
738 const unsigned char *dir, const char *header, int angle_brackets,
739 const cpp_token **comments)
740{
741 maybe_print_line (src_loc: line);
742 if (angle_brackets)
743 fprintf (stream: print.outf, format: "#%s <%s>", dir, header);
744 else
745 fprintf (stream: print.outf, format: "#%s \"%s\"", dir, header);
746
747 if (comments != NULL)
748 {
749 while (*comments != NULL)
750 {
751 if ((*comments)->flags & PREV_WHITE)
752 putc (c: ' ', stream: print.outf);
753 cpp_output_token (*comments, print.outf);
754 ++comments;
755 }
756 }
757
758 putc (c: '\n', stream: print.outf);
759 print.printed = false;
760 print.src_line++;
761}
762
763/* Callback called when -fworking-director and -E to emit working
764 directory in cpp output file. */
765
766void
767pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
768{
769 size_t to_file_len = strlen (s: dir);
770 unsigned char *to_file_quoted =
771 (unsigned char *) alloca (to_file_len * 4 + 1);
772 unsigned char *p;
773
774 /* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */
775 p = cpp_quote_string (to_file_quoted, (const unsigned char *) dir, to_file_len);
776 *p = '\0';
777 fprintf (stream: print.outf, format: "# 1 \"%s//\"\n", to_file_quoted);
778}
779
780/* The file name, line number or system header flags have changed, as
781 described in MAP. */
782
783void
784pp_file_change (const line_map_ordinary *map)
785{
786 const char *flags = "";
787
788 if (flag_no_line_commands)
789 return;
790
791 if (map != NULL)
792 {
793 input_location = map->start_location;
794 if (print.first_time)
795 {
796 /* Avoid printing foo.i when the main file is foo.c. */
797 if (!cpp_get_options (parse_in)->preprocessed)
798 print_line (src_loc: map->start_location, special_flags: flags);
799 print.first_time = 0;
800 }
801 else
802 {
803 /* Bring current file to correct line when entering a new file. */
804 if (map->reason == LC_ENTER)
805 {
806 maybe_print_line (src_loc: linemap_included_from (ord_map: map));
807 flags = " 1";
808 }
809 else if (map->reason == LC_LEAVE)
810 flags = " 2";
811 print_line (src_loc: map->start_location, special_flags: flags);
812 }
813 }
814}
815
816/* Copy a #pragma directive to the preprocessed output. */
817static void
818cb_def_pragma (cpp_reader *pfile, location_t line)
819{
820 maybe_print_line (src_loc: line);
821 fputs (s: "#pragma ", stream: print.outf);
822 cpp_output_line (pfile, print.outf);
823 print.printed = false;
824 print.src_line++;
825}
826
827/* Stream a token as if we had seen it directly ourselves; needed
828 in case a token was lexed externally, e.g. while processing a
829 pragma. */
830void
831c_pp_stream_token (cpp_reader *pfile, const cpp_token *tok, location_t loc)
832{
833 gcc_assert (print.streamer);
834 print.streamer->stream (pfile, token: tok, loc);
835}
836
837/* Dump out the hash table. */
838static int
839dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED)
840{
841 if (cpp_user_macro_p (node))
842 {
843 fputs (s: "#define ", stream: print.outf);
844 fputs (s: (const char *) cpp_macro_definition (pfile, node),
845 stream: print.outf);
846 putc (c: '\n', stream: print.outf);
847 print.printed = false;
848 print.src_line++;
849 }
850
851 return 1;
852}
853
854/* Load in the PCH file NAME, open on FD. It was originally searched for
855 by ORIG_NAME. Also, print out a #include command so that the PCH
856 file can be loaded when the preprocessed output is compiled. */
857
858static void
859cb_read_pch (cpp_reader *pfile, const char *name,
860 int fd, const char *orig_name ATTRIBUTE_UNUSED)
861{
862 c_common_read_pch (pfile, name, fd, orig: orig_name);
863
864 fprintf (stream: print.outf, format: "#pragma GCC pch_preprocess \"%s\"\n", name);
865 print.src_line++;
866
867 /* The process of reading the PCH has destroyed the frontend parser,
868 so ask the frontend to reinitialize it, in case we need it to
869 process any #pragma directives encountered while preprocessing. */
870 c_init_preprocess ();
871}
872

source code of gcc/c-family/c-ppoutput.cc