* gcc.c (option_map): Remove --version.
[official-gcc.git] / gcc / f / symbol.c
blob816ad1964bbcf1c13681e6eb0b8c7f9a379cf830
1 /* Implementation of Fortran symbol manager
2 Copyright (C) 1995, 1996, 1997 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 #include "proj.h"
23 #include "symbol.h"
24 #include "bad.h"
25 #include "bld.h"
26 #include "com.h"
27 #include "equiv.h"
28 #include "global.h"
29 #include "info.h"
30 #include "intrin.h"
31 #include "lex.h"
32 #include "malloc.h"
33 #include "src.h"
34 #include "st.h"
35 #include "storag.h"
36 #include "target.h"
37 #include "where.h"
39 /* Choice of how to handle global symbols -- either global only within the
40 program unit being defined or global within the entire source file.
41 The former is appropriate for systems where an object file can
42 easily be taken apart program unit by program unit, the latter is the
43 UNIX/C model where the object file is essentially a monolith. */
45 #define FFESYMBOL_globalPROGUNIT_ 1
46 #define FFESYMBOL_globalFILE_ 2
48 /* Choose how to handle global symbols here. */
50 /* Would be good to understand why PROGUNIT in this case too.
51 (1995-08-22). */
52 #define FFESYMBOL_globalCURRENT_ FFESYMBOL_globalPROGUNIT_
54 /* Choose how to handle memory pools based on global symbol stuff. */
56 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalPROGUNIT_
57 #define FFESYMBOL_SPACE_POOL_ ffe_pool_program_unit()
58 #elif FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalFILE_
59 #define FFESYMBOL_SPACE_POOL_ ffe_pool_file()
60 #else
61 #error
62 #endif
64 /* What kind of retraction is needed for a symbol? */
66 enum _ffesymbol_retractcommand_
68 FFESYMBOL_retractcommandDELETE_,
69 FFESYMBOL_retractcommandRETRACT_,
70 FFESYMBOL_retractcommand_
72 typedef enum _ffesymbol_retractcommand_ ffesymbolRetractCommand_;
74 /* This object keeps track of retraction for a symbol and links to the next
75 such object. */
77 typedef struct _ffesymbol_retract_ *ffesymbolRetract_;
78 struct _ffesymbol_retract_
80 ffesymbolRetract_ next;
81 ffesymbolRetractCommand_ command;
82 ffesymbol live; /* Live symbol. */
83 ffesymbol symbol; /* Backup copy of symbol. */
86 static ffebad ffesymbol_check_token_ (ffelexToken t, char *c);
87 static void ffesymbol_kill_manifest_ (void);
88 static ffesymbol ffesymbol_new_ (ffename n);
89 static ffesymbol ffesymbol_unhook_ (ffesymbol s);
90 static void ffesymbol_whine_state_ (ffebad bad, ffelexToken t, char c);
92 /* Manifest names for unnamed things (as tokens) so we make them only
93 once. */
95 static ffelexToken ffesymbol_token_blank_common_ = NULL;
96 static ffelexToken ffesymbol_token_unnamed_main_ = NULL;
97 static ffelexToken ffesymbol_token_unnamed_blockdata_ = NULL;
99 /* Name spaces currently in force. */
101 static ffenameSpace ffesymbol_global_ = NULL;
102 static ffenameSpace ffesymbol_local_ = NULL;
103 static ffenameSpace ffesymbol_sfunc_ = NULL;
105 /* Keep track of retraction. */
107 static bool ffesymbol_retractable_ = FALSE;
108 static mallocPool ffesymbol_retract_pool_;
109 static ffesymbolRetract_ ffesymbol_retract_first_;
110 static ffesymbolRetract_ *ffesymbol_retract_list_;
112 /* List of state names. */
114 static const char *const ffesymbol_state_name_[] =
116 "?",
117 "@",
118 "&",
119 "$",
122 /* List of attribute names. */
124 static const char *const ffesymbol_attr_name_[] =
126 #define DEFATTR(ATTR,ATTRS,NAME) NAME,
127 #include "symbol.def"
128 #undef DEFATTR
132 /* Check whether the token text has any invalid characters. If not,
133 return FALSE. If so, if error messages inhibited, return TRUE
134 so caller knows to try again later, else report error and return
135 FALSE. */
137 static ffebad
138 ffesymbol_check_token_ (ffelexToken t, char *c)
140 char *p = ffelex_token_text (t);
141 ffeTokenLength len = ffelex_token_length (t);
142 ffebad bad;
143 ffeTokenLength i = 0;
144 ffebad skip_me = ((ffe_case_symbol () == FFE_caseINITCAP)
145 ? FFEBAD_SYMBOL_NOLOWER_INITCAP : FFEBAD + 1);
146 ffebad stop_me = ((ffe_case_symbol () == FFE_caseINITCAP)
147 ? FFEBAD : FFEBAD + 1);
148 if (len == 0)
149 return FFEBAD;
151 bad = ffesrc_bad_char_symbol_init (*p);
152 if (bad == FFEBAD)
154 for (++i, ++p; i < len; ++i, ++p)
156 bad = ffesrc_bad_char_symbol_noninit (*p);
157 if (bad == skip_me)
158 continue; /* Keep looking for good InitCap character. */
159 if (bad == stop_me)
160 break; /* Found good InitCap character. */
161 if (bad != FFEBAD)
162 break; /* Bad character found. */
166 if (bad != FFEBAD)
168 if (i >= len)
169 *c = *(ffelex_token_text (t));
170 else
171 *c = *p;
174 return bad;
177 /* Kill manifest (g77-picked) names. */
179 static void
180 ffesymbol_kill_manifest_ ()
182 if (ffesymbol_token_blank_common_ != NULL)
183 ffelex_token_kill (ffesymbol_token_blank_common_);
184 if (ffesymbol_token_unnamed_main_ != NULL)
185 ffelex_token_kill (ffesymbol_token_unnamed_main_);
186 if (ffesymbol_token_unnamed_blockdata_ != NULL)
187 ffelex_token_kill (ffesymbol_token_unnamed_blockdata_);
189 ffesymbol_token_blank_common_ = NULL;
190 ffesymbol_token_unnamed_main_ = NULL;
191 ffesymbol_token_unnamed_blockdata_ = NULL;
194 /* Make new symbol.
196 If the "retractable" flag is not set, just return the new symbol.
197 Else, add symbol to the "retract" list as a delete item, set
198 the "have_old" flag, and return the new symbol. */
200 static ffesymbol
201 ffesymbol_new_ (ffename n)
203 ffesymbol s;
204 ffesymbolRetract_ r;
206 assert (n != NULL);
208 s = (ffesymbol) malloc_new_ks (FFESYMBOL_SPACE_POOL_, "FFESYMBOL",
209 sizeof (*s));
210 s->name = n;
211 s->other_space_name = NULL;
212 #if FFEGLOBAL_ENABLED
213 s->global = NULL;
214 #endif
215 s->attrs = FFESYMBOL_attrsetNONE;
216 s->state = FFESYMBOL_stateNONE;
217 s->info = ffeinfo_new_null ();
218 s->dims = NULL;
219 s->extents = NULL;
220 s->dim_syms = NULL;
221 s->array_size = NULL;
222 s->init = NULL;
223 s->accretion = NULL;
224 s->accretes = 0;
225 s->dummy_args = NULL;
226 s->namelist = NULL;
227 s->common_list = NULL;
228 s->sfunc_expr = NULL;
229 s->list_bottom = NULL;
230 s->common = NULL;
231 s->equiv = NULL;
232 s->storage = NULL;
233 #ifdef FFECOM_symbolHOOK
234 s->hook = FFECOM_symbolNULL;
235 #endif
236 s->sfa_dummy_parent = NULL;
237 s->func_result = NULL;
238 s->value = 0;
239 s->check_state = FFESYMBOL_checkstateNONE_;
240 s->check_token = NULL;
241 s->max_entry_num = 0;
242 s->num_entries = 0;
243 s->generic = FFEINTRIN_genNONE;
244 s->specific = FFEINTRIN_specNONE;
245 s->implementation = FFEINTRIN_impNONE;
246 s->is_save = FALSE;
247 s->is_init = FALSE;
248 s->do_iter = FALSE;
249 s->reported = FALSE;
250 s->explicit_where = FALSE;
251 s->namelisted = FALSE;
252 s->assigned = FALSE;
254 ffename_set_symbol (n, s);
256 if (!ffesymbol_retractable_)
258 s->have_old = FALSE;
259 return s;
262 r = (ffesymbolRetract_) malloc_new_kp (ffesymbol_retract_pool_,
263 "FFESYMBOL retract", sizeof (*r));
264 r->next = NULL;
265 r->command = FFESYMBOL_retractcommandDELETE_;
266 r->live = s;
267 r->symbol = NULL; /* No backup copy. */
269 *ffesymbol_retract_list_ = r;
270 ffesymbol_retract_list_ = &r->next;
272 s->have_old = TRUE;
273 return s;
276 /* Unhook a symbol from its (soon-to-be-killed) name obj.
278 NULLify the names to which this symbol points. Do other cleanup as
279 needed. */
281 static ffesymbol
282 ffesymbol_unhook_ (ffesymbol s)
284 s->other_space_name = s->name = NULL;
285 if ((ffesymbol_attrs (s) & FFESYMBOL_attrsCBLOCK)
286 || (ffesymbol_kind (s) == FFEINFO_kindNAMELIST))
287 ffebld_end_list (ffesymbol_ptr_to_listbottom (s));
288 if (s->check_state == FFESYMBOL_checkstatePENDING_)
289 ffelex_token_kill (s->check_token);
291 return s;
294 /* Issue diagnostic about bad character in token representing user-defined
295 symbol name. */
297 static void
298 ffesymbol_whine_state_ (ffebad bad, ffelexToken t, char c)
300 char badstr[2];
302 badstr[0] = c;
303 badstr[1] = '\0';
305 ffebad_start (bad);
306 ffebad_here (0, ffelex_token_where_line (t),
307 ffelex_token_where_column (t));
308 ffebad_string (badstr);
309 ffebad_finish ();
312 /* Returns a string representing the attributes set. */
314 const char *
315 ffesymbol_attrs_string (ffesymbolAttrs attrs)
317 static char string[FFESYMBOL_attr * 12 + 20];
318 char *p;
319 ffesymbolAttr attr;
321 p = &string[0];
323 if (attrs == FFESYMBOL_attrsetNONE)
325 strcpy (p, "NONE");
326 return &string[0];
329 for (attr = 0; attr < FFESYMBOL_attr; ++attr)
331 if (attrs & ((ffesymbolAttrs) 1 << attr))
333 attrs &= ~((ffesymbolAttrs) 1 << attr);
334 strcpy (p, ffesymbol_attr_name_[attr]);
335 while (*p)
336 ++p;
337 *(p++) = '|';
340 if (attrs == FFESYMBOL_attrsetNONE)
341 *--p = '\0';
342 else
343 sprintf (p, "?0x%" ffesymbolAttrs_f "x?", attrs);
344 assert (((size_t) (p - &string[0])) < ARRAY_SIZE (string));
345 return &string[0];
348 /* Check symbol's name for validity, considering that it might actually
349 be an intrinsic and thus should not be complained about just yet. */
351 void
352 ffesymbol_check (ffesymbol s, ffelexToken t, bool maybe_intrin)
354 char c;
355 ffebad bad;
356 ffeintrinGen gen;
357 ffeintrinSpec spec;
358 ffeintrinImp imp;
360 if (!ffesrc_check_symbol ()
361 || ((s->check_state != FFESYMBOL_checkstateNONE_)
362 && ((s->check_state != FFESYMBOL_checkstateINHIBITED_)
363 || ffebad_inhibit ())))
364 return;
366 bad = ffesymbol_check_token_ (t, &c);
368 if (bad == FFEBAD)
370 s->check_state = FFESYMBOL_checkstateCHECKED_;
371 return;
374 if (maybe_intrin
375 && ffeintrin_is_intrinsic (ffelex_token_text (t), NULL, FALSE,
376 &gen, &spec, &imp))
378 s->check_state = FFESYMBOL_checkstatePENDING_;
379 s->check_token = ffelex_token_use (t);
380 return;
383 if (ffebad_inhibit ())
385 s->check_state = FFESYMBOL_checkstateINHIBITED_;
386 return; /* Don't complain now, do it later. */
389 s->check_state = FFESYMBOL_checkstateCHECKED_;
391 ffesymbol_whine_state_ (bad, t, c);
394 /* Declare a BLOCKDATA unit.
396 Retrieves or creates the ffesymbol for the specified BLOCKDATA (unnamed
397 if t is NULL). Doesn't actually ensure the named item is a
398 BLOCKDATA; the caller must handle that. */
400 ffesymbol
401 ffesymbol_declare_blockdataunit (ffelexToken t, ffewhereLine wl,
402 ffewhereColumn wc)
404 ffename n;
405 ffesymbol s;
406 bool user = (t != NULL);
408 assert (!ffesymbol_retractable_);
410 if (t == NULL)
412 if (ffesymbol_token_unnamed_blockdata_ == NULL)
413 ffesymbol_token_unnamed_blockdata_
414 = ffelex_token_new_name (FFETARGET_nameUNNAMED_BLOCK_DATA, wl, wc);
415 t = ffesymbol_token_unnamed_blockdata_;
418 n = ffename_lookup (ffesymbol_local_, t);
419 if (n != NULL)
420 return ffename_symbol (n); /* This will become an error. */
422 n = ffename_find (ffesymbol_global_, t);
423 s = ffename_symbol (n);
424 if (s != NULL)
426 if (user)
427 ffesymbol_check (s, t, FALSE);
428 return s;
431 s = ffesymbol_new_ (n);
432 if (user)
433 ffesymbol_check (s, t, FALSE);
435 /* A program unit name also is in the local name space. */
437 n = ffename_find (ffesymbol_local_, t);
438 ffename_set_symbol (n, s);
439 s->other_space_name = n;
441 ffeglobal_new_blockdata (s, t); /* Detect conflicts, when
442 appropriate. */
444 return s;
447 /* Declare a common block (named or unnamed).
449 Retrieves or creates the ffesymbol for the specified common block (blank
450 common if t is NULL). Doesn't actually ensure the named item is a
451 common block; the caller must handle that. */
453 ffesymbol
454 ffesymbol_declare_cblock (ffelexToken t, ffewhereLine wl, ffewhereColumn wc)
456 ffename n;
457 ffesymbol s;
458 bool blank;
460 assert (!ffesymbol_retractable_);
462 if (t == NULL)
464 blank = TRUE;
465 if (ffesymbol_token_blank_common_ == NULL)
466 ffesymbol_token_blank_common_
467 = ffelex_token_new_name (FFETARGET_nameBLANK_COMMON, wl, wc);
468 t = ffesymbol_token_blank_common_;
470 else
471 blank = FALSE;
473 n = ffename_find (ffesymbol_global_, t);
474 s = ffename_symbol (n);
475 if (s != NULL)
477 if (!blank)
478 ffesymbol_check (s, t, FALSE);
479 return s;
482 s = ffesymbol_new_ (n);
483 if (!blank)
484 ffesymbol_check (s, t, FALSE);
486 ffeglobal_new_common (s, t, blank); /* Detect conflicts. */
488 return s;
491 /* Declare a FUNCTION program unit (with distinct RESULT() name).
493 Retrieves or creates the ffesymbol for the specified function. Doesn't
494 actually ensure the named item is a function; the caller must handle
495 that.
497 If FUNCTION with RESULT() is specified but the names are the same,
498 pretend as though RESULT() was not specified, and don't call this
499 function; use ffesymbol_declare_funcunit() instead. */
501 ffesymbol
502 ffesymbol_declare_funcnotresunit (ffelexToken t)
504 ffename n;
505 ffesymbol s;
507 assert (t != NULL);
508 assert (!ffesymbol_retractable_);
510 n = ffename_lookup (ffesymbol_local_, t);
511 if (n != NULL)
512 return ffename_symbol (n); /* This will become an error. */
514 n = ffename_find (ffesymbol_global_, t);
515 s = ffename_symbol (n);
516 if (s != NULL)
518 ffesymbol_check (s, t, FALSE);
519 return s;
522 s = ffesymbol_new_ (n);
523 ffesymbol_check (s, t, FALSE);
525 /* A FUNCTION program unit name also is in the local name space; handle it
526 here since RESULT() is a different name and is handled separately. */
528 n = ffename_find (ffesymbol_local_, t);
529 ffename_set_symbol (n, s);
530 s->other_space_name = n;
532 ffeglobal_new_function (s, t);/* Detect conflicts, when appropriate. */
534 return s;
537 /* Declare a function result.
539 Retrieves or creates the ffesymbol for the specified function result,
540 whether specified via a distinct RESULT() or by default in a FUNCTION or
541 ENTRY statement. */
543 ffesymbol
544 ffesymbol_declare_funcresult (ffelexToken t)
546 ffename n;
547 ffesymbol s;
549 assert (t != NULL);
550 assert (!ffesymbol_retractable_);
552 n = ffename_find (ffesymbol_local_, t);
553 s = ffename_symbol (n);
554 if (s != NULL)
555 return s;
557 return ffesymbol_new_ (n);
560 /* Declare a FUNCTION program unit with no RESULT().
562 Retrieves or creates the ffesymbol for the specified function. Doesn't
563 actually ensure the named item is a function; the caller must handle
564 that.
566 This is the function to call when the FUNCTION or ENTRY statement has
567 no separate and distinct name specified via RESULT(). That's because
568 this function enters the global name of the function in only the global
569 name space. ffesymbol_declare_funcresult() must still be called to
570 declare the name for the function result in the local name space. */
572 ffesymbol
573 ffesymbol_declare_funcunit (ffelexToken t)
575 ffename n;
576 ffesymbol s;
578 assert (t != NULL);
579 assert (!ffesymbol_retractable_);
581 n = ffename_find (ffesymbol_global_, t);
582 s = ffename_symbol (n);
583 if (s != NULL)
585 ffesymbol_check (s, t, FALSE);
586 return s;
589 s = ffesymbol_new_ (n);
590 ffesymbol_check (s, t, FALSE);
592 ffeglobal_new_function (s, t);/* Detect conflicts. */
594 return s;
597 /* Declare a local entity.
599 Retrieves or creates the ffesymbol for the specified local entity.
600 Set maybe_intrin TRUE if this name might turn out to name an
601 intrinsic (legitimately); otherwise if the name doesn't meet the
602 requirements for a user-defined symbol name, a diagnostic will be
603 issued right away rather than waiting until the intrinsicness of the
604 symbol is determined. */
606 ffesymbol
607 ffesymbol_declare_local (ffelexToken t, bool maybe_intrin)
609 ffename n;
610 ffesymbol s;
612 assert (t != NULL);
614 /* If we're parsing within a statement function definition, return the
615 symbol if already known (a dummy argument for the statement function).
616 Otherwise continue on, which means the symbol is declared within the
617 containing (local) program unit rather than the statement function
618 definition. */
620 if ((ffesymbol_sfunc_ != NULL)
621 && ((n = ffename_lookup (ffesymbol_sfunc_, t)) != NULL))
622 return ffename_symbol (n);
624 n = ffename_find (ffesymbol_local_, t);
625 s = ffename_symbol (n);
626 if (s != NULL)
628 ffesymbol_check (s, t, maybe_intrin);
629 return s;
632 s = ffesymbol_new_ (n);
633 ffesymbol_check (s, t, maybe_intrin);
634 return s;
637 /* Declare a main program unit.
639 Retrieves or creates the ffesymbol for the specified main program unit
640 (unnamed main program unit if t is NULL). Doesn't actually ensure the
641 named item is a program; the caller must handle that. */
643 ffesymbol
644 ffesymbol_declare_programunit (ffelexToken t, ffewhereLine wl,
645 ffewhereColumn wc)
647 ffename n;
648 ffesymbol s;
649 bool user = (t != NULL);
651 assert (!ffesymbol_retractable_);
653 if (t == NULL)
655 if (ffesymbol_token_unnamed_main_ == NULL)
656 ffesymbol_token_unnamed_main_
657 = ffelex_token_new_name (FFETARGET_nameUNNAMED_MAIN, wl, wc);
658 t = ffesymbol_token_unnamed_main_;
661 n = ffename_lookup (ffesymbol_local_, t);
662 if (n != NULL)
663 return ffename_symbol (n); /* This will become an error. */
665 n = ffename_find (ffesymbol_global_, t);
666 s = ffename_symbol (n);
667 if (s != NULL)
669 if (user)
670 ffesymbol_check (s, t, FALSE);
671 return s;
674 s = ffesymbol_new_ (n);
675 if (user)
676 ffesymbol_check (s, t, FALSE);
678 /* A program unit name also is in the local name space. */
680 n = ffename_find (ffesymbol_local_, t);
681 ffename_set_symbol (n, s);
682 s->other_space_name = n;
684 ffeglobal_new_program (s, t); /* Detect conflicts. */
686 return s;
689 /* Declare a statement-function dummy.
691 Retrieves or creates the ffesymbol for the specified statement
692 function dummy. Also ensures that it has a link to the parent (local)
693 ffesymbol with the same name, creating it if necessary. */
695 ffesymbol
696 ffesymbol_declare_sfdummy (ffelexToken t)
698 ffename n;
699 ffesymbol s;
700 ffesymbol sp; /* Parent symbol in local area. */
702 assert (t != NULL);
704 n = ffename_find (ffesymbol_local_, t);
705 sp = ffename_symbol (n);
706 if (sp == NULL)
707 sp = ffesymbol_new_ (n);
708 ffesymbol_check (sp, t, FALSE);
710 n = ffename_find (ffesymbol_sfunc_, t);
711 s = ffename_symbol (n);
712 if (s == NULL)
714 s = ffesymbol_new_ (n);
715 s->sfa_dummy_parent = sp;
717 else
718 assert (s->sfa_dummy_parent == sp);
720 return s;
723 /* Declare a subroutine program unit.
725 Retrieves or creates the ffesymbol for the specified subroutine
726 Doesn't actually ensure the named item is a subroutine; the caller must
727 handle that. */
729 ffesymbol
730 ffesymbol_declare_subrunit (ffelexToken t)
732 ffename n;
733 ffesymbol s;
735 assert (!ffesymbol_retractable_);
736 assert (t != NULL);
738 n = ffename_lookup (ffesymbol_local_, t);
739 if (n != NULL)
740 return ffename_symbol (n); /* This will become an error. */
742 n = ffename_find (ffesymbol_global_, t);
743 s = ffename_symbol (n);
744 if (s != NULL)
746 ffesymbol_check (s, t, FALSE);
747 return s;
750 s = ffesymbol_new_ (n);
751 ffesymbol_check (s, t, FALSE);
753 /* A program unit name also is in the local name space. */
755 n = ffename_find (ffesymbol_local_, t);
756 ffename_set_symbol (n, s);
757 s->other_space_name = n;
759 ffeglobal_new_subroutine (s, t); /* Detect conflicts, when
760 appropriate. */
762 return s;
765 /* Call given fn with all local/global symbols.
767 ffesymbol (*fn) (ffesymbol s);
768 ffesymbol_drive (fn); */
770 void
771 ffesymbol_drive (ffesymbol (*fn) (ffesymbol))
773 assert (ffesymbol_sfunc_ == NULL); /* Might be ok, but not for current
774 uses. */
775 ffename_space_drive_symbol (ffesymbol_local_, fn);
776 ffename_space_drive_symbol (ffesymbol_global_, fn);
779 /* Call given fn with all sfunc-only symbols.
781 ffesymbol (*fn) (ffesymbol s);
782 ffesymbol_drive_sfnames (fn); */
784 void
785 ffesymbol_drive_sfnames (ffesymbol (*fn) (ffesymbol))
787 ffename_space_drive_symbol (ffesymbol_sfunc_, fn);
790 /* Produce generic error message about a symbol.
792 For now, just output error message using symbol's name and pointing to
793 the token. */
795 void
796 ffesymbol_error (ffesymbol s, ffelexToken t)
798 if ((t != NULL)
799 && ffest_ffebad_start (FFEBAD_SYMERR))
801 ffebad_string (ffesymbol_text (s));
802 ffebad_here (0, ffelex_token_where_line (t),
803 ffelex_token_where_column (t));
804 ffebad_here (1, ffesymbol_where_line (s), ffesymbol_where_column (s));
805 ffebad_finish ();
808 if (ffesymbol_attr (s, FFESYMBOL_attrANY))
809 return;
811 ffesymbol_signal_change (s); /* May need to back up to previous version. */
812 if ((ffesymbol_attrs (s) & FFESYMBOL_attrsCBLOCK)
813 || (ffesymbol_kind (s) == FFEINFO_kindNAMELIST))
814 ffebld_end_list (ffesymbol_ptr_to_listbottom (s));
815 ffesymbol_set_attr (s, FFESYMBOL_attrANY);
816 ffesymbol_set_info (s, ffeinfo_new_any ());
817 ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
818 if (s->check_state == FFESYMBOL_checkstatePENDING_)
819 ffelex_token_kill (s->check_token);
820 s->check_state = FFESYMBOL_checkstateCHECKED_;
821 s = ffecom_sym_learned (s);
822 ffesymbol_signal_unreported (s);
825 void
826 ffesymbol_init_0 ()
828 ffesymbolAttrs attrs = FFESYMBOL_attrsetNONE;
830 assert (FFESYMBOL_state == ARRAY_SIZE (ffesymbol_state_name_));
831 assert (FFESYMBOL_attr == ARRAY_SIZE (ffesymbol_attr_name_));
832 assert (attrs == FFESYMBOL_attrsetNONE);
833 attrs = ((ffesymbolAttrs) 1 << FFESYMBOL_attr);
834 assert (attrs != 0);
837 void
838 ffesymbol_init_1 ()
840 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalFILE_
841 ffesymbol_global_ = ffename_space_new (ffe_pool_file ());
842 #endif
845 void
846 ffesymbol_init_2 ()
850 void
851 ffesymbol_init_3 ()
853 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalPROGUNIT_
854 ffesymbol_global_ = ffename_space_new (ffe_pool_program_unit ());
855 #endif
856 ffesymbol_local_ = ffename_space_new (ffe_pool_program_unit ());
859 void
860 ffesymbol_init_4 ()
862 ffesymbol_sfunc_ = ffename_space_new (ffe_pool_program_unit ());
865 /* Look up a local entity.
867 Retrieves the ffesymbol for the specified local entity, or returns NULL
868 if no local entity by that name exists. */
870 ffesymbol
871 ffesymbol_lookup_local (ffelexToken t)
873 ffename n;
874 ffesymbol s;
876 assert (t != NULL);
878 n = ffename_lookup (ffesymbol_local_, t);
879 if (n == NULL)
880 return NULL;
882 s = ffename_symbol (n);
883 return s; /* May be NULL here, too. */
886 /* Registers the symbol as one that is referenced by the
887 current program unit. Currently applies only to
888 symbols known to have global interest (globals and
889 intrinsics).
891 s is the (global/intrinsic) symbol referenced; t is the
892 referencing token; explicit is TRUE if the reference
893 is, e.g., INTRINSIC FOO. */
895 void
896 ffesymbol_reference (ffesymbol s, ffelexToken t, bool explicit)
898 ffename gn;
899 ffesymbol gs = NULL;
900 ffeinfoKind kind;
901 ffeinfoWhere where;
902 bool okay;
904 if (ffesymbol_retractable_)
905 return;
907 if (t == NULL)
908 t = ffename_token (s->name); /* Use the first reference in this program unit. */
910 kind = ffesymbol_kind (s);
911 where = ffesymbol_where (s);
913 if (where == FFEINFO_whereINTRINSIC)
915 ffeglobal_ref_intrinsic (s, t,
916 explicit
917 || s->explicit_where
918 || ffeintrin_is_standard (s->generic, s->specific));
919 return;
922 if ((where != FFEINFO_whereGLOBAL)
923 && ((where != FFEINFO_whereLOCAL)
924 || ((kind != FFEINFO_kindFUNCTION)
925 && (kind != FFEINFO_kindSUBROUTINE))))
926 return;
928 gn = ffename_lookup (ffesymbol_global_, t);
929 if (gn != NULL)
930 gs = ffename_symbol (gn);
931 if ((gs != NULL) && (gs != s))
933 /* We have just discovered another global symbol with the same name
934 but a different `nature'. Complain. Note that COMMON /FOO/ can
935 coexist with local symbol FOO, e.g. local variable, just not with
936 CALL FOO, hence the separate namespaces. */
938 ffesymbol_error (gs, t);
939 ffesymbol_error (s, NULL);
940 return;
943 switch (kind)
945 case FFEINFO_kindBLOCKDATA:
946 okay = ffeglobal_ref_blockdata (s, t);
947 break;
949 case FFEINFO_kindSUBROUTINE:
950 okay = ffeglobal_ref_subroutine (s, t);
951 break;
953 case FFEINFO_kindFUNCTION:
954 okay = ffeglobal_ref_function (s, t);
955 break;
957 case FFEINFO_kindNONE:
958 okay = ffeglobal_ref_external (s, t);
959 break;
961 default:
962 assert ("bad kind in global ref" == NULL);
963 return;
966 if (! okay)
967 ffesymbol_error (s, NULL);
970 /* Resolve symbol that has become known intrinsic or non-intrinsic. */
972 void
973 ffesymbol_resolve_intrin (ffesymbol s)
975 char c;
976 ffebad bad;
978 if (!ffesrc_check_symbol ())
979 return;
980 if (s->check_state != FFESYMBOL_checkstatePENDING_)
981 return;
982 if (ffebad_inhibit ())
983 return; /* We'll get back to this later. */
985 if (ffesymbol_where (s) != FFEINFO_whereINTRINSIC)
987 bad = ffesymbol_check_token_ (s->check_token, &c);
988 assert (bad != FFEBAD); /* How did this suddenly become ok? */
989 ffesymbol_whine_state_ (bad, s->check_token, c);
992 s->check_state = FFESYMBOL_checkstateCHECKED_;
993 ffelex_token_kill (s->check_token);
996 /* Retract or cancel retract list. */
998 void
999 ffesymbol_retract (bool retract)
1001 ffesymbolRetract_ r;
1002 ffename name;
1003 ffename other_space_name;
1004 ffesymbol ls;
1005 ffesymbol os;
1007 assert (ffesymbol_retractable_);
1009 ffesymbol_retractable_ = FALSE;
1011 for (r = ffesymbol_retract_first_; r != NULL; r = r->next)
1013 ls = r->live;
1014 os = r->symbol;
1015 switch (r->command)
1017 case FFESYMBOL_retractcommandDELETE_:
1018 if (retract)
1020 ffecom_sym_retract (ls);
1021 name = ls->name;
1022 other_space_name = ls->other_space_name;
1023 ffesymbol_unhook_ (ls);
1024 malloc_kill_ks (FFESYMBOL_SPACE_POOL_, ls, sizeof (*ls));
1025 if (name != NULL)
1026 ffename_set_symbol (name, NULL);
1027 if (other_space_name != NULL)
1028 ffename_set_symbol (other_space_name, NULL);
1030 else
1032 ffecom_sym_commit (ls);
1033 ls->have_old = FALSE;
1035 break;
1037 case FFESYMBOL_retractcommandRETRACT_:
1038 if (retract)
1040 ffecom_sym_retract (ls);
1041 ffesymbol_unhook_ (ls);
1042 *ls = *os;
1043 malloc_kill_ks (FFESYMBOL_SPACE_POOL_, os, sizeof (*os));
1045 else
1047 ffecom_sym_commit (ls);
1048 ffesymbol_unhook_ (os);
1049 malloc_kill_ks (FFESYMBOL_SPACE_POOL_, os, sizeof (*os));
1050 ls->have_old = FALSE;
1052 break;
1054 default:
1055 assert ("bad command" == NULL);
1056 break;
1061 /* Return retractable flag. */
1063 bool
1064 ffesymbol_retractable ()
1066 return ffesymbol_retractable_;
1069 /* Set retractable flag, retract pool.
1071 Between this call and ffesymbol_retract, any changes made to existing
1072 symbols cause the previous versions of those symbols to be saved, and any
1073 newly created symbols to have their previous nonexistence saved. When
1074 ffesymbol_retract is called, this information either is used to retract
1075 the changes and new symbols, or is discarded. */
1077 void
1078 ffesymbol_set_retractable (mallocPool pool)
1080 assert (!ffesymbol_retractable_);
1082 ffesymbol_retractable_ = TRUE;
1083 ffesymbol_retract_pool_ = pool;
1084 ffesymbol_retract_list_ = &ffesymbol_retract_first_;
1085 ffesymbol_retract_first_ = NULL;
1088 /* Existing symbol about to be changed; save?
1090 Call this function before changing a symbol if it is possible that
1091 the current actions may need to be undone (i.e. one of several possible
1092 statement forms are being used to analyze the current system).
1094 If the "retractable" flag is not set, just return.
1095 Else, if the symbol's "have_old" flag is set, just return.
1096 Else, make a copy of the symbol and add it to the "retract" list, set
1097 the "have_old" flag, and return. */
1099 void
1100 ffesymbol_signal_change (ffesymbol s)
1102 ffesymbolRetract_ r;
1103 ffesymbol sym;
1105 if (!ffesymbol_retractable_ || s->have_old)
1106 return;
1108 r = (ffesymbolRetract_) malloc_new_kp (ffesymbol_retract_pool_,
1109 "FFESYMBOL retract", sizeof (*r));
1110 r->next = NULL;
1111 r->command = FFESYMBOL_retractcommandRETRACT_;
1112 r->live = s;
1113 r->symbol = sym = (ffesymbol) malloc_new_ks (FFESYMBOL_SPACE_POOL_,
1114 "FFESYMBOL", sizeof (*sym));
1115 *sym = *s; /* Make an exact copy of the symbol in case
1116 we need it back. */
1117 sym->info = ffeinfo_use (s->info);
1118 if (s->check_state == FFESYMBOL_checkstatePENDING_)
1119 sym->check_token = ffelex_token_use (s->check_token);
1121 *ffesymbol_retract_list_ = r;
1122 ffesymbol_retract_list_ = &r->next;
1124 s->have_old = TRUE;
1127 /* Returns the string based on the state. */
1129 const char *
1130 ffesymbol_state_string (ffesymbolState state)
1132 if (state >= ARRAY_SIZE (ffesymbol_state_name_))
1133 return "?\?\?";
1134 return ffesymbol_state_name_[state];
1137 void
1138 ffesymbol_terminate_0 ()
1142 void
1143 ffesymbol_terminate_1 ()
1145 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalFILE_
1146 ffename_space_drive_symbol (ffesymbol_global_, ffesymbol_unhook_);
1147 ffename_space_kill (ffesymbol_global_);
1148 ffesymbol_global_ = NULL;
1150 ffesymbol_kill_manifest_ ();
1151 #endif
1154 void
1155 ffesymbol_terminate_2 ()
1157 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalPROGUNIT_
1158 ffesymbol_kill_manifest_ ();
1159 #endif
1162 void
1163 ffesymbol_terminate_3 ()
1165 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalPROGUNIT_
1166 ffename_space_drive_symbol (ffesymbol_global_, ffesymbol_unhook_);
1167 ffename_space_kill (ffesymbol_global_);
1168 #endif
1169 ffename_space_drive_symbol (ffesymbol_local_, ffesymbol_unhook_);
1170 ffename_space_kill (ffesymbol_local_);
1171 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalPROGUNIT_
1172 ffesymbol_global_ = NULL;
1173 #endif
1174 ffesymbol_local_ = NULL;
1177 void
1178 ffesymbol_terminate_4 ()
1180 ffename_space_drive_symbol (ffesymbol_sfunc_, ffesymbol_unhook_);
1181 ffename_space_kill (ffesymbol_sfunc_);
1182 ffesymbol_sfunc_ = NULL;
1185 /* Update INIT info to TRUE and all equiv/storage too.
1187 If INIT flag is TRUE, does nothing. Else sets it to TRUE and calls
1188 on the ffeequiv and ffestorag modules to update their INIT flags if
1189 the <s> symbol has those objects, and also updates the common area if
1190 it exists. */
1192 void
1193 ffesymbol_update_init (ffesymbol s)
1195 ffebld item;
1197 if (s->is_init)
1198 return;
1200 s->is_init = TRUE;
1202 if ((s->equiv != NULL)
1203 && !ffeequiv_is_init (s->equiv))
1204 ffeequiv_update_init (s->equiv);
1206 if ((s->storage != NULL)
1207 && !ffestorag_is_init (s->storage))
1208 ffestorag_update_init (s->storage);
1210 if ((s->common != NULL)
1211 && (!ffesymbol_is_init (s->common)))
1212 ffesymbol_update_init (s->common);
1214 for (item = s->common_list; item != NULL; item = ffebld_trail (item))
1216 if (!ffesymbol_is_init (ffebld_symter (ffebld_head (item))))
1217 ffesymbol_update_init (ffebld_symter (ffebld_head (item)));
1221 /* Update SAVE info to TRUE and all equiv/storage too.
1223 If SAVE flag is TRUE, does nothing. Else sets it to TRUE and calls
1224 on the ffeequiv and ffestorag modules to update their SAVE flags if
1225 the <s> symbol has those objects, and also updates the common area if
1226 it exists. */
1228 void
1229 ffesymbol_update_save (ffesymbol s)
1231 ffebld item;
1233 if (s->is_save)
1234 return;
1236 s->is_save = TRUE;
1238 if ((s->equiv != NULL)
1239 && !ffeequiv_is_save (s->equiv))
1240 ffeequiv_update_save (s->equiv);
1242 if ((s->storage != NULL)
1243 && !ffestorag_is_save (s->storage))
1244 ffestorag_update_save (s->storage);
1246 if ((s->common != NULL)
1247 && (!ffesymbol_is_save (s->common)))
1248 ffesymbol_update_save (s->common);
1250 for (item = s->common_list; item != NULL; item = ffebld_trail (item))
1252 if (!ffesymbol_is_save (ffebld_symter (ffebld_head (item))))
1253 ffesymbol_update_save (ffebld_symter (ffebld_head (item)));