static const struct line_map* first_map_in_common_1 (struct line_maps *set, source_location *loc0, source_location *loc1) { source_location l0 = *loc0, l1 = *loc1; const struct line_map *map0 = linemap_lookup (set, l0), *map1 = linemap_lookup (set, l1); while (linemap_macro_expansion_map_p (map0) && linemap_macro_expansion_map_p (map1) && (map0 != map1)) { if (MAP_START_LOCATION (map0) < MAP_START_LOCATION (map1)) { l0 = linemap_macro_map_loc_to_exp_point (map0, l0); map0 = linemap_lookup (set, l0); } else { l1 = linemap_macro_map_loc_to_exp_point (map1, l1); map1 = linemap_lookup (set, l1); } } if (map0 == map1) { *loc0 = l0; *loc1 = l1; return map0; } return NULL; }
/* Print the logical file location (LINE, COL) in preparation for a diagnostic. Outputs the #include chain if it has changed. A line of zero suppresses the include stack, and outputs the program name instead. */ static void print_location (cpp_reader *pfile, source_location line, unsigned int col) { if (line == 0) fprintf (stderr, "%s: ", progname); else { const struct line_map *map; linenum_type lin; map = linemap_lookup (pfile->line_table, line); linemap_print_containing_files (pfile->line_table, map); lin = SOURCE_LINE (map, line); if (col == 0) { col = SOURCE_COLUMN (map, line); if (col == 0) col = 1; } if (lin == 0) fprintf (stderr, "%s:", map->to_file); else if (CPP_OPTION (pfile, show_column) == 0) fprintf (stderr, "%s:%u:", map->to_file, lin); else fprintf (stderr, "%s:%u:%u:", map->to_file, lin, col); fputc (' ', stderr); } }
/* Helper function for cb_line_change and scan_translation_unit. */ static void do_line_change (cpp_reader *pfile, const cpp_token *token, source_location src_loc, int parsing_args) { if (define_queue || undef_queue) dump_queued_macros (pfile); if (token->type == CPP_EOF || parsing_args) return; maybe_print_line (src_loc); print.prev = 0; print.source = 0; /* Supply enough spaces to put this token in its original column, one space per column greater than 2, since scan_translation_unit will provide a space if PREV_WHITE. Don't bother trying to reconstruct tabs; we can't get it right in general, and nothing ought to care. Some things do care; the fault lies with them. */ if (!CPP_OPTION (pfile, traditional)) { const struct line_map *map = linemap_lookup (line_table, src_loc); int spaces = SOURCE_COLUMN (map, src_loc) - 2; print.printed = 1; while (-- spaces >= 0) putc (' ', print.outf); } }
/* #define callback for DWARF and DWARF2 debug info. */ static void cb_define (cpp_reader *pfile, source_location loc, cpp_hashnode *node) { const struct line_map *map = linemap_lookup (&line_table, loc); (*debug_hooks->define) (SOURCE_LINE (map, loc), (const char *) cpp_macro_definition (pfile, node)); }
/* If the token read on logical line LINE needs to be output on a different line to the current one, output the required newlines or a line marker, and return 1. Otherwise return 0. */ static void maybe_print_line (source_location src_loc) { const struct line_map *map = linemap_lookup (line_table, src_loc); int src_line = SOURCE_LINE (map, src_loc); /* End the previous line of text. */ if (print.printed) { putc ('\n', print.outf); print.src_line++; print.printed = 0; } if (!flag_no_line_commands && src_line >= print.src_line && src_line < print.src_line + 8 && strcmp (map->to_file, print.src_file) == 0) { while (src_line > print.src_line) { putc ('\n', print.outf); print.src_line++; } } else print_line (src_loc, ""); }
/* If LOC is the virtual location of a token coming from the expansion of a macro M and if its spelling location is reserved (e.g, a location for a built-in token), then this function unwinds (using linemap_unwind_toward_expansion) the location until a location that is not reserved and is not in a system header is reached. In other words, this unwinds the reserved location until a location that is in real source code is reached. Otherwise, if the spelling location for LOC is not reserved or if LOC doesn't come from the expansion of a macro, the function returns LOC as is and *MAP is not touched. *MAP is set to the map of the returned location if the later is different from LOC. */ source_location linemap_unwind_to_first_non_reserved_loc (struct line_maps *set, source_location loc, const struct line_map **map) { source_location resolved_loc; const struct line_map *map0 = NULL, *map1 = NULL; map0 = linemap_lookup (set, loc); if (!linemap_macro_expansion_map_p (map0)) return loc; resolved_loc = linemap_resolve_location (set, loc, LRK_SPELLING_LOCATION, &map1); if (resolved_loc >= RESERVED_LOCATION_COUNT && !LINEMAP_SYSP (map1)) return loc; while (linemap_macro_expansion_map_p (map0) && (resolved_loc < RESERVED_LOCATION_COUNT || LINEMAP_SYSP (map1))) { loc = linemap_unwind_toward_expansion (set, loc, &map0); resolved_loc = linemap_resolve_location (set, loc, LRK_SPELLING_LOCATION, &map1); } if (map != NULL) *map = map0; return loc; }
static void cb_def_pragma (cpp_reader *pfile, source_location loc) { /* Issue a warning message if we have been asked to do so. Ignore unknown pragmas in system headers unless an explicit -Wunknown-pragmas has been given. */ if (warn_unknown_pragmas > in_system_header) { const unsigned char *space, *name; const cpp_token *s; #ifndef USE_MAPPED_LOCATION location_t fe_loc; const struct line_map *map = linemap_lookup (&line_table, loc); fe_loc.file = map->to_file; fe_loc.line = SOURCE_LINE (map, loc); #else location_t fe_loc = loc; #endif space = name = (const unsigned char *) ""; s = cpp_get_token (pfile); if (s->type != CPP_EOF) { space = cpp_token_as_text (pfile, s); s = cpp_get_token (pfile); if (s->type == CPP_NAME) name = cpp_token_as_text (pfile, s); } warning (OPT_Wunknown_pragmas, "%Hignoring #pragma %s %s", &fe_loc, space, name); } }
/* Output a line marker for logical line LINE. Special flags are "1" or "2" indicating entering or leaving a file. */ static void print_line (source_location src_loc, const char *special_flags) { /* End any previous line of text. */ if (print.printed) putc ('\n', print.outf); print.printed = 0; if (!flag_no_line_commands) { const struct line_map *map = linemap_lookup (&line_table, src_loc); size_t to_file_len = strlen (map->to_file); unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1); unsigned char *p; print.src_line = SOURCE_LINE (map, src_loc); /* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */ p = cpp_quote_string (to_file_quoted, (unsigned char *) map->to_file, to_file_len); *p = '\0'; fprintf (print.outf, "# %u \"%s\"%s", print.src_line, to_file_quoted, special_flags); if (map->sysp == 2) fputs (" 3 4", print.outf); else if (map->sysp == 1) fputs (" 3", print.outf); putc ('\n', print.outf); } }
/* #undef callback for DWARF and DWARF2 debug info. */ static void cb_undef (cpp_reader * ARG_UNUSED (pfile), source_location loc, cpp_hashnode *node) { const struct line_map *map = linemap_lookup (&line_table, loc); (*debug_hooks->undef) (SOURCE_LINE (map, loc), (const char *) NODE_NAME (node)); }
source_location linemap_unwind_toward_expansion (struct line_maps *set, source_location loc, const struct line_map **map) { source_location resolved_location; const struct line_map *resolved_map; resolved_location = linemap_macro_map_loc_unwind_toward_spelling (*map, loc); resolved_map = linemap_lookup (set, resolved_location); if (!linemap_macro_expansion_map_p (resolved_map)) { resolved_location = linemap_macro_map_loc_to_exp_point (*map, loc); resolved_map = linemap_lookup (set, resolved_location); } *map = resolved_map; return resolved_location; }
/* Print the logical file location (LINE, COL) in preparation for a diagnostic. Outputs the #include chain if it has changed. A line of zero suppresses the include stack, and outputs the program name instead. */ static void print_location (cpp_reader *pfile, source_location line, unsigned int col) { /* APPLE LOCAL begin error-colon */ const char *estr; { static int done = 0; if ( ! done) { done = 1; /* Do this only once. */ /* Pretend we saw "-w" on commandline. */ if (getenv ("GCC_DASH_W")) CPP_OPTION (pfile, inhibit_warnings) = 1; /* referenced by diagnostic.h:diagnostic_report_warnings() */ if (getenv ("GCC_ERROR_COLON")) gcc_error_colon = 1; } } estr = (gcc_error_colon) ? "error:" : "" ; /* APPLE LOCAL end error-colon */ if (line == 0) fprintf (stderr, "%s: ", progname); else { const struct line_map *map; unsigned int lin; map = linemap_lookup (pfile->line_table, line); linemap_print_containing_files (pfile->line_table, map); lin = SOURCE_LINE (map, line); if (col == 0) { col = SOURCE_COLUMN (map, line); if (col == 0) col = 1; } /* APPLE LOCAL begin error-colon */ if (lin == 0) fprintf (stderr, "%s:%s", map->to_file, estr); else if (CPP_OPTION (pfile, show_column) == 0) fprintf (stderr, "%s:%u:%s", map->to_file, lin, estr); else fprintf (stderr, "%s:%u:%u:%s", map->to_file, lin, col, estr); /* APPLE LOCAL end error-colon */ fputc (' ', stderr); } }
/* Called at the start of every non-empty line. TOKEN is the first lexed token on the line. Used for diagnostic line numbers. */ static void cb_line_change (cpp_reader * ARG_UNUSED (pfile), const cpp_token *token, int parsing_args) { if (token->type != CPP_EOF && !parsing_args) #ifdef USE_MAPPED_LOCATION input_location = token->src_loc; #else { source_location loc = token->src_loc; const struct line_map *map = linemap_lookup (&line_table, loc); input_line = SOURCE_LINE (map, loc); } #endif }
static source_location get_loc (unsigned int line_num, unsigned int col_num) { /* Use input_location to get the relevant line_map */ const struct line_map_ordinary *line_map = (const line_map_ordinary *)(linemap_lookup (line_table, input_location)); /* Convert from 0-based column numbers to 1-based column numbers. */ source_location loc = linemap_position_for_line_and_column (line_map, line_num, col_num + 1); return loc; }
void diagnostic_report_current_module (diagnostic_context *context) { const struct line_map *map; if (pp_needs_newline (context->printer)) { pp_newline (context->printer); pp_needs_newline (context->printer) = false; } if (input_location <= BUILTINS_LOCATION) return; map = linemap_lookup (line_table, input_location); if (map && diagnostic_last_module_changed (context, map)) { diagnostic_set_last_module (context, map); if (! MAIN_FILE_P (map)) { map = INCLUDED_FROM (line_table, map); if (flag_show_column) pp_verbatim (context->printer, "In file included from %s:%d:%d", map->to_file, LAST_SOURCE_LINE (map), LAST_SOURCE_COLUMN (map)); else pp_verbatim (context->printer, "In file included from %s:%d", map->to_file, LAST_SOURCE_LINE (map)); while (! MAIN_FILE_P (map)) { map = INCLUDED_FROM (line_table, map); pp_verbatim (context->printer, ",\n from %s:%d", map->to_file, LAST_SOURCE_LINE (map)); } pp_verbatim (context->printer, ":"); pp_newline (context->printer); } } }
static source_location linemap_macro_loc_to_exp_point (struct line_maps *set, source_location location, const struct line_map **original_map) { struct line_map *map; linemap_assert (set && location >= RESERVED_LOCATION_COUNT); while (true) { map = (struct line_map*) linemap_lookup (set, location); if (!linemap_macro_expansion_map_p (map)) break; location = linemap_macro_map_loc_to_exp_point (map, location); } if (original_map) *original_map = map; return location; }
int linemap_location_in_system_header_p (struct line_maps *set, source_location location) { const struct line_map *map = NULL; if (location < RESERVED_LOCATION_COUNT) return false; /* Let's look at where the token for LOCATION comes from. */ while (true) { map = linemap_lookup (set, location); if (map != NULL) { if (!linemap_macro_expansion_map_p (map)) /* It's a normal token. */ return LINEMAP_SYSP (map); else { /* It's a token resulting from a macro expansion. */ source_location loc = linemap_macro_map_loc_unwind_toward_spelling (map, location); if (loc < RESERVED_LOCATION_COUNT) /* This token might come from a built-in macro. Let's look at where that macro got expanded. */ location = linemap_macro_map_loc_to_exp_point (map, location); else location = loc; } } else break; } return false; }
/* Writes out the preprocessed file, handling spacing and paste avoidance issues. */ static void scan_translation_unit (cpp_reader *pfile) { bool avoid_paste = false; bool do_line_adjustments = cpp_get_options (parse_in)->lang != CLK_ASM && !flag_no_line_commands; bool in_pragma = false; print.source = NULL; for (;;) { source_location loc; const cpp_token *token = cpp_get_token_with_location (pfile, &loc); if (token->type == CPP_PADDING) { avoid_paste = true; if (print.source == NULL || (!(print.source->flags & PREV_WHITE) && token->val.source == NULL)) print.source = token->val.source; continue; } if (token->type == CPP_EOF) break; /* Subtle logic to output a space if and only if necessary. */ if (avoid_paste) { const struct line_map *map = linemap_lookup (line_table, loc); int src_line = SOURCE_LINE (map, loc); if (print.source == NULL) print.source = token; if (src_line != print.src_line && do_line_adjustments && !in_pragma) { do_line_change (pfile, token, loc, false); putc (' ', print.outf); } else if (print.source->flags & PREV_WHITE || (print.prev && cpp_avoid_paste (pfile, print.prev, token)) || (print.prev == NULL && token->type == CPP_HASH)) putc (' ', print.outf); } else if (token->flags & PREV_WHITE) { const struct line_map *map = linemap_lookup (line_table, loc); int src_line = SOURCE_LINE (map, loc); if (src_line != print.src_line && do_line_adjustments && !in_pragma) do_line_change (pfile, token, loc, false); putc (' ', print.outf); } avoid_paste = false; print.source = NULL; print.prev = token; if (token->type == CPP_PRAGMA) { const char *space; const char *name; maybe_print_line (token->src_loc); fputs ("#pragma ", print.outf); c_pp_lookup_pragma (token->val.pragma, &space, &name); if (space) fprintf (print.outf, "%s %s", space, name); else fprintf (print.outf, "%s", name); print.printed = 1; in_pragma = true; } else if (token->type == CPP_PRAGMA_EOL) { maybe_print_line (token->src_loc); in_pragma = false; } else cpp_output_token (token, print.outf); if (token->type == CPP_COMMENT) account_for_newlines (token->val.str.text, token->val.str.len); } }