* Makefile.tpl: Fix stupid pasto.
[official-gcc.git] / gcc / f / where.c
blobb16f965721e2f2a72b201763311680a6a90ebaf1
1 /* where.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 2002 Free Software Foundation, Inc.
3 Contributed by James Craig Burley.
5 This file is part of GNU Fortran.
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
22 Related Modules:
24 Description:
25 Simple data abstraction for Fortran source lines (called card images).
27 Modifications:
30 /* Include files. */
32 #include "proj.h"
33 #include "where.h"
34 #include "lex.h"
35 #include "malloc.h"
36 #include "ggc.h"
38 /* Externals defined here. */
40 struct _ffewhere_line_ ffewhere_unknown_line_
42 {NULL, NULL, 0, 0, 0, {0}};
44 /* Simple definitions and enumerations. */
47 /* Internal typedefs. */
49 typedef struct _ffewhere_ll_ *ffewhereLL_;
51 /* Private include files. */
54 /* Internal structure definitions. */
56 struct _ffewhere_ll_ GTY (())
58 ffewhereLL_ next;
59 ffewhereLL_ previous;
60 ffewhereFile wf;
61 ffewhereLineNumber line_no; /* ffelex_line_number() at time of creation. */
62 ffewhereLineNumber offset; /* User-desired offset (usually 1). */
65 struct _ffewhere_root_ll_ GTY (())
67 ffewhereLL_ first;
68 ffewhereLL_ last;
71 struct _ffewhere_root_line_
73 ffewhereLine first;
74 ffewhereLine last;
75 ffewhereLineNumber none;
78 /* Static objects accessed by functions in this module. */
80 static GTY (()) struct _ffewhere_root_ll_ *ffewhere_root_ll_;
81 static struct _ffewhere_root_line_ ffewhere_root_line_;
83 /* Static functions (internal). */
85 static ffewhereLL_ ffewhere_ll_lookup_ (ffewhereLineNumber ln);
87 /* Internal macros. */
90 /* Look up line-to-line object from absolute line num. */
92 static ffewhereLL_
93 ffewhere_ll_lookup_ (ffewhereLineNumber ln)
95 ffewhereLL_ ll;
97 if (ln == 0)
98 return ffewhere_root_ll_->first;
100 for (ll = ffewhere_root_ll_->last;
101 ll != (ffewhereLL_) &ffewhere_root_ll_->first;
102 ll = ll->previous)
104 if (ll->line_no <= ln)
105 return ll;
108 assert ("no line num" == NULL);
109 return NULL;
112 /* Create file object. */
114 ffewhereFile
115 ffewhere_file_new (const char *name, size_t length)
117 ffewhereFile wf;
118 wf = ggc_alloc (offsetof (struct _ffewhere_file_, text) + length + 1);
119 wf->length = length;
120 memcpy (&wf->text[0], name, length);
121 wf->text[length] = '\0';
123 return wf;
126 /* Set file and first line number.
128 Pass FALSE if no line number is specified. */
130 void
131 ffewhere_file_set (ffewhereFile wf, bool have_num, ffewhereLineNumber ln)
133 ffewhereLL_ ll;
134 ll = ggc_alloc (sizeof (*ll));
135 ll->next = (ffewhereLL_) &ffewhere_root_ll_->first;
136 ll->previous = ffewhere_root_ll_->last;
137 ll->next->previous = ll;
138 ll->previous->next = ll;
139 if (wf == NULL)
141 if (ll->previous == ll->next)
142 ll->wf = NULL;
143 else
144 ll->wf = ll->previous->wf;
146 else
147 ll->wf = wf;
148 ll->line_no = ffelex_line_number ();
149 if (have_num)
150 ll->offset = ln;
151 else
153 if (ll->previous == ll->next)
154 ll->offset = 1;
155 else
156 ll->offset
157 = ll->line_no - ll->previous->line_no + ll->previous->offset;
161 /* Do initializations. */
163 void
164 ffewhere_init_1 ()
166 ffewhere_root_line_.first = ffewhere_root_line_.last
167 = (ffewhereLine) &ffewhere_root_line_.first;
168 ffewhere_root_line_.none = 0;
170 /* The sentinel is (must be) GGC-allocated. It is accessed as a
171 struct _ffewhere_ll_/ffewhereLL_ though its type contains just the
172 first two fields (layout-wise). */
173 ffewhere_root_ll_ = ggc_alloc_cleared (sizeof (struct _ffewhere_ll_));
174 ffewhere_root_ll_->first = ffewhere_root_ll_->last
175 = (ffewhereLL_) &ffewhere_root_ll_->first;
178 /* Return the textual content of the line. */
180 char *
181 ffewhere_line_content (ffewhereLine wl)
183 assert (wl != NULL);
184 return wl->content;
187 /* Look up file object from line object. */
189 ffewhereFile
190 ffewhere_line_file (ffewhereLine wl)
192 ffewhereLL_ ll;
194 assert (wl != NULL);
195 ll = ffewhere_ll_lookup_ (wl->line_num);
196 return ll->wf;
199 /* Lookup file object from line object, calc line#. */
201 ffewhereLineNumber
202 ffewhere_line_filelinenum (ffewhereLine wl)
204 ffewhereLL_ ll;
206 assert (wl != NULL);
207 ll = ffewhere_ll_lookup_ (wl->line_num);
208 return wl->line_num + ll->offset - ll->line_no;
211 /* Decrement use count for line, deallocate if no uses left. */
213 void
214 ffewhere_line_kill (ffewhereLine wl)
216 #if 0
217 if (!ffewhere_line_is_unknown (wl))
218 fprintf (dmpout, "; ffewhere_line_kill %" ffewhereLineNumber_f "u, uses=%"
219 ffewhereUses_f_ "u\n",
220 wl->line_num, wl->uses);
221 #endif
222 assert (ffewhere_line_is_unknown (wl) || (wl->uses != 0));
223 if (!ffewhere_line_is_unknown (wl) && (--wl->uses == 0))
225 wl->previous->next = wl->next;
226 wl->next->previous = wl->previous;
227 malloc_kill_ks (ffe_pool_file (), wl,
228 offsetof (struct _ffewhere_line_, content)
229 + wl->length + 1);
233 /* Make a new line or increment use count of existing one.
235 Find out where line object is, if anywhere. If in lexer, it might also
236 be at the end of the list of lines, else put it on the end of the list.
237 Then, if in the list of lines, increment the use count and return the
238 line object. Else, make an empty line object (no line) and return
239 that. */
241 ffewhereLine
242 ffewhere_line_new (ffewhereLineNumber ln)
244 ffewhereLine wl = ffewhere_root_line_.last;
246 /* If this is the lexer's current line, see if it is already at the end of
247 the list, and if not, make it and return it. */
249 if (((ln == 0) /* Presumably asking for EOF pointer. */
250 || (wl->line_num != ln))
251 && (ffelex_line_number () == ln))
253 #if 0
254 fprintf (dmpout,
255 "; ffewhere_line_new %" ffewhereLineNumber_f "u, lexer\n",
256 ln);
257 #endif
258 wl = malloc_new_ks (ffe_pool_file (), "FFEWHERE line",
259 offsetof (struct _ffewhere_line_, content)
260 + (size_t) ffelex_line_length () + 1);
261 wl->next = (ffewhereLine) &ffewhere_root_line_;
262 wl->previous = ffewhere_root_line_.last;
263 wl->previous->next = wl;
264 wl->next->previous = wl;
265 wl->line_num = ln;
266 wl->uses = 1;
267 wl->length = ffelex_line_length ();
268 strcpy (wl->content, ffelex_line ());
269 return wl;
272 /* See if line is on list already. */
274 while (wl->line_num > ln)
275 wl = wl->previous;
277 /* If line is there, increment its use count and return. */
279 if (wl->line_num == ln)
281 #if 0
282 fprintf (dmpout, "; ffewhere_line_new %" ffewhereLineNumber_f "u, uses=%"
283 ffewhereUses_f_ "u\n", ln,
284 wl->uses);
285 #endif
286 wl->uses++;
287 return wl;
290 /* Else, make a new one with a blank line (since we've obviously lost it,
291 which should never happen) and return it. */
293 fprintf (stderr,
294 "(Cannot resurrect line %lu for error reporting purposes.)\n",
295 ln);
297 wl = malloc_new_ks (ffe_pool_file (), "FFEWHERE line",
298 offsetof (struct _ffewhere_line_, content)
299 + 1);
300 wl->next = (ffewhereLine) &ffewhere_root_line_;
301 wl->previous = ffewhere_root_line_.last;
302 wl->previous->next = wl;
303 wl->next->previous = wl;
304 wl->line_num = ln;
305 wl->uses = 1;
306 wl->length = 0;
307 *(wl->content) = '\0';
308 return wl;
311 /* Increment use count of line, as in a copy. */
313 ffewhereLine
314 ffewhere_line_use (ffewhereLine wl)
316 #if 0
317 fprintf (dmpout, "; ffewhere_line_use %" ffewhereLineNumber_f "u, uses=%" ffewhereUses_f_
318 "u\n", wl->line_num, wl->uses);
319 #endif
320 assert (ffewhere_line_is_unknown (wl) || (wl->uses != 0));
321 if (!ffewhere_line_is_unknown (wl))
322 ++wl->uses;
323 return wl;
326 /* Set an ffewhere object based on a track index.
328 Determines the absolute line and column number of a character at a given
329 index into an ffewhereTrack array. wr* is the reference position, wt is
330 the tracking information, and i is the index desired. wo* is set to wr*
331 plus the continual offsets described by wt[0...i-1], or unknown if any of
332 the continual offsets are not known. */
334 void
335 ffewhere_set_from_track (ffewhereLine *wol, ffewhereColumn *woc,
336 ffewhereLine wrl, ffewhereColumn wrc,
337 ffewhereTrack wt, ffewhereIndex i)
339 ffewhereLineNumber ln;
340 ffewhereColumnNumber cn;
341 ffewhereIndex j;
342 ffewhereIndex k;
344 if ((i == 0) || (i >= FFEWHERE_indexMAX))
346 *wol = ffewhere_line_use (wrl);
347 *woc = ffewhere_column_use (wrc);
349 else
351 ln = ffewhere_line_number (wrl);
352 cn = ffewhere_column_number (wrc);
353 for (j = 0, k = 0; j < i; ++j, k += 2)
355 if ((wt[k] == FFEWHERE_indexUNKNOWN)
356 || (wt[k + 1] == FFEWHERE_indexUNKNOWN))
358 *wol = ffewhere_line_unknown ();
359 *woc = ffewhere_column_unknown ();
360 return;
362 if (wt[k] == 0)
363 cn += wt[k + 1] + 1;
364 else
366 ln += wt[k];
367 cn = wt[k + 1] + 1;
370 if (ln == ffewhere_line_number (wrl))
371 { /* Already have the line object, just use it
372 directly. */
373 *wol = ffewhere_line_use (wrl);
375 else /* Must search for the line object. */
376 *wol = ffewhere_line_new (ln);
377 *woc = ffewhere_column_new (cn);
381 /* Build next tracking index.
383 Set wt[i-1] continual offset so that it offsets from w* to (ln,cn). Update
384 w* to contain (ln,cn). DO NOT call this routine if i >= FFEWHERE_indexMAX
385 or i == 0. */
387 void
388 ffewhere_track (ffewhereLine *wl, ffewhereColumn *wc, ffewhereTrack wt,
389 ffewhereIndex i, ffewhereLineNumber ln,
390 ffewhereColumnNumber cn)
392 unsigned int lo;
393 unsigned int co;
395 if ((ffewhere_line_is_unknown (*wl))
396 || (ffewhere_column_is_unknown (*wc))
397 || ((lo = ln - ffewhere_line_number (*wl)) >= FFEWHERE_indexUNKNOWN))
399 wt[i * 2 - 2] = wt[i * 2 - 1] = FFEWHERE_indexUNKNOWN;
400 ffewhere_line_kill (*wl);
401 ffewhere_column_kill (*wc);
402 *wl = FFEWHERE_lineUNKNOWN;
403 *wc = FFEWHERE_columnUNKNOWN;
405 else if (lo == 0)
407 wt[i * 2 - 2] = 0;
408 if ((co = cn - ffewhere_column_number (*wc)) > FFEWHERE_indexUNKNOWN)
410 wt[i * 2 - 1] = FFEWHERE_indexUNKNOWN;
411 ffewhere_line_kill (*wl);
412 ffewhere_column_kill (*wc);
413 *wl = FFEWHERE_lineUNKNOWN;
414 *wc = FFEWHERE_columnUNKNOWN;
416 else
418 wt[i * 2 - 1] = co - 1;
419 ffewhere_column_kill (*wc);
420 *wc = ffewhere_column_use (ffewhere_column_new (cn));
423 else
425 wt[i * 2 - 2] = lo;
426 wt[i * 2 - 1] = cn - 1;
427 ffewhere_line_kill (*wl);
428 ffewhere_column_kill (*wc);
429 *wl = ffewhere_line_use (ffewhere_line_new (ln));
430 *wc = ffewhere_column_use (ffewhere_column_new (cn));
434 /* Clear tracking index for internally created track.
436 Set the tracking information to indicate that the tracking is at its
437 simplest (no spaces or newlines within the tracking). This means set
438 everything to zero in the current implementation. Length is the total
439 length of the token; length must be 2 or greater, since length-1 tracking
440 characters are set. */
442 void
443 ffewhere_track_clear (ffewhereTrack wt, ffewhereIndex length)
445 ffewhereIndex i;
447 if (length > FFEWHERE_indexMAX)
448 length = FFEWHERE_indexMAX;
450 for (i = 1; i < length; ++i)
451 wt[i * 2 - 2] = wt[i * 2 - 1] = 0;
454 /* Copy tracking index from one place to another.
456 Copy tracking information from swt[start] to dwt[0] and so on, presumably
457 after an ffewhere_set_from_track call. Length is the total
458 length of the token; length must be 2 or greater, since length-1 tracking
459 characters are set. */
461 void
462 ffewhere_track_copy (ffewhereTrack dwt, ffewhereTrack swt, ffewhereIndex start,
463 ffewhereIndex length)
465 ffewhereIndex i;
466 ffewhereIndex copy;
468 if (length > FFEWHERE_indexMAX)
469 length = FFEWHERE_indexMAX;
471 if (length + start > FFEWHERE_indexMAX)
472 copy = FFEWHERE_indexMAX - start;
473 else
474 copy = length;
476 for (i = 1; i < copy; ++i)
478 dwt[i * 2 - 2] = swt[(i + start) * 2 - 2];
479 dwt[i * 2 - 1] = swt[(i + start) * 2 - 1];
482 for (; i < length; ++i)
484 dwt[i * 2 - 2] = 0;
485 dwt[i * 2 - 1] = 0;
489 /* Kill tracking data.
491 Kill all the tracking information by killing incremented lines from the
492 first line number. */
494 void
495 ffewhere_track_kill (ffewhereLine wrl, ffewhereColumn wrc UNUSED,
496 ffewhereTrack wt, ffewhereIndex length)
498 ffewhereLineNumber ln;
499 unsigned int lo;
500 ffewhereIndex i;
502 ln = ffewhere_line_number (wrl);
504 if (length > FFEWHERE_indexMAX)
505 length = FFEWHERE_indexMAX;
507 for (i = 0; i < length - 1; ++i)
509 if ((lo = wt[i * 2]) == FFEWHERE_indexUNKNOWN)
510 break;
511 else if (lo != 0)
513 ln += lo;
514 wrl = ffewhere_line_new (ln);
515 ffewhere_line_kill (wrl);
520 #include "gt-f-where.h"