1/* Preprocess only, using cpplib.
2 Copyright (C) 1995-2023 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->get_source_date_epoch = cb_get_source_date_epoch;
166 cb->remap_filename = remap_macro_filename;
167
168 /* Initialize the print structure. */
169 print.src_line = 1;
170 print.printed = false;
171 print.prev = 0;
172 print.outf = out_stream;
173 print.first_time = 1;
174 print.src_file = "";
175 print.prev_was_system_token = false;
176 print.streamer = nullptr;
177}
178
179// FIXME: Ideally we'd just turn the entirety of the print struct into
180// an encapsulated streamer ...
181
182class token_streamer
183{
184 bool avoid_paste;
185 bool do_line_adjustments;
186 bool in_pragma;
187
188 public:
189 token_streamer (cpp_reader *pfile)
190 :avoid_paste (false),
191 do_line_adjustments (cpp_get_options (pfile)->lang != CLK_ASM
192 && !flag_no_line_commands),
193 in_pragma (false)
194 {
195 gcc_assert (!print.streamer);
196 print.streamer = this;
197 }
198
199 void begin_pragma ()
200 {
201 in_pragma = true;
202 }
203
204 void stream (cpp_reader *pfile, const cpp_token *tok, location_t);
205};
206
207void
208token_streamer::stream (cpp_reader *pfile, const cpp_token *token,
209 location_t loc)
210{
211 /* Keep input_location up to date, since it is needed for processing early
212 pragmas such as #pragma GCC diagnostic. */
213 input_location = loc;
214
215 if (token->type == CPP_PADDING)
216 {
217 avoid_paste = true;
218 if (print.source == NULL
219 || (!(print.source->flags & PREV_WHITE)
220 && token->val.source == NULL))
221 print.source = token->val.source;
222 return;
223 }
224
225 if (token->type == CPP_EOF)
226 return;
227
228 /* Keep track when we move into and out of system locations. */
229 const bool is_system_token = in_system_header_at (loc);
230 const bool system_state_changed
231 = (is_system_token != print.prev_was_system_token);
232 print.prev_was_system_token = is_system_token;
233
234 /* Subtle logic to output a space if and only if necessary. */
235 bool line_marker_emitted = false;
236 if (avoid_paste)
237 {
238 unsigned src_line = LOCATION_LINE (loc);
239
240 if (print.source == NULL)
241 print.source = token;
242
243 if (src_line != print.src_line
244 && do_line_adjustments
245 && !in_pragma)
246 {
247 line_marker_emitted = do_line_change (pfile, token, loc, false);
248 putc (c: ' ', stream: print.outf);
249 print.printed = true;
250 }
251 else if (print.source->flags & PREV_WHITE
252 || (print.prev
253 && cpp_avoid_paste (pfile, print.prev, token))
254 || (print.prev == NULL && token->type == CPP_HASH))
255 {
256 putc (c: ' ', stream: print.outf);
257 print.printed = true;
258 }
259 }
260 else if (token->flags & PREV_WHITE && token->type != CPP_PRAGMA)
261 {
262 unsigned src_line = LOCATION_LINE (loc);
263
264 if (src_line != print.src_line
265 && do_line_adjustments
266 && !in_pragma)
267 line_marker_emitted = do_line_change (pfile, token, loc, false);
268 putc (c: ' ', stream: print.outf);
269 print.printed = true;
270 }
271
272 avoid_paste = false;
273 print.source = NULL;
274 print.prev = token;
275 if (token->type == CPP_PRAGMA)
276 {
277 in_pragma = true;
278 if (should_output_pragmas ())
279 {
280 const char *space;
281 const char *name;
282
283 line_marker_emitted = maybe_print_line (token->src_loc);
284 fputs (s: "#pragma ", stream: print.outf);
285 c_pp_lookup_pragma (token->val.pragma, &space, &name);
286 if (space)
287 fprintf (stream: print.outf, format: "%s %s", space, name);
288 else
289 fprintf (stream: print.outf, format: "%s", name);
290 print.printed = true;
291 }
292 if (token->val.pragma >= PRAGMA_FIRST_EXTERNAL)
293 c_pp_invoke_early_pragma_handler (token->val.pragma);
294 }
295 else if (token->type == CPP_PRAGMA_EOL)
296 {
297 if (should_output_pragmas ())
298 maybe_print_line (UNKNOWN_LOCATION);
299 in_pragma = false;
300 }
301 else
302 {
303 if (cpp_get_options (parse_in)->debug)
304 linemap_dump_location (line_table, token->src_loc, print.outf);
305
306 if (do_line_adjustments
307 && !in_pragma
308 && !line_marker_emitted
309 && system_state_changed
310 && !is_location_from_builtin_token (loc))
311 /* The system-ness of this token is different from the one of
312 the previous token. Let's emit a line change to mark the
313 new system-ness before we emit the token. */
314 {
315 line_marker_emitted = do_line_change (pfile, token, loc, false);
316 }
317 if (!in_pragma || should_output_pragmas ())
318 {
319 cpp_output_token (token, print.outf);
320 print.printed = true;
321 }
322 }
323
324 /* CPP_COMMENT tokens and raw-string literal tokens can have
325 embedded new-line characters. Rather than enumerating all the
326 possible token types just check if token uses val.str union
327 member. */
328 if (cpp_token_val_index (tok: token) == CPP_TOKEN_FLD_STR)
329 account_for_newlines (token->val.str.text, token->val.str.len);
330}
331
332/* Writes out the preprocessed file, handling spacing and paste
333 avoidance issues. */
334
335static void
336scan_translation_unit (cpp_reader *pfile)
337{
338 token_streamer streamer (pfile);
339 uintptr_t filter = 0;
340
341 if (lang_hooks.preprocess_token)
342 filter = lang_hooks.preprocess_token (pfile, NULL, filter);
343
344 print.source = NULL;
345 for (;;)
346 {
347 location_t spelling_loc;
348 const cpp_token *token
349 = cpp_get_token_with_location (pfile, &spelling_loc);
350
351 streamer.stream (pfile, token, loc: spelling_loc);
352 if (filter)
353 {
354 unsigned flags = lang_hooks.preprocess_token (pfile, token, filter);
355 if (flags & lang_hooks::PT_begin_pragma)
356 streamer.begin_pragma ();
357 }
358 if (token->type == CPP_EOF)
359 break;
360 }
361
362 if (filter)
363 lang_hooks.preprocess_token (pfile, NULL, filter);
364}
365
366class do_streamer : public token_streamer
367{
368 public:
369 uintptr_t filter;
370
371 do_streamer (cpp_reader *pfile, uintptr_t filter)
372 :token_streamer (pfile), filter (filter)
373 {
374 }
375};
376
377static void
378directives_only_cb (cpp_reader *pfile, CPP_DO_task task, void *data_, ...)
379{
380 va_list args;
381 va_start (args, data_);
382
383 do_streamer *streamer = reinterpret_cast <do_streamer *> (data_);
384 switch (task)
385 {
386 default:
387 gcc_unreachable ();
388
389 case CPP_DO_print:
390 {
391 print.src_line += va_arg (args, unsigned);
392
393 const void *buf = va_arg (args, const void *);
394 size_t size = va_arg (args, size_t);
395 fwrite (ptr: buf, size: 1, n: size, s: print.outf);
396 }
397 break;
398
399 case CPP_DO_location:
400 maybe_print_line (va_arg (args, location_t));
401 break;
402
403 case CPP_DO_token:
404 {
405 const cpp_token *token = va_arg (args, const cpp_token *);
406 location_t spelling_loc = va_arg (args, location_t);
407 streamer->stream (pfile, token, loc: spelling_loc);
408 if (streamer->filter)
409 {
410 unsigned flags = lang_hooks.preprocess_token
411 (pfile, token, streamer->filter);
412 if (flags & lang_hooks::PT_begin_pragma)
413 streamer->begin_pragma ();
414 }
415 }
416 break;
417 }
418
419 va_end (args);
420}
421
422/* Writes out the preprocessed file, handling spacing and paste
423 avoidance issues. */
424static void
425scan_translation_unit_directives_only (cpp_reader *pfile)
426{
427 uintptr_t filter = 0;
428 if (lang_hooks.preprocess_token)
429 filter = lang_hooks.preprocess_token (pfile, NULL, filter);
430 do_streamer streamer (pfile, filter);
431 cpp_directive_only_process (pfile, data: &streamer, cb: directives_only_cb);
432 if (streamer.filter)
433 lang_hooks.preprocess_token (pfile, NULL, streamer.filter);
434}
435
436/* Adjust print.src_line for newlines embedded in output. For example, if a raw
437 string literal contains newlines, then we need to increment our notion of the
438 current line to keep in sync and avoid outputting a line marker
439 unnecessarily. If a raw string literal containing newlines is the result of
440 macro expansion, then we have the opposite problem, where the token takes up
441 more lines in the output than it did in the input, and hence a line marker is
442 needed to restore the correct state for subsequent lines. In this case,
443 incrementing print.src_line still does the job, because it will cause us to
444 emit the line marker the next time a token is streamed. */
445static void
446account_for_newlines (const unsigned char *str, size_t len)
447{
448 while (len--)
449 if (*str++ == '\n')
450 print.src_line++;
451}
452
453/* Writes out a traditionally preprocessed file. */
454static void
455scan_translation_unit_trad (cpp_reader *pfile)
456{
457 while (_cpp_read_logical_line_trad (pfile))
458 {
459 size_t len = pfile->out.cur - pfile->out.base;
460 maybe_print_line (pfile->out.first_line);
461 fwrite (ptr: pfile->out.base, size: 1, n: len, s: print.outf);
462 print.printed = true;
463 if (!CPP_OPTION (pfile, discard_comments))
464 account_for_newlines (str: pfile->out.base, len);
465 }
466}
467
468/* If the token read on logical line LINE needs to be output on a
469 different line to the current one, output the required newlines or
470 a line marker. If a line marker was emitted, return TRUE otherwise
471 return FALSE. */
472
473static bool
474maybe_print_line_1 (location_t src_loc, FILE *stream)
475{
476 bool emitted_line_marker = false;
477 unsigned src_line = LOCATION_LINE (src_loc);
478 const char *src_file = LOCATION_FILE (src_loc);
479
480 /* End the previous line of text. */
481 if (print.printed)
482 {
483 putc (c: '\n', stream: stream);
484 print.src_line++;
485 print.printed = false;
486 }
487
488 if (!flag_no_line_commands
489 && src_line >= print.src_line
490 && src_line < print.src_line + 8
491 && src_loc != UNKNOWN_LOCATION
492 && strcmp (s1: src_file, s2: print.src_file) == 0)
493 {
494 while (src_line > print.src_line)
495 {
496 putc (c: '\n', stream: stream);
497 print.src_line++;
498 }
499 }
500 else
501 emitted_line_marker = print_line_1 (src_loc, "", stream);
502
503 return emitted_line_marker;
504}
505
506/* If the token read on logical line LINE needs to be output on a
507 different line to the current one, output the required newlines or
508 a line marker. If a line marker was emitted, return TRUE otherwise
509 return FALSE. */
510
511static bool
512maybe_print_line (location_t src_loc)
513{
514 if (cpp_get_options (parse_in)->debug)
515 linemap_dump_location (line_table, src_loc,
516 print.outf);
517 return maybe_print_line_1 (src_loc, stream: print.outf);
518}
519
520/* Output a line marker for logical line LINE. Special flags are "1"
521 or "2" indicating entering or leaving a file. If the line marker
522 was effectively emitted, return TRUE otherwise return FALSE. */
523
524static bool
525print_line_1 (location_t src_loc, const char *special_flags, FILE *stream)
526{
527 bool emitted_line_marker = false;
528
529 /* End any previous line of text. */
530 if (print.printed)
531 putc (c: '\n', stream: stream);
532 print.printed = false;
533
534 if (src_loc != UNKNOWN_LOCATION && !flag_no_line_commands)
535 {
536 const char *file_path = LOCATION_FILE (src_loc);
537 size_t to_file_len = strlen (s: file_path);
538 unsigned char *to_file_quoted =
539 (unsigned char *) alloca (to_file_len * 4 + 1);
540
541 /* cpp_quote_string does not nul-terminate, so we have to do it
542 ourselves. */
543 unsigned char *p = cpp_quote_string (to_file_quoted,
544 (const unsigned char *) file_path,
545 to_file_len);
546 *p = '\0';
547
548 print.src_line = LOCATION_LINE (src_loc);
549 print.src_file = file_path;
550
551 fprintf (stream: stream, format: "# %u \"%s\"%s",
552 print.src_line, to_file_quoted, special_flags);
553
554 int sysp = in_system_header_at (loc: src_loc);
555 if (sysp == 2)
556 fputs (s: " 3 4", stream: stream);
557 else if (sysp == 1)
558 fputs (s: " 3", stream: stream);
559
560 putc (c: '\n', stream: stream);
561 emitted_line_marker = true;
562 }
563
564 return emitted_line_marker;
565}
566
567/* Output a line marker for logical line LINE. Special flags are "1"
568 or "2" indicating entering or leaving a file. Return TRUE if a
569 line marker was effectively emitted, FALSE otherwise. */
570
571static bool
572print_line (location_t src_loc, const char *special_flags)
573{
574 if (cpp_get_options (parse_in)->debug)
575 linemap_dump_location (line_table, src_loc,
576 print.outf);
577 return print_line_1 (src_loc, special_flags, stream: print.outf);
578}
579
580/* Helper function for cb_line_change and scan_translation_unit.
581 Return TRUE if a line marker is emitted, FALSE otherwise. */
582static bool
583do_line_change (cpp_reader *pfile, const cpp_token *token,
584 location_t src_loc, int parsing_args)
585{
586 bool emitted_line_marker = false;
587 if (define_queue || undef_queue)
588 dump_queued_macros (pfile);
589
590 if (token->type == CPP_EOF || parsing_args)
591 return false;
592
593 emitted_line_marker = maybe_print_line (src_loc);
594 print.prev = 0;
595 print.source = 0;
596
597 /* Supply enough spaces to put this token in its original column,
598 one space per column greater than 2, since scan_translation_unit
599 will provide a space if PREV_WHITE. Don't bother trying to
600 reconstruct tabs; we can't get it right in general, and nothing
601 ought to care. Some things do care; the fault lies with them.
602
603 Also do not output the spaces if this is a CPP_PRAGMA token. In this
604 case, libcpp has provided the location of the first token after #pragma,
605 so we would start at the wrong column. */
606 if (!CPP_OPTION (pfile, traditional) && token->type != CPP_PRAGMA)
607 {
608 int spaces = LOCATION_COLUMN (src_loc) - 2;
609 print.printed = true;
610
611 while (-- spaces >= 0)
612 putc (c: ' ', stream: print.outf);
613 }
614
615 return emitted_line_marker;
616}
617
618/* Called when a line of output is started. TOKEN is the first token
619 of the line, and at end of file will be CPP_EOF. */
620static void
621cb_line_change (cpp_reader *pfile, const cpp_token *token,
622 int parsing_args)
623{
624 do_line_change (pfile, token, src_loc: token->src_loc, parsing_args);
625}
626
627static void
628cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
629 const cpp_string *str)
630{
631 maybe_print_line (src_loc: line);
632 fprintf (stream: print.outf, format: "#ident %s\n", str->text);
633 print.src_line++;
634}
635
636static void
637cb_define (cpp_reader *pfile, location_t line, cpp_hashnode *node)
638{
639 const line_map_ordinary *map;
640
641 maybe_print_line (src_loc: line);
642 fputs (s: "#define ", stream: print.outf);
643
644 /* 'D' is whole definition; 'N' is name only. */
645 if (flag_dump_macros == 'D')
646 fputs (s: (const char *) cpp_macro_definition (pfile, node),
647 stream: print.outf);
648 else
649 fputs (s: (const char *) NODE_NAME (node), stream: print.outf);
650
651 putc (c: '\n', stream: print.outf);
652 print.printed = false;
653 linemap_resolve_location (line_table, loc: line,
654 lrk: LRK_MACRO_DEFINITION_LOCATION,
655 loc_map: &map);
656 print.src_line++;
657}
658
659static void
660cb_undef (cpp_reader *pfile, location_t line, cpp_hashnode *node)
661{
662 if (lang_hooks.preprocess_undef)
663 lang_hooks.preprocess_undef (pfile, line, node);
664 maybe_print_line (src_loc: line);
665 fprintf (stream: print.outf, format: "#undef %s\n", NODE_NAME (node));
666 print.src_line++;
667}
668
669static void
670cb_used_define (cpp_reader *pfile, location_t line ATTRIBUTE_UNUSED,
671 cpp_hashnode *node)
672{
673 if (cpp_user_macro_p (node))
674 {
675 macro_queue *q;
676 q = XNEW (macro_queue);
677 q->macro = xstrdup ((const char *) cpp_macro_definition (pfile, node));
678 q->next = define_queue;
679 define_queue = q;
680 }
681}
682
683static void
684cb_used_undef (cpp_reader *pfile ATTRIBUTE_UNUSED,
685 location_t line ATTRIBUTE_UNUSED,
686 cpp_hashnode *node)
687{
688 macro_queue *q;
689 q = XNEW (macro_queue);
690 q->macro = xstrdup ((const char *) NODE_NAME (node));
691 q->next = undef_queue;
692 undef_queue = q;
693}
694
695static void
696dump_queued_macros (cpp_reader *pfile ATTRIBUTE_UNUSED)
697{
698 macro_queue *q;
699
700 /* End the previous line of text. */
701 if (print.printed)
702 {
703 putc (c: '\n', stream: print.outf);
704 print.src_line++;
705 print.printed = false;
706 }
707
708 for (q = define_queue; q;)
709 {
710 macro_queue *oq;
711 fputs (s: "#define ", stream: print.outf);
712 fputs (s: q->macro, stream: print.outf);
713 putc (c: '\n', stream: print.outf);
714 print.printed = false;
715 print.src_line++;
716 oq = q;
717 q = q->next;
718 free (ptr: oq->macro);
719 free (ptr: oq);
720 }
721 define_queue = NULL;
722 for (q = undef_queue; q;)
723 {
724 macro_queue *oq;
725 fprintf (stream: print.outf, format: "#undef %s\n", q->macro);
726 print.src_line++;
727 oq = q;
728 q = q->next;
729 free (ptr: oq->macro);
730 free (ptr: oq);
731 }
732 undef_queue = NULL;
733}
734
735static void
736cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, location_t line,
737 const unsigned char *dir, const char *header, int angle_brackets,
738 const cpp_token **comments)
739{
740 maybe_print_line (src_loc: line);
741 if (angle_brackets)
742 fprintf (stream: print.outf, format: "#%s <%s>", dir, header);
743 else
744 fprintf (stream: print.outf, format: "#%s \"%s\"", dir, header);
745
746 if (comments != NULL)
747 {
748 while (*comments != NULL)
749 {
750 if ((*comments)->flags & PREV_WHITE)
751 putc (c: ' ', stream: print.outf);
752 cpp_output_token (*comments, print.outf);
753 ++comments;
754 }
755 }
756
757 putc (c: '\n', stream: print.outf);
758 print.printed = false;
759 print.src_line++;
760}
761
762/* Callback called when -fworking-director and -E to emit working
763 directory in cpp output file. */
764
765void
766pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
767{
768 size_t to_file_len = strlen (s: dir);
769 unsigned char *to_file_quoted =
770 (unsigned char *) alloca (to_file_len * 4 + 1);
771 unsigned char *p;
772
773 /* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */
774 p = cpp_quote_string (to_file_quoted, (const unsigned char *) dir, to_file_len);
775 *p = '\0';
776 fprintf (stream: print.outf, format: "# 1 \"%s//\"\n", to_file_quoted);
777}
778
779/* The file name, line number or system header flags have changed, as
780 described in MAP. */
781
782void
783pp_file_change (const line_map_ordinary *map)
784{
785 const char *flags = "";
786
787 if (flag_no_line_commands)
788 return;
789
790 if (map != NULL)
791 {
792 input_location = map->start_location;
793 if (print.first_time)
794 {
795 /* Avoid printing foo.i when the main file is foo.c. */
796 if (!cpp_get_options (parse_in)->preprocessed)
797 print_line (src_loc: map->start_location, special_flags: flags);
798 print.first_time = 0;
799 }
800 else
801 {
802 /* Bring current file to correct line when entering a new file. */
803 if (map->reason == LC_ENTER)
804 {
805 maybe_print_line (src_loc: linemap_included_from (ord_map: map));
806 flags = " 1";
807 }
808 else if (map->reason == LC_LEAVE)
809 flags = " 2";
810 print_line (src_loc: map->start_location, special_flags: flags);
811 }
812 }
813}
814
815/* Copy a #pragma directive to the preprocessed output. */
816static void
817cb_def_pragma (cpp_reader *pfile, location_t line)
818{
819 maybe_print_line (src_loc: line);
820 fputs (s: "#pragma ", stream: print.outf);
821 cpp_output_line (pfile, print.outf);
822 print.printed = false;
823 print.src_line++;
824}
825
826/* Stream a token as if we had seen it directly ourselves; needed
827 in case a token was lexed externally, e.g. while processing a
828 pragma. */
829void
830c_pp_stream_token (cpp_reader *pfile, const cpp_token *tok, location_t loc)
831{
832 gcc_assert (print.streamer);
833 print.streamer->stream (pfile, token: tok, loc);
834}
835
836/* Dump out the hash table. */
837static int
838dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED)
839{
840 if (cpp_user_macro_p (node))
841 {
842 fputs (s: "#define ", stream: print.outf);
843 fputs (s: (const char *) cpp_macro_definition (pfile, node),
844 stream: print.outf);
845 putc (c: '\n', stream: print.outf);
846 print.printed = false;
847 print.src_line++;
848 }
849
850 return 1;
851}
852
853/* Load in the PCH file NAME, open on FD. It was originally searched for
854 by ORIG_NAME. Also, print out a #include command so that the PCH
855 file can be loaded when the preprocessed output is compiled. */
856
857static void
858cb_read_pch (cpp_reader *pfile, const char *name,
859 int fd, const char *orig_name ATTRIBUTE_UNUSED)
860{
861 c_common_read_pch (pfile, name, fd, orig: orig_name);
862
863 fprintf (stream: print.outf, format: "#pragma GCC pch_preprocess \"%s\"\n", name);
864 print.src_line++;
865}
866

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