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

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