]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/f/where.c
re PR fortran/13930 (derived type with intent(in) attribute not accepted)
[thirdparty/gcc.git] / gcc / f / where.c
CommitLineData
5ff904cd 1/* where.c -- Implementation File (module.c template V1.0)
77f9b92c 2 Copyright (C) 1995, 2002, 2003 Free Software Foundation, Inc.
25d7717e 3 Contributed by James Craig Burley.
5ff904cd
JL
4
5This file is part of GNU Fortran.
6
7GNU Fortran is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Fortran is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Fortran; see the file COPYING. If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2002111-1307, USA.
21
22 Related Modules:
23
24 Description:
25 Simple data abstraction for Fortran source lines (called card images).
26
27 Modifications:
28*/
29
30/* Include files. */
31
32#include "proj.h"
33#include "where.h"
34#include "lex.h"
35#include "malloc.h"
d7704f76 36#include "ggc.h"
5ff904cd
JL
37
38/* Externals defined here. */
39
40struct _ffewhere_line_ ffewhere_unknown_line_
41=
0816ebdd 42{NULL, NULL, 0, 0, 0, {0}};
5ff904cd
JL
43
44/* Simple definitions and enumerations. */
45
46
47/* Internal typedefs. */
48
49typedef struct _ffewhere_ll_ *ffewhereLL_;
50
51/* Private include files. */
52
53
54/* Internal structure definitions. */
55
d7704f76 56struct _ffewhere_ll_ GTY (())
5ff904cd
JL
57 {
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). */
63 };
64
d7704f76 65struct _ffewhere_root_ll_ GTY (())
5ff904cd
JL
66 {
67 ffewhereLL_ first;
68 ffewhereLL_ last;
69 };
70
71struct _ffewhere_root_line_
72 {
73 ffewhereLine first;
74 ffewhereLine last;
75 ffewhereLineNumber none;
76 };
77
78/* Static objects accessed by functions in this module. */
79
d7704f76 80static GTY (()) struct _ffewhere_root_ll_ *ffewhere_root_ll_;
5ff904cd
JL
81static struct _ffewhere_root_line_ ffewhere_root_line_;
82
83/* Static functions (internal). */
84
85static ffewhereLL_ ffewhere_ll_lookup_ (ffewhereLineNumber ln);
86
87/* Internal macros. */
88\f
89
90/* Look up line-to-line object from absolute line num. */
91
92static ffewhereLL_
93ffewhere_ll_lookup_ (ffewhereLineNumber ln)
94{
95 ffewhereLL_ ll;
96
97 if (ln == 0)
d7704f76 98 return ffewhere_root_ll_->first;
5ff904cd 99
d7704f76
HPN
100 for (ll = ffewhere_root_ll_->last;
101 ll != (ffewhereLL_) &ffewhere_root_ll_->first;
5ff904cd
JL
102 ll = ll->previous)
103 {
104 if (ll->line_no <= ln)
105 return ll;
106 }
107
108 assert ("no line num" == NULL);
109 return NULL;
110}
111
5ff904cd
JL
112/* Create file object. */
113
114ffewhereFile
3b304f5b 115ffewhere_file_new (const char *name, size_t length)
5ff904cd
JL
116{
117 ffewhereFile wf;
d7704f76 118 wf = ggc_alloc (offsetof (struct _ffewhere_file_, text) + length + 1);
5ff904cd
JL
119 wf->length = length;
120 memcpy (&wf->text[0], name, length);
121 wf->text[length] = '\0';
122
123 return wf;
124}
125
126/* Set file and first line number.
127
128 Pass FALSE if no line number is specified. */
129
130void
131ffewhere_file_set (ffewhereFile wf, bool have_num, ffewhereLineNumber ln)
132{
133 ffewhereLL_ ll;
d7704f76
HPN
134 ll = ggc_alloc (sizeof (*ll));
135 ll->next = (ffewhereLL_) &ffewhere_root_ll_->first;
136 ll->previous = ffewhere_root_ll_->last;
5ff904cd
JL
137 ll->next->previous = ll;
138 ll->previous->next = ll;
139 if (wf == NULL)
140 {
141 if (ll->previous == ll->next)
142 ll->wf = NULL;
143 else
144 ll->wf = ll->previous->wf;
145 }
146 else
147 ll->wf = wf;
148 ll->line_no = ffelex_line_number ();
149 if (have_num)
150 ll->offset = ln;
151 else
152 {
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;
158 }
159}
160
161/* Do initializations. */
162
163void
77f9b92c 164ffewhere_init_1 (void)
5ff904cd
JL
165{
166 ffewhere_root_line_.first = ffewhere_root_line_.last
167 = (ffewhereLine) &ffewhere_root_line_.first;
168 ffewhere_root_line_.none = 0;
169
d7704f76
HPN
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;
5ff904cd
JL
176}
177
178/* Return the textual content of the line. */
179
180char *
181ffewhere_line_content (ffewhereLine wl)
182{
183 assert (wl != NULL);
184 return wl->content;
185}
186
187/* Look up file object from line object. */
188
189ffewhereFile
190ffewhere_line_file (ffewhereLine wl)
191{
192 ffewhereLL_ ll;
193
194 assert (wl != NULL);
195 ll = ffewhere_ll_lookup_ (wl->line_num);
196 return ll->wf;
197}
198
199/* Lookup file object from line object, calc line#. */
200
201ffewhereLineNumber
202ffewhere_line_filelinenum (ffewhereLine wl)
203{
204 ffewhereLL_ ll;
205
206 assert (wl != NULL);
207 ll = ffewhere_ll_lookup_ (wl->line_num);
208 return wl->line_num + ll->offset - ll->line_no;
209}
210
211/* Decrement use count for line, deallocate if no uses left. */
212
213void
214ffewhere_line_kill (ffewhereLine wl)
215{
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))
224 {
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);
230 }
231}
232
233/* Make a new line or increment use count of existing one.
234
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. */
240
241ffewhereLine
242ffewhere_line_new (ffewhereLineNumber ln)
243{
244 ffewhereLine wl = ffewhere_root_line_.last;
245
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. */
248
249 if (((ln == 0) /* Presumably asking for EOF pointer. */
250 || (wl->line_num != ln))
251 && (ffelex_line_number () == ln))
252 {
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;
270 }
271
272 /* See if line is on list already. */
273
274 while (wl->line_num > ln)
275 wl = wl->previous;
276
277 /* If line is there, increment its use count and return. */
278
279 if (wl->line_num == ln)
280 {
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;
288 }
289
290 /* Else, make a new one with a blank line (since we've obviously lost it,
291 which should never happen) and return it. */
292
293 fprintf (stderr,
294 "(Cannot resurrect line %lu for error reporting purposes.)\n",
295 ln);
296
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;
309}
310
311/* Increment use count of line, as in a copy. */
312
313ffewhereLine
314ffewhere_line_use (ffewhereLine wl)
315{
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;
324}
325
326/* Set an ffewhere object based on a track index.
327
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. */
333
334void
335ffewhere_set_from_track (ffewhereLine *wol, ffewhereColumn *woc,
336 ffewhereLine wrl, ffewhereColumn wrc,
337 ffewhereTrack wt, ffewhereIndex i)
338{
339 ffewhereLineNumber ln;
340 ffewhereColumnNumber cn;
341 ffewhereIndex j;
342 ffewhereIndex k;
343
344 if ((i == 0) || (i >= FFEWHERE_indexMAX))
345 {
346 *wol = ffewhere_line_use (wrl);
347 *woc = ffewhere_column_use (wrc);
348 }
349 else
350 {
351 ln = ffewhere_line_number (wrl);
352 cn = ffewhere_column_number (wrc);
353 for (j = 0, k = 0; j < i; ++j, k += 2)
354 {
355 if ((wt[k] == FFEWHERE_indexUNKNOWN)
356 || (wt[k + 1] == FFEWHERE_indexUNKNOWN))
357 {
358 *wol = ffewhere_line_unknown ();
359 *woc = ffewhere_column_unknown ();
360 return;
361 }
362 if (wt[k] == 0)
363 cn += wt[k + 1] + 1;
364 else
365 {
366 ln += wt[k];
367 cn = wt[k + 1] + 1;
368 }
369 }
370 if (ln == ffewhere_line_number (wrl))
371 { /* Already have the line object, just use it
372 directly. */
373 *wol = ffewhere_line_use (wrl);
374 }
375 else /* Must search for the line object. */
376 *wol = ffewhere_line_new (ln);
377 *woc = ffewhere_column_new (cn);
378 }
379}
380
381/* Build next tracking index.
382
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. */
386
387void
388ffewhere_track (ffewhereLine *wl, ffewhereColumn *wc, ffewhereTrack wt,
389 ffewhereIndex i, ffewhereLineNumber ln,
390 ffewhereColumnNumber cn)
391{
392 unsigned int lo;
393 unsigned int co;
394
395 if ((ffewhere_line_is_unknown (*wl))
396 || (ffewhere_column_is_unknown (*wc))
397 || ((lo = ln - ffewhere_line_number (*wl)) >= FFEWHERE_indexUNKNOWN))
398 {
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;
404 }
405 else if (lo == 0)
406 {
407 wt[i * 2 - 2] = 0;
408 if ((co = cn - ffewhere_column_number (*wc)) > FFEWHERE_indexUNKNOWN)
409 {
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;
415 }
416 else
417 {
418 wt[i * 2 - 1] = co - 1;
419 ffewhere_column_kill (*wc);
420 *wc = ffewhere_column_use (ffewhere_column_new (cn));
421 }
422 }
423 else
424 {
425 wt[i * 2 - 2] = lo;
fe932535
KG
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));
5ff904cd
JL
431 }
432}
433
434/* Clear tracking index for internally created track.
435
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. */
441
442void
443ffewhere_track_clear (ffewhereTrack wt, ffewhereIndex length)
444{
445 ffewhereIndex i;
446
447 if (length > FFEWHERE_indexMAX)
448 length = FFEWHERE_indexMAX;
449
450 for (i = 1; i < length; ++i)
451 wt[i * 2 - 2] = wt[i * 2 - 1] = 0;
452}
453
454/* Copy tracking index from one place to another.
455
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. */
460
461void
462ffewhere_track_copy (ffewhereTrack dwt, ffewhereTrack swt, ffewhereIndex start,
463 ffewhereIndex length)
464{
465 ffewhereIndex i;
466 ffewhereIndex copy;
467
468 if (length > FFEWHERE_indexMAX)
469 length = FFEWHERE_indexMAX;
470
471 if (length + start > FFEWHERE_indexMAX)
472 copy = FFEWHERE_indexMAX - start;
473 else
474 copy = length;
475
476 for (i = 1; i < copy; ++i)
477 {
478 dwt[i * 2 - 2] = swt[(i + start) * 2 - 2];
479 dwt[i * 2 - 1] = swt[(i + start) * 2 - 1];
480 }
481
482 for (; i < length; ++i)
483 {
484 dwt[i * 2 - 2] = 0;
485 dwt[i * 2 - 1] = 0;
486 }
487}
488
489/* Kill tracking data.
490
491 Kill all the tracking information by killing incremented lines from the
492 first line number. */
493
494void
495ffewhere_track_kill (ffewhereLine wrl, ffewhereColumn wrc UNUSED,
496 ffewhereTrack wt, ffewhereIndex length)
497{
498 ffewhereLineNumber ln;
499 unsigned int lo;
500 ffewhereIndex i;
501
502 ln = ffewhere_line_number (wrl);
503
504 if (length > FFEWHERE_indexMAX)
505 length = FFEWHERE_indexMAX;
506
507 for (i = 0; i < length - 1; ++i)
508 {
509 if ((lo = wt[i * 2]) == FFEWHERE_indexUNKNOWN)
510 break;
511 else if (lo != 0)
512 {
513 ln += lo;
514 wrl = ffewhere_line_new (ln);
515 ffewhere_line_kill (wrl);
516 }
517 }
518}
d7704f76
HPN
519
520#include "gt-f-where.h"