OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [libcpp/] [line-map.c] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Map logical line numbers to (source file, line number) pairs.
2
   Copyright (C) 2001, 2003, 2004
3
   Free Software Foundation, Inc.
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 2, 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; if not, write to the Free Software
17
Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 
19
 In other words, you are welcome to use, share and improve this program.
20
 You are forbidden to forbid anyone else to use, share and improve
21
 what you give them.   Help stamp out software-hoarding!  */
22
 
23
#include "config.h"
24
#include "system.h"
25
#include "line-map.h"
26
 
27
static void trace_include (const struct line_maps *, const struct line_map *);
28
 
29
/* Initialize a line map set.  */
30
 
31
void
32
linemap_init (struct line_maps *set)
33
{
34
  set->maps = NULL;
35
  set->allocated = 0;
36
  set->used = 0;
37
  set->last_listed = -1;
38
  set->trace_includes = false;
39
  set->depth = 0;
40
  set->cache = 0;
41
  set->highest_location = 0;
42
  set->highest_line = 0;
43
  set->max_column_hint = 0;
44
}
45
 
46
/* Check for and warn about line_maps entered but not exited.  */
47
 
48
void
49
linemap_check_files_exited (struct line_maps *set)
50
{
51
  struct line_map *map;
52
  /* Depending upon whether we are handling preprocessed input or
53
     not, this can be a user error or an ICE.  */
54
  for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
55
       map = INCLUDED_FROM (set, map))
56
    fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
57
             map->to_file);
58
}
59
 
60
/* Free a line map set.  */
61
 
62
void
63
linemap_free (struct line_maps *set)
64
{
65
  if (set->maps)
66
    {
67
      linemap_check_files_exited (set);
68
 
69
      free (set->maps);
70
    }
71
}
72
 
73
/* Add a mapping of logical source line to physical source file and
74
   line number.
75
 
76
   The text pointed to by TO_FILE must have a lifetime
77
   at least as long as the final call to lookup_line ().  An empty
78
   TO_FILE means standard input.  If reason is LC_LEAVE, and
79
   TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
80
   natural values considering the file we are returning to.
81
 
82
   FROM_LINE should be monotonic increasing across calls to this
83
   function.  A call to this function can relocate the previous set of
84
   A call to this function can relocate the previous set of
85
   maps, so any stored line_map pointers should not be used.  */
86
 
87
const struct line_map *
88
linemap_add (struct line_maps *set, enum lc_reason reason,
89
             unsigned int sysp, const char *to_file, unsigned int to_line)
90
{
91
  struct line_map *map;
92
  source_location start_location = set->highest_location + 1;
93
 
94
  if (set->used && start_location < set->maps[set->used - 1].start_location)
95
    abort ();
96
 
97
  if (set->used == set->allocated)
98
    {
99
      set->allocated = 2 * set->allocated + 256;
100
      set->maps = XRESIZEVEC (struct line_map, set->maps, set->allocated);
101
    }
102
 
103
  map = &set->maps[set->used];
104
 
105
  if (to_file && *to_file == '\0')
106
    to_file = "<stdin>";
107
 
108
  /* If we don't keep our line maps consistent, we can easily
109
     segfault.  Don't rely on the client to do it for us.  */
110
  if (set->depth == 0)
111
    reason = LC_ENTER;
112
  else if (reason == LC_LEAVE)
113
    {
114
      struct line_map *from;
115
      bool error;
116
 
117
      if (MAIN_FILE_P (map - 1))
118
        {
119
          if (to_file == NULL)
120
            {
121
              set->depth--;
122
              return NULL;
123
            }
124
          error = true;
125
          reason = LC_RENAME;
126
          from = map - 1;
127
        }
128
      else
129
        {
130
          from = INCLUDED_FROM (set, map - 1);
131
          error = to_file && strcmp (from->to_file, to_file);
132
        }
133
 
134
      /* Depending upon whether we are handling preprocessed input or
135
         not, this can be a user error or an ICE.  */
136
      if (error)
137
        fprintf (stderr, "line-map.c: file \"%s\" left but not entered\n",
138
                 to_file);
139
 
140
      /* A TO_FILE of NULL is special - we use the natural values.  */
141
      if (error || to_file == NULL)
142
        {
143
          to_file = from->to_file;
144
          to_line = SOURCE_LINE (from, from[1].start_location);
145
          sysp = from->sysp;
146
        }
147
    }
148
 
149
  map->reason = reason;
150
  map->sysp = sysp;
151
  map->start_location = start_location;
152
  map->to_file = to_file;
153
  map->to_line = to_line;
154
  set->cache = set->used++;
155
  map->column_bits = 0;
156
  set->highest_location = start_location;
157
  set->highest_line = start_location;
158
  set->max_column_hint = 0;
159
 
160
  if (reason == LC_ENTER)
161
    {
162
      map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
163
      set->depth++;
164
      if (set->trace_includes)
165
        trace_include (set, map);
166
    }
167
  else if (reason == LC_RENAME)
168
    map->included_from = map[-1].included_from;
169
  else if (reason == LC_LEAVE)
170
    {
171
      set->depth--;
172
      map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
173
    }
174
 
175
  return map;
176
}
177
 
178
source_location
179
linemap_line_start (struct line_maps *set, unsigned int to_line,
180
                    unsigned int max_column_hint)
181
{
182
  struct line_map *map = &set->maps[set->used - 1];
183
  source_location highest = set->highest_location;
184
  source_location r;
185
  unsigned int last_line = SOURCE_LINE (map, set->highest_line);
186
  int line_delta = to_line - last_line;
187
  bool add_map = false;
188
  if (line_delta < 0
189
      || (line_delta > 10 && line_delta * map->column_bits > 1000)
190
      || (max_column_hint >= (1U << map->column_bits))
191
      || (max_column_hint <= 80 && map->column_bits >= 10))
192
    {
193
      add_map = true;
194
    }
195
  else
196
    max_column_hint = set->max_column_hint;
197
  if (add_map)
198
    {
199
      int column_bits;
200
      if (max_column_hint > 100000 || highest > 0xC0000000)
201
        {
202
          /* If the column number is ridiculous or we've allocated a huge
203
             number of source_locations, give up on column numbers. */
204
          max_column_hint = 0;
205
          if (highest >0xF0000000)
206
            return 0;
207
          column_bits = 0;
208
        }
209
      else
210
        {
211
          column_bits = 7;
212
          while (max_column_hint >= (1U << column_bits))
213
            column_bits++;
214
          max_column_hint = 1U << column_bits;
215
        }
216
      /* Allocate the new line_map.  However, if the current map only has a
217
         single line we can sometimes just increase its column_bits instead. */
218
      if (line_delta < 0
219
          || last_line != map->to_line
220
          || SOURCE_COLUMN (map, highest) >= (1U << column_bits))
221
        map = (struct line_map*) linemap_add (set, LC_RENAME, map->sysp,
222
                                      map->to_file, to_line);
223
      map->column_bits = column_bits;
224
      r = map->start_location + ((to_line - map->to_line) << column_bits);
225
    }
226
  else
227
    r = highest - SOURCE_COLUMN (map, highest)
228
      + (line_delta << map->column_bits);
229
  set->highest_line = r;
230
  if (r > set->highest_location)
231
    set->highest_location = r;
232
  set->max_column_hint = max_column_hint;
233
  return r;
234
}
235
 
236
source_location
237
linemap_position_for_column (struct line_maps *set, unsigned int to_column)
238
{
239
  source_location r = set->highest_line;
240
  if (to_column >= set->max_column_hint)
241
    {
242
      if (r >= 0xC000000 || to_column > 100000)
243
        {
244
          /* Running low on source_locations - disable column numbers.  */
245
          return r;
246
        }
247
      else
248
        {
249
          struct line_map *map = &set->maps[set->used - 1];
250
          r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
251
        }
252
    }
253
  r = r + to_column;
254
  if (r >= set->highest_location)
255
    set->highest_location = r;
256
  return r;
257
}
258
 
259
/* Given a logical line, returns the map from which the corresponding
260
   (source file, line) pair can be deduced.  Since the set is built
261
   chronologically, the logical lines are monotonic increasing, and so
262
   the list is sorted and we can use a binary search.  */
263
 
264
const struct line_map *
265
linemap_lookup (struct line_maps *set, source_location line)
266
{
267
  unsigned int md, mn, mx;
268
  const struct line_map *cached;
269
 
270
  mn = set->cache;
271
  mx = set->used;
272
 
273
  cached = &set->maps[mn];
274
  /* We should get a segfault if no line_maps have been added yet.  */
275
  if (line >= cached->start_location)
276
    {
277
      if (mn + 1 == mx || line < cached[1].start_location)
278
        return cached;
279
    }
280
  else
281
    {
282
      mx = mn;
283
      mn = 0;
284
    }
285
 
286
  while (mx - mn > 1)
287
    {
288
      md = (mn + mx) / 2;
289
      if (set->maps[md].start_location > line)
290
        mx = md;
291
      else
292
        mn = md;
293
    }
294
 
295
  set->cache = mn;
296
  return &set->maps[mn];
297
}
298
 
299
/* Print the file names and line numbers of the #include commands
300
   which led to the map MAP, if any, to stderr.  Nothing is output if
301
   the most recently listed stack is the same as the current one.  */
302
 
303
void
304
linemap_print_containing_files (struct line_maps *set,
305
                                const struct line_map *map)
306
{
307
  if (MAIN_FILE_P (map) || set->last_listed == map->included_from)
308
    return;
309
 
310
  set->last_listed = map->included_from;
311
  map = INCLUDED_FROM (set, map);
312
 
313
  fprintf (stderr,  _("In file included from %s:%u"),
314
           map->to_file, LAST_SOURCE_LINE (map));
315
 
316
  while (! MAIN_FILE_P (map))
317
    {
318
      map = INCLUDED_FROM (set, map);
319
      /* Translators note: this message is used in conjunction
320
         with "In file included from %s:%ld" and some other
321
         tricks.  We want something like this:
322
 
323
         | In file included from sys/select.h:123,
324
         |                  from sys/types.h:234,
325
         |                  from userfile.c:31:
326
         | bits/select.h:45: <error message here>
327
 
328
         with all the "from"s lined up.
329
         The trailing comma is at the beginning of this message,
330
         and the trailing colon is not translated.  */
331
      fprintf (stderr, _(",\n                 from %s:%u"),
332
               map->to_file, LAST_SOURCE_LINE (map));
333
    }
334
 
335
  fputs (":\n", stderr);
336
}
337
 
338
/* Print an include trace, for e.g. the -H option of the preprocessor.  */
339
 
340
static void
341
trace_include (const struct line_maps *set, const struct line_map *map)
342
{
343
  unsigned int i = set->depth;
344
 
345
  while (--i)
346
    putc ('.', stderr);
347
  fprintf (stderr, " %s\n", map->to_file);
348
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.