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)
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
25 Simple data abstraction for Fortran source lines (called card images).
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 (())
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 (())
71 struct _ffewhere_root_line_
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. */
93 ffewhere_ll_lookup_ (ffewhereLineNumber ln
)
98 return ffewhere_root_ll_
->first
;
100 for (ll
= ffewhere_root_ll_
->last
;
101 ll
!= (ffewhereLL_
) &ffewhere_root_ll_
->first
;
104 if (ll
->line_no
<= ln
)
108 assert ("no line num" == NULL
);
112 /* Create file object. */
115 ffewhere_file_new (const char *name
, size_t length
)
118 wf
= ggc_alloc (offsetof (struct _ffewhere_file_
, text
) + length
+ 1);
120 memcpy (&wf
->text
[0], name
, length
);
121 wf
->text
[length
] = '\0';
126 /* Set file and first line number.
128 Pass FALSE if no line number is specified. */
131 ffewhere_file_set (ffewhereFile wf
, bool have_num
, ffewhereLineNumber ln
)
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
;
141 if (ll
->previous
== ll
->next
)
144 ll
->wf
= ll
->previous
->wf
;
148 ll
->line_no
= ffelex_line_number ();
153 if (ll
->previous
== ll
->next
)
157 = ll
->line_no
- ll
->previous
->line_no
+ ll
->previous
->offset
;
161 /* Do initializations. */
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. */
181 ffewhere_line_content (ffewhereLine wl
)
187 /* Look up file object from line object. */
190 ffewhere_line_file (ffewhereLine wl
)
195 ll
= ffewhere_ll_lookup_ (wl
->line_num
);
199 /* Lookup file object from line object, calc line#. */
202 ffewhere_line_filelinenum (ffewhereLine wl
)
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. */
214 ffewhere_line_kill (ffewhereLine wl
)
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
);
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
)
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
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
))
255 "; ffewhere_line_new %" ffewhereLineNumber_f
"u, lexer\n",
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
;
267 wl
->length
= ffelex_line_length ();
268 strcpy (wl
->content
, ffelex_line ());
272 /* See if line is on list already. */
274 while (wl
->line_num
> ln
)
277 /* If line is there, increment its use count and return. */
279 if (wl
->line_num
== ln
)
282 fprintf (dmpout
, "; ffewhere_line_new %" ffewhereLineNumber_f
"u, uses=%"
283 ffewhereUses_f_
"u\n", ln
,
290 /* Else, make a new one with a blank line (since we've obviously lost it,
291 which should never happen) and return it. */
294 "(Cannot resurrect line %lu for error reporting purposes.)\n",
297 wl
= malloc_new_ks (ffe_pool_file (), "FFEWHERE line",
298 offsetof (struct _ffewhere_line_
, content
)
300 wl
->next
= (ffewhereLine
) &ffewhere_root_line_
;
301 wl
->previous
= ffewhere_root_line_
.last
;
302 wl
->previous
->next
= wl
;
303 wl
->next
->previous
= wl
;
307 *(wl
->content
) = '\0';
311 /* Increment use count of line, as in a copy. */
314 ffewhere_line_use (ffewhereLine wl
)
317 fprintf (dmpout
, "; ffewhere_line_use %" ffewhereLineNumber_f
"u, uses=%" ffewhereUses_f_
318 "u\n", wl
->line_num
, wl
->uses
);
320 assert (ffewhere_line_is_unknown (wl
) || (wl
->uses
!= 0));
321 if (!ffewhere_line_is_unknown (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. */
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
;
344 if ((i
== 0) || (i
>= FFEWHERE_indexMAX
))
346 *wol
= ffewhere_line_use (wrl
);
347 *woc
= ffewhere_column_use (wrc
);
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 ();
370 if (ln
== ffewhere_line_number (wrl
))
371 { /* Already have the line object, just use it
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
388 ffewhere_track (ffewhereLine
*wl
, ffewhereColumn
*wc
, ffewhereTrack wt
,
389 ffewhereIndex i
, ffewhereLineNumber ln
,
390 ffewhereColumnNumber cn
)
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
;
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
;
418 wt
[i
* 2 - 1] = co
- 1;
419 ffewhere_column_kill (*wc
);
420 *wc
= ffewhere_column_use (ffewhere_column_new (cn
));
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. */
443 ffewhere_track_clear (ffewhereTrack wt
, ffewhereIndex length
)
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. */
462 ffewhere_track_copy (ffewhereTrack dwt
, ffewhereTrack swt
, ffewhereIndex start
,
463 ffewhereIndex length
)
468 if (length
> FFEWHERE_indexMAX
)
469 length
= FFEWHERE_indexMAX
;
471 if (length
+ start
> FFEWHERE_indexMAX
)
472 copy
= FFEWHERE_indexMAX
- start
;
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
)
489 /* Kill tracking data.
491 Kill all the tracking information by killing incremented lines from the
492 first line number. */
495 ffewhere_track_kill (ffewhereLine wrl
, ffewhereColumn wrc UNUSED
,
496 ffewhereTrack wt
, ffewhereIndex length
)
498 ffewhereLineNumber ln
;
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
)
514 wrl
= ffewhere_line_new (ln
);
515 ffewhere_line_kill (wrl
);
520 #include "gt-f-where.h"