00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "line-map.h"
00026
00027 static void trace_include (const struct line_maps *, const struct line_map *);
00028
00029
00030
00031 void
00032 linemap_init (struct line_maps *set)
00033 {
00034 set->maps = NULL;
00035 set->allocated = 0;
00036 set->used = 0;
00037 set->last_listed = -1;
00038 set->trace_includes = false;
00039 set->depth = 0;
00040 set->cache = 0;
00041 set->highest_location = 0;
00042 set->highest_line = 0;
00043 set->max_column_hint = 0;
00044 }
00045
00046
00047
00048 void
00049 linemap_check_files_exited (struct line_maps *set)
00050 {
00051 struct line_map *map;
00052
00053
00054 for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
00055 map = INCLUDED_FROM (set, map))
00056 fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
00057 map->to_file);
00058 }
00059
00060
00061
00062 void
00063 linemap_free (struct line_maps *set)
00064 {
00065 if (set->maps)
00066 {
00067 linemap_check_files_exited (set);
00068
00069 free (set->maps);
00070 }
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 const struct line_map *
00088 linemap_add (struct line_maps *set, enum lc_reason reason,
00089 unsigned int sysp, const char *to_file, unsigned int to_line)
00090 {
00091 struct line_map *map;
00092 source_location start_location = set->highest_location + 1;
00093
00094 if (set->used && start_location < set->maps[set->used - 1].start_location)
00095 abort ();
00096
00097 if (set->used == set->allocated)
00098 {
00099 set->allocated = 2 * set->allocated + 256;
00100 set->maps = xrealloc (set->maps, set->allocated * sizeof (struct line_map));
00101 }
00102
00103 map = &set->maps[set->used];
00104
00105 if (to_file && *to_file == '\0')
00106 to_file = "<stdin>";
00107
00108
00109
00110 if (set->depth == 0)
00111 reason = LC_ENTER;
00112 else if (reason == LC_LEAVE)
00113 {
00114 struct line_map *from;
00115 bool error;
00116
00117 if (MAIN_FILE_P (map - 1))
00118 {
00119 if (to_file == NULL)
00120 {
00121 set->depth--;
00122 return NULL;
00123 }
00124 error = true;
00125 reason = LC_RENAME;
00126 from = map - 1;
00127 }
00128 else
00129 {
00130 from = INCLUDED_FROM (set, map - 1);
00131 error = to_file && strcmp (from->to_file, to_file);
00132 }
00133
00134
00135
00136 if (error)
00137 fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n",
00138 to_file);
00139
00140
00141 if (error || to_file == NULL)
00142 {
00143 to_file = from->to_file;
00144 to_line = SOURCE_LINE (from, from[1].start_location);
00145 sysp = from->sysp;
00146 }
00147 }
00148
00149 map->reason = reason;
00150 map->sysp = sysp;
00151 map->start_location = start_location;
00152 map->to_file = to_file;
00153 map->to_line = to_line;
00154 set->cache = set->used++;
00155 map->column_bits = 0;
00156 set->highest_location = start_location;
00157 set->highest_line = start_location;
00158 set->max_column_hint = 0;
00159
00160 if (reason == LC_ENTER)
00161 {
00162 map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
00163 set->depth++;
00164 if (set->trace_includes)
00165 trace_include (set, map);
00166 }
00167 else if (reason == LC_RENAME)
00168 map->included_from = map[-1].included_from;
00169 else if (reason == LC_LEAVE)
00170 {
00171 set->depth--;
00172 map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
00173 }
00174
00175 return map;
00176 }
00177
00178 source_location
00179 linemap_line_start (struct line_maps *set, unsigned int to_line,
00180 unsigned int max_column_hint)
00181 {
00182 struct line_map *map = &set->maps[set->used - 1];
00183 source_location highest = set->highest_location;
00184 source_location r;
00185 unsigned int last_line = SOURCE_LINE (map, set->highest_line);
00186 int line_delta = to_line - last_line;
00187 bool add_map = false;
00188 if (line_delta < 0
00189 || (line_delta > 10 && line_delta * map->column_bits > 1000)
00190 || (max_column_hint >= (1U << map->column_bits))
00191 || (max_column_hint <= 80 && map->column_bits >= 10))
00192 {
00193 add_map = true;
00194 }
00195 else
00196 max_column_hint = set->max_column_hint;
00197 if (add_map)
00198 {
00199 int column_bits;
00200 if (max_column_hint > 100000 || highest > 0xC0000000)
00201 {
00202
00203
00204 max_column_hint = 0;
00205 if (highest >0xF0000000)
00206 return 0;
00207 column_bits = 0;
00208 }
00209 else
00210 {
00211 column_bits = 7;
00212 while (max_column_hint >= (1U << column_bits))
00213 column_bits++;
00214 max_column_hint = 1U << column_bits;
00215 }
00216
00217
00218 if (line_delta < 0
00219 || last_line != map->to_line
00220 || SOURCE_COLUMN (map, highest) >= (1U << column_bits))
00221 map = (struct line_map*) linemap_add (set, LC_RENAME, map->sysp,
00222 map->to_file, to_line);
00223 map->column_bits = column_bits;
00224 r = map->start_location + ((to_line - map->to_line) << column_bits);
00225 }
00226 else
00227 r = highest - SOURCE_COLUMN (map, highest)
00228 + (line_delta << map->column_bits);
00229 set->highest_line = r;
00230 if (r > set->highest_location)
00231 set->highest_location = r;
00232 set->max_column_hint = max_column_hint;
00233 return r;
00234 }
00235
00236 source_location
00237 linemap_position_for_column (struct line_maps *set, unsigned int to_column)
00238 {
00239 source_location r = set->highest_line;
00240 if (to_column >= set->max_column_hint)
00241 {
00242 if (r >= 0xC000000 || to_column > 100000)
00243 {
00244
00245 return r;
00246 }
00247 else
00248 {
00249 struct line_map *map = &set->maps[set->used - 1];
00250 r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
00251 }
00252 }
00253 r = r + to_column;
00254 if (r >= set->highest_location)
00255 set->highest_location = r;
00256 return r;
00257 }
00258
00259
00260
00261
00262
00263
00264 const struct line_map *
00265 linemap_lookup (struct line_maps *set, source_location line)
00266 {
00267 unsigned int md, mn, mx;
00268 const struct line_map *cached;
00269
00270 mn = set->cache;
00271 mx = set->used;
00272
00273 cached = &set->maps[mn];
00274
00275 if (line >= cached->start_location)
00276 {
00277 if (mn + 1 == mx || line < cached[1].start_location)
00278 return cached;
00279 }
00280 else
00281 {
00282 mx = mn;
00283 mn = 0;
00284 }
00285
00286 while (mx - mn > 1)
00287 {
00288 md = (mn + mx) / 2;
00289 if (set->maps[md].start_location > line)
00290 mx = md;
00291 else
00292 mn = md;
00293 }
00294
00295 set->cache = mn;
00296 return &set->maps[mn];
00297 }
00298
00299
00300
00301
00302
00303 void
00304 linemap_print_containing_files (struct line_maps *set,
00305 const struct line_map *map)
00306 {
00307 if (MAIN_FILE_P (map) || set->last_listed == map->included_from)
00308 return;
00309
00310 set->last_listed = map->included_from;
00311 map = INCLUDED_FROM (set, map);
00312
00313 fprintf (stderr, _("In file included from %s:%u"),
00314 map->to_file, LAST_SOURCE_LINE (map));
00315
00316 while (! MAIN_FILE_P (map))
00317 {
00318 map = INCLUDED_FROM (set, map);
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331 fprintf (stderr, _(",\n from %s:%u"),
00332 map->to_file, LAST_SOURCE_LINE (map));
00333 }
00334
00335 fputs (":\n", stderr);
00336 }
00337
00338
00339
00340 static void
00341 trace_include (const struct line_maps *set, const struct line_map *map)
00342 {
00343 unsigned int i = set->depth;
00344
00345 while (--i)
00346 putc ('.', stderr);
00347 fprintf (stderr, " %s\n", map->to_file);
00348 }