1169695Skan/* Map logical line numbers to (source file, line number) pairs. 2169695Skan Copyright (C) 2001, 2003, 2004 3169695Skan Free Software Foundation, Inc. 4169695Skan 5169695SkanThis program is free software; you can redistribute it and/or modify it 6169695Skanunder the terms of the GNU General Public License as published by the 7169695SkanFree Software Foundation; either version 2, or (at your option) any 8169695Skanlater version. 9169695Skan 10169695SkanThis program is distributed in the hope that it will be useful, 11169695Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 12169695SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13169695SkanGNU General Public License for more details. 14169695Skan 15169695SkanYou should have received a copy of the GNU General Public License 16169695Skanalong with this program; if not, write to the Free Software 17169695SkanFoundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18169695Skan 19169695Skan In other words, you are welcome to use, share and improve this program. 20169695Skan You are forbidden to forbid anyone else to use, share and improve 21169695Skan what you give them. Help stamp out software-hoarding! */ 22169695Skan 23169695Skan#include "config.h" 24169695Skan#include "system.h" 25169695Skan#include "line-map.h" 26169695Skan 27169695Skanstatic void trace_include (const struct line_maps *, const struct line_map *); 28169695Skan 29169695Skan/* Initialize a line map set. */ 30169695Skan 31169695Skanvoid 32169695Skanlinemap_init (struct line_maps *set) 33169695Skan{ 34169695Skan set->maps = NULL; 35169695Skan set->allocated = 0; 36169695Skan set->used = 0; 37169695Skan set->last_listed = -1; 38169695Skan set->trace_includes = false; 39169695Skan set->depth = 0; 40169695Skan set->cache = 0; 41169695Skan set->highest_location = 0; 42169695Skan set->highest_line = 0; 43169695Skan set->max_column_hint = 0; 44169695Skan} 45169695Skan 46169695Skan/* Check for and warn about line_maps entered but not exited. */ 47169695Skan 48169695Skanvoid 49169695Skanlinemap_check_files_exited (struct line_maps *set) 50169695Skan{ 51169695Skan struct line_map *map; 52169695Skan /* Depending upon whether we are handling preprocessed input or 53169695Skan not, this can be a user error or an ICE. */ 54169695Skan for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map); 55169695Skan map = INCLUDED_FROM (set, map)) 56169695Skan fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n", 57169695Skan map->to_file); 58169695Skan} 59169695Skan 60169695Skan/* Free a line map set. */ 61169695Skan 62169695Skanvoid 63169695Skanlinemap_free (struct line_maps *set) 64169695Skan{ 65169695Skan if (set->maps) 66169695Skan { 67169695Skan linemap_check_files_exited (set); 68169695Skan 69169695Skan free (set->maps); 70169695Skan } 71169695Skan} 72169695Skan 73169695Skan/* Add a mapping of logical source line to physical source file and 74169695Skan line number. 75169695Skan 76169695Skan The text pointed to by TO_FILE must have a lifetime 77169695Skan at least as long as the final call to lookup_line (). An empty 78169695Skan TO_FILE means standard input. If reason is LC_LEAVE, and 79169695Skan TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their 80169695Skan natural values considering the file we are returning to. 81169695Skan 82169695Skan FROM_LINE should be monotonic increasing across calls to this 83169695Skan function. A call to this function can relocate the previous set of 84169695Skan A call to this function can relocate the previous set of 85169695Skan maps, so any stored line_map pointers should not be used. */ 86169695Skan 87169695Skanconst struct line_map * 88169695Skanlinemap_add (struct line_maps *set, enum lc_reason reason, 89169695Skan unsigned int sysp, const char *to_file, unsigned int to_line) 90169695Skan{ 91169695Skan struct line_map *map; 92169695Skan source_location start_location = set->highest_location + 1; 93169695Skan 94169695Skan if (set->used && start_location < set->maps[set->used - 1].start_location) 95169695Skan abort (); 96169695Skan 97169695Skan if (set->used == set->allocated) 98169695Skan { 99169695Skan set->allocated = 2 * set->allocated + 256; 100169695Skan set->maps = XRESIZEVEC (struct line_map, set->maps, set->allocated); 101169695Skan } 102169695Skan 103169695Skan map = &set->maps[set->used]; 104169695Skan 105169695Skan if (to_file && *to_file == '\0') 106169695Skan to_file = "<stdin>"; 107169695Skan 108169695Skan /* If we don't keep our line maps consistent, we can easily 109169695Skan segfault. Don't rely on the client to do it for us. */ 110169695Skan if (set->depth == 0) 111169695Skan reason = LC_ENTER; 112169695Skan else if (reason == LC_LEAVE) 113169695Skan { 114169695Skan struct line_map *from; 115169695Skan bool error; 116169695Skan 117169695Skan if (MAIN_FILE_P (map - 1)) 118169695Skan { 119169695Skan if (to_file == NULL) 120169695Skan { 121169695Skan set->depth--; 122169695Skan return NULL; 123169695Skan } 124169695Skan error = true; 125169695Skan reason = LC_RENAME; 126169695Skan from = map - 1; 127169695Skan } 128169695Skan else 129169695Skan { 130169695Skan from = INCLUDED_FROM (set, map - 1); 131169695Skan error = to_file && strcmp (from->to_file, to_file); 132169695Skan } 133169695Skan 134169695Skan /* Depending upon whether we are handling preprocessed input or 135169695Skan not, this can be a user error or an ICE. */ 136169695Skan if (error) 137169695Skan fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n", 138169695Skan to_file); 139169695Skan 140169695Skan /* A TO_FILE of NULL is special - we use the natural values. */ 141169695Skan if (error || to_file == NULL) 142169695Skan { 143169695Skan to_file = from->to_file; 144169695Skan to_line = SOURCE_LINE (from, from[1].start_location); 145169695Skan sysp = from->sysp; 146169695Skan } 147169695Skan } 148169695Skan 149169695Skan map->reason = reason; 150169695Skan map->sysp = sysp; 151169695Skan map->start_location = start_location; 152169695Skan map->to_file = to_file; 153169695Skan map->to_line = to_line; 154169695Skan set->cache = set->used++; 155169695Skan map->column_bits = 0; 156169695Skan set->highest_location = start_location; 157169695Skan set->highest_line = start_location; 158169695Skan set->max_column_hint = 0; 159169695Skan 160169695Skan if (reason == LC_ENTER) 161169695Skan { 162169695Skan map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2); 163169695Skan set->depth++; 164169695Skan if (set->trace_includes) 165169695Skan trace_include (set, map); 166169695Skan } 167169695Skan else if (reason == LC_RENAME) 168169695Skan map->included_from = map[-1].included_from; 169169695Skan else if (reason == LC_LEAVE) 170169695Skan { 171169695Skan set->depth--; 172169695Skan map->included_from = INCLUDED_FROM (set, map - 1)->included_from; 173169695Skan } 174169695Skan 175169695Skan return map; 176169695Skan} 177169695Skan 178169695Skansource_location 179169695Skanlinemap_line_start (struct line_maps *set, unsigned int to_line, 180169695Skan unsigned int max_column_hint) 181169695Skan{ 182169695Skan struct line_map *map = &set->maps[set->used - 1]; 183169695Skan source_location highest = set->highest_location; 184169695Skan source_location r; 185169695Skan unsigned int last_line = SOURCE_LINE (map, set->highest_line); 186169695Skan int line_delta = to_line - last_line; 187169695Skan bool add_map = false; 188169695Skan if (line_delta < 0 189169695Skan || (line_delta > 10 && line_delta * map->column_bits > 1000) 190169695Skan || (max_column_hint >= (1U << map->column_bits)) 191169695Skan || (max_column_hint <= 80 && map->column_bits >= 10)) 192169695Skan { 193169695Skan add_map = true; 194169695Skan } 195169695Skan else 196169695Skan max_column_hint = set->max_column_hint; 197169695Skan if (add_map) 198169695Skan { 199169695Skan int column_bits; 200169695Skan if (max_column_hint > 100000 || highest > 0xC0000000) 201169695Skan { 202169695Skan /* If the column number is ridiculous or we've allocated a huge 203169695Skan number of source_locations, give up on column numbers. */ 204169695Skan max_column_hint = 0; 205169695Skan if (highest >0xF0000000) 206169695Skan return 0; 207169695Skan column_bits = 0; 208169695Skan } 209169695Skan else 210169695Skan { 211169695Skan column_bits = 7; 212169695Skan while (max_column_hint >= (1U << column_bits)) 213169695Skan column_bits++; 214169695Skan max_column_hint = 1U << column_bits; 215169695Skan } 216169695Skan /* Allocate the new line_map. However, if the current map only has a 217169695Skan single line we can sometimes just increase its column_bits instead. */ 218169695Skan if (line_delta < 0 219169695Skan || last_line != map->to_line 220169695Skan || SOURCE_COLUMN (map, highest) >= (1U << column_bits)) 221169695Skan map = (struct line_map*) linemap_add (set, LC_RENAME, map->sysp, 222169695Skan map->to_file, to_line); 223169695Skan map->column_bits = column_bits; 224169695Skan r = map->start_location + ((to_line - map->to_line) << column_bits); 225169695Skan } 226169695Skan else 227169695Skan r = highest - SOURCE_COLUMN (map, highest) 228169695Skan + (line_delta << map->column_bits); 229169695Skan set->highest_line = r; 230169695Skan if (r > set->highest_location) 231169695Skan set->highest_location = r; 232169695Skan set->max_column_hint = max_column_hint; 233169695Skan return r; 234169695Skan} 235169695Skan 236169695Skansource_location 237169695Skanlinemap_position_for_column (struct line_maps *set, unsigned int to_column) 238169695Skan{ 239169695Skan source_location r = set->highest_line; 240169695Skan if (to_column >= set->max_column_hint) 241169695Skan { 242169695Skan if (r >= 0xC000000 || to_column > 100000) 243169695Skan { 244169695Skan /* Running low on source_locations - disable column numbers. */ 245169695Skan return r; 246169695Skan } 247169695Skan else 248169695Skan { 249169695Skan struct line_map *map = &set->maps[set->used - 1]; 250169695Skan r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50); 251169695Skan } 252169695Skan } 253169695Skan r = r + to_column; 254169695Skan if (r >= set->highest_location) 255169695Skan set->highest_location = r; 256169695Skan return r; 257169695Skan} 258169695Skan 259169695Skan/* Given a logical line, returns the map from which the corresponding 260169695Skan (source file, line) pair can be deduced. Since the set is built 261169695Skan chronologically, the logical lines are monotonic increasing, and so 262169695Skan the list is sorted and we can use a binary search. */ 263169695Skan 264169695Skanconst struct line_map * 265169695Skanlinemap_lookup (struct line_maps *set, source_location line) 266169695Skan{ 267169695Skan unsigned int md, mn, mx; 268169695Skan const struct line_map *cached; 269169695Skan 270169695Skan mn = set->cache; 271169695Skan mx = set->used; 272169695Skan 273169695Skan cached = &set->maps[mn]; 274169695Skan /* We should get a segfault if no line_maps have been added yet. */ 275169695Skan if (line >= cached->start_location) 276169695Skan { 277169695Skan if (mn + 1 == mx || line < cached[1].start_location) 278169695Skan return cached; 279169695Skan } 280169695Skan else 281169695Skan { 282169695Skan mx = mn; 283169695Skan mn = 0; 284169695Skan } 285169695Skan 286169695Skan while (mx - mn > 1) 287169695Skan { 288169695Skan md = (mn + mx) / 2; 289169695Skan if (set->maps[md].start_location > line) 290169695Skan mx = md; 291169695Skan else 292169695Skan mn = md; 293169695Skan } 294169695Skan 295169695Skan set->cache = mn; 296169695Skan return &set->maps[mn]; 297169695Skan} 298169695Skan 299169695Skan/* Print the file names and line numbers of the #include commands 300169695Skan which led to the map MAP, if any, to stderr. Nothing is output if 301169695Skan the most recently listed stack is the same as the current one. */ 302169695Skan 303169695Skanvoid 304169695Skanlinemap_print_containing_files (struct line_maps *set, 305169695Skan const struct line_map *map) 306169695Skan{ 307169695Skan if (MAIN_FILE_P (map) || set->last_listed == map->included_from) 308169695Skan return; 309169695Skan 310169695Skan set->last_listed = map->included_from; 311169695Skan map = INCLUDED_FROM (set, map); 312169695Skan 313169695Skan fprintf (stderr, _("In file included from %s:%u"), 314169695Skan map->to_file, LAST_SOURCE_LINE (map)); 315169695Skan 316169695Skan while (! MAIN_FILE_P (map)) 317169695Skan { 318169695Skan map = INCLUDED_FROM (set, map); 319169695Skan /* Translators note: this message is used in conjunction 320169695Skan with "In file included from %s:%ld" and some other 321169695Skan tricks. We want something like this: 322169695Skan 323169695Skan | In file included from sys/select.h:123, 324169695Skan | from sys/types.h:234, 325169695Skan | from userfile.c:31: 326169695Skan | bits/select.h:45: <error message here> 327169695Skan 328169695Skan with all the "from"s lined up. 329169695Skan The trailing comma is at the beginning of this message, 330169695Skan and the trailing colon is not translated. */ 331169695Skan fprintf (stderr, _(",\n from %s:%u"), 332169695Skan map->to_file, LAST_SOURCE_LINE (map)); 333169695Skan } 334169695Skan 335169695Skan fputs (":\n", stderr); 336169695Skan} 337169695Skan 338169695Skan/* Print an include trace, for e.g. the -H option of the preprocessor. */ 339169695Skan 340169695Skanstatic void 341169695Skantrace_include (const struct line_maps *set, const struct line_map *map) 342169695Skan{ 343169695Skan unsigned int i = set->depth; 344169695Skan 345169695Skan while (--i) 346169695Skan putc ('.', stderr); 347169695Skan fprintf (stderr, " %s\n", map->to_file); 348169695Skan} 349