* sh.c (prepare_move_operand): Check if operand 0 is an invalid
[official-gcc.git] / gcc / f / symbol.c
blobaf452203ba3c19199e475a57fc819ae53ce10a3b
1 /* Implementation of Fortran symbol manager
2 Copyright (C) 1995, 1996, 1997, 2003
3 Free Software Foundation, Inc.
4 Contributed by James Craig Burley.
6 This file is part of GNU Fortran.
8 GNU Fortran is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 GNU Fortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Fortran; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA. */
23 #include "proj.h"
24 #include "symbol.h"
25 #include "bad.h"
26 #include "bld.h"
27 #include "com.h"
28 #include "equiv.h"
29 #include "global.h"
30 #include "info.h"
31 #include "intrin.h"
32 #include "lex.h"
33 #include "malloc.h"
34 #include "src.h"
35 #include "st.h"
36 #include "storag.h"
37 #include "target.h"
38 #include "where.h"
40 /* Choice of how to handle global symbols -- either global only within the
41 program unit being defined or global within the entire source file.
42 The former is appropriate for systems where an object file can
43 easily be taken apart program unit by program unit, the latter is the
44 UNIX/C model where the object file is essentially a monolith. */
46 #define FFESYMBOL_globalPROGUNIT_ 1
47 #define FFESYMBOL_globalFILE_ 2
49 /* Choose how to handle global symbols here. */
51 /* Would be good to understand why PROGUNIT in this case too.
52 (1995-08-22). */
53 #define FFESYMBOL_globalCURRENT_ FFESYMBOL_globalPROGUNIT_
55 /* Choose how to handle memory pools based on global symbol stuff. */
57 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalPROGUNIT_
58 #define FFESYMBOL_SPACE_POOL_ ffe_pool_program_unit()
59 #elif FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalFILE_
60 #define FFESYMBOL_SPACE_POOL_ ffe_pool_file()
61 #else
62 #error
63 #endif
65 /* What kind of retraction is needed for a symbol? */
67 enum _ffesymbol_retractcommand_
69 FFESYMBOL_retractcommandDELETE_,
70 FFESYMBOL_retractcommandRETRACT_,
71 FFESYMBOL_retractcommand_
73 typedef enum _ffesymbol_retractcommand_ ffesymbolRetractCommand_;
75 /* This object keeps track of retraction for a symbol and links to the next
76 such object. */
78 typedef struct _ffesymbol_retract_ *ffesymbolRetract_;
79 struct _ffesymbol_retract_
81 ffesymbolRetract_ next;
82 ffesymbolRetractCommand_ command;
83 ffesymbol live; /* Live symbol. */
84 ffesymbol symbol; /* Backup copy of symbol. */
87 static ffebad ffesymbol_check_token_ (ffelexToken t, char *c);
88 static void ffesymbol_kill_manifest_ (void);
89 static ffesymbol ffesymbol_new_ (ffename n);
90 static ffesymbol ffesymbol_unhook_ (ffesymbol s);
91 static void ffesymbol_whine_state_ (ffebad bad, ffelexToken t, char c);
93 /* Manifest names for unnamed things (as tokens) so we make them only
94 once. */
96 static ffelexToken ffesymbol_token_blank_common_ = NULL;
97 static ffelexToken ffesymbol_token_unnamed_main_ = NULL;
98 static ffelexToken ffesymbol_token_unnamed_blockdata_ = NULL;
100 /* Name spaces currently in force. */
102 static ffenameSpace ffesymbol_global_ = NULL;
103 static ffenameSpace ffesymbol_local_ = NULL;
104 static ffenameSpace ffesymbol_sfunc_ = NULL;
106 /* Keep track of retraction. */
108 static bool ffesymbol_retractable_ = FALSE;
109 static mallocPool ffesymbol_retract_pool_;
110 static ffesymbolRetract_ ffesymbol_retract_first_;
111 static ffesymbolRetract_ *ffesymbol_retract_list_;
113 /* List of state names. */
115 static const char *const ffesymbol_state_name_[] =
117 "?",
118 "@",
119 "&",
120 "$",
123 /* List of attribute names. */
125 static const char *const ffesymbol_attr_name_[] =
127 #define DEFATTR(ATTR,ATTRS,NAME) NAME,
128 #include "symbol.def"
129 #undef DEFATTR
133 /* Check whether the token text has any invalid characters. If not,
134 return FALSE. If so, if error messages inhibited, return TRUE
135 so caller knows to try again later, else report error and return
136 FALSE. */
138 static ffebad
139 ffesymbol_check_token_ (ffelexToken t, char *c)
141 char *p = ffelex_token_text (t);
142 ffeTokenLength len = ffelex_token_length (t);
143 ffebad bad;
144 ffeTokenLength i = 0;
145 ffebad skip_me = ((ffe_case_symbol () == FFE_caseINITCAP)
146 ? FFEBAD_SYMBOL_NOLOWER_INITCAP : FFEBAD + 1);
147 ffebad stop_me = ((ffe_case_symbol () == FFE_caseINITCAP)
148 ? FFEBAD : FFEBAD + 1);
149 if (len == 0)
150 return FFEBAD;
152 bad = ffesrc_bad_char_symbol_init (*p);
153 if (bad == FFEBAD)
155 for (++i, ++p; i < len; ++i, ++p)
157 bad = ffesrc_bad_char_symbol_noninit (*p);
158 if (bad == skip_me)
159 continue; /* Keep looking for good InitCap character. */
160 if (bad == stop_me)
161 break; /* Found good InitCap character. */
162 if (bad != FFEBAD)
163 break; /* Bad character found. */
167 if (bad != FFEBAD)
169 if (i >= len)
170 *c = *(ffelex_token_text (t));
171 else
172 *c = *p;
175 return bad;
178 /* Kill manifest (g77-picked) names. */
180 static void
181 ffesymbol_kill_manifest_ ()
183 if (ffesymbol_token_blank_common_ != NULL)
184 ffelex_token_kill (ffesymbol_token_blank_common_);
185 if (ffesymbol_token_unnamed_main_ != NULL)
186 ffelex_token_kill (ffesymbol_token_unnamed_main_);
187 if (ffesymbol_token_unnamed_blockdata_ != NULL)
188 ffelex_token_kill (ffesymbol_token_unnamed_blockdata_);
190 ffesymbol_token_blank_common_ = NULL;
191 ffesymbol_token_unnamed_main_ = NULL;
192 ffesymbol_token_unnamed_blockdata_ = NULL;
195 /* Make new symbol.
197 If the "retractable" flag is not set, just return the new symbol.
198 Else, add symbol to the "retract" list as a delete item, set
199 the "have_old" flag, and return the new symbol. */
201 static ffesymbol
202 ffesymbol_new_ (ffename n)
204 ffesymbol s;
205 ffesymbolRetract_ r;
207 assert (n != NULL);
209 s = (ffesymbol) malloc_new_ks (FFESYMBOL_SPACE_POOL_, "FFESYMBOL",
210 sizeof (*s));
211 s->name = n;
212 s->other_space_name = NULL;
213 #if FFEGLOBAL_ENABLED
214 s->global = NULL;
215 #endif
216 s->attrs = FFESYMBOL_attrsetNONE;
217 s->state = FFESYMBOL_stateNONE;
218 s->info = ffeinfo_new_null ();
219 s->dims = NULL;
220 s->extents = NULL;
221 s->dim_syms = NULL;
222 s->array_size = NULL;
223 s->init = NULL;
224 s->accretion = NULL;
225 s->accretes = 0;
226 s->dummy_args = NULL;
227 s->namelist = NULL;
228 s->common_list = NULL;
229 s->sfunc_expr = NULL;
230 s->list_bottom = NULL;
231 s->common = NULL;
232 s->equiv = NULL;
233 s->storage = NULL;
234 s->hook = FFECOM_symbolNULL;
235 s->sfa_dummy_parent = NULL;
236 s->func_result = NULL;
237 s->value = 0;
238 s->check_state = FFESYMBOL_checkstateNONE_;
239 s->check_token = NULL;
240 s->max_entry_num = 0;
241 s->num_entries = 0;
242 s->generic = FFEINTRIN_genNONE;
243 s->specific = FFEINTRIN_specNONE;
244 s->implementation = FFEINTRIN_impNONE;
245 s->is_save = FALSE;
246 s->is_init = FALSE;
247 s->do_iter = FALSE;
248 s->reported = FALSE;
249 s->explicit_where = FALSE;
250 s->namelisted = FALSE;
251 s->assigned = FALSE;
253 ffename_set_symbol (n, s);
255 if (!ffesymbol_retractable_)
257 s->have_old = FALSE;
258 return s;
261 r = (ffesymbolRetract_) malloc_new_kp (ffesymbol_retract_pool_,
262 "FFESYMBOL retract", sizeof (*r));
263 r->next = NULL;
264 r->command = FFESYMBOL_retractcommandDELETE_;
265 r->live = s;
266 r->symbol = NULL; /* No backup copy. */
268 *ffesymbol_retract_list_ = r;
269 ffesymbol_retract_list_ = &r->next;
271 s->have_old = TRUE;
272 return s;
275 /* Unhook a symbol from its (soon-to-be-killed) name obj.
277 NULLify the names to which this symbol points. Do other cleanup as
278 needed. */
280 static ffesymbol
281 ffesymbol_unhook_ (ffesymbol s)
283 s->other_space_name = s->name = NULL;
284 if ((ffesymbol_attrs (s) & FFESYMBOL_attrsCBLOCK)
285 || (ffesymbol_kind (s) == FFEINFO_kindNAMELIST))
286 ffebld_end_list (ffesymbol_ptr_to_listbottom (s));
287 if (s->check_state == FFESYMBOL_checkstatePENDING_)
288 ffelex_token_kill (s->check_token);
290 return s;
293 /* Issue diagnostic about bad character in token representing user-defined
294 symbol name. */
296 static void
297 ffesymbol_whine_state_ (ffebad bad, ffelexToken t, char c)
299 char badstr[2];
301 badstr[0] = c;
302 badstr[1] = '\0';
304 ffebad_start (bad);
305 ffebad_here (0, ffelex_token_where_line (t),
306 ffelex_token_where_column (t));
307 ffebad_string (badstr);
308 ffebad_finish ();
311 /* Returns a string representing the attributes set. */
313 const char *
314 ffesymbol_attrs_string (ffesymbolAttrs attrs)
316 static char string[FFESYMBOL_attr * 12 + 20];
317 char *p;
318 ffesymbolAttr attr;
320 p = &string[0];
322 if (attrs == FFESYMBOL_attrsetNONE)
324 strcpy (p, "NONE");
325 return &string[0];
328 for (attr = 0; attr < FFESYMBOL_attr; ++attr)
330 if (attrs & ((ffesymbolAttrs) 1 << attr))
332 attrs &= ~((ffesymbolAttrs) 1 << attr);
333 strcpy (p, ffesymbol_attr_name_[attr]);
334 while (*p)
335 ++p;
336 *(p++) = '|';
339 if (attrs == FFESYMBOL_attrsetNONE)
340 *--p = '\0';
341 else
342 sprintf (p, "?0x%" ffesymbolAttrs_f "x?", attrs);
343 assert (((size_t) (p - &string[0])) < ARRAY_SIZE (string));
344 return &string[0];
347 /* Check symbol's name for validity, considering that it might actually
348 be an intrinsic and thus should not be complained about just yet. */
350 void
351 ffesymbol_check (ffesymbol s, ffelexToken t, bool maybe_intrin)
353 char c;
354 ffebad bad;
355 ffeintrinGen gen;
356 ffeintrinSpec spec;
357 ffeintrinImp imp;
359 if (!ffesrc_check_symbol ()
360 || ((s->check_state != FFESYMBOL_checkstateNONE_)
361 && ((s->check_state != FFESYMBOL_checkstateINHIBITED_)
362 || ffebad_inhibit ())))
363 return;
365 bad = ffesymbol_check_token_ (t, &c);
367 if (bad == FFEBAD)
369 s->check_state = FFESYMBOL_checkstateCHECKED_;
370 return;
373 if (maybe_intrin
374 && ffeintrin_is_intrinsic (ffelex_token_text (t), NULL, FALSE,
375 &gen, &spec, &imp))
377 s->check_state = FFESYMBOL_checkstatePENDING_;
378 s->check_token = ffelex_token_use (t);
379 return;
382 if (ffebad_inhibit ())
384 s->check_state = FFESYMBOL_checkstateINHIBITED_;
385 return; /* Don't complain now, do it later. */
388 s->check_state = FFESYMBOL_checkstateCHECKED_;
390 ffesymbol_whine_state_ (bad, t, c);
393 /* Declare a BLOCKDATA unit.
395 Retrieves or creates the ffesymbol for the specified BLOCKDATA (unnamed
396 if t is NULL). Doesn't actually ensure the named item is a
397 BLOCKDATA; the caller must handle that. */
399 ffesymbol
400 ffesymbol_declare_blockdataunit (ffelexToken t, ffewhereLine wl,
401 ffewhereColumn wc)
403 ffename n;
404 ffesymbol s;
405 bool user = (t != NULL);
407 assert (!ffesymbol_retractable_);
409 if (t == NULL)
411 if (ffesymbol_token_unnamed_blockdata_ == NULL)
412 ffesymbol_token_unnamed_blockdata_
413 = ffelex_token_new_name (FFETARGET_nameUNNAMED_BLOCK_DATA, wl, wc);
414 t = ffesymbol_token_unnamed_blockdata_;
417 n = ffename_lookup (ffesymbol_local_, t);
418 if (n != NULL)
419 return ffename_symbol (n); /* This will become an error. */
421 n = ffename_find (ffesymbol_global_, t);
422 s = ffename_symbol (n);
423 if (s != NULL)
425 if (user)
426 ffesymbol_check (s, t, FALSE);
427 return s;
430 s = ffesymbol_new_ (n);
431 if (user)
432 ffesymbol_check (s, t, FALSE);
434 /* A program unit name also is in the local name space. */
436 n = ffename_find (ffesymbol_local_, t);
437 ffename_set_symbol (n, s);
438 s->other_space_name = n;
440 ffeglobal_new_blockdata (s, t); /* Detect conflicts, when
441 appropriate. */
443 return s;
446 /* Declare a common block (named or unnamed).
448 Retrieves or creates the ffesymbol for the specified common block (blank
449 common if t is NULL). Doesn't actually ensure the named item is a
450 common block; the caller must handle that. */
452 ffesymbol
453 ffesymbol_declare_cblock (ffelexToken t, ffewhereLine wl, ffewhereColumn wc)
455 ffename n;
456 ffesymbol s;
457 bool blank;
459 assert (!ffesymbol_retractable_);
461 if (t == NULL)
463 blank = TRUE;
464 if (ffesymbol_token_blank_common_ == NULL)
465 ffesymbol_token_blank_common_
466 = ffelex_token_new_name (FFETARGET_nameBLANK_COMMON, wl, wc);
467 t = ffesymbol_token_blank_common_;
469 else
470 blank = FALSE;
472 n = ffename_find (ffesymbol_global_, t);
473 s = ffename_symbol (n);
474 if (s != NULL)
476 if (!blank)
477 ffesymbol_check (s, t, FALSE);
478 return s;
481 s = ffesymbol_new_ (n);
482 if (!blank)
483 ffesymbol_check (s, t, FALSE);
485 ffeglobal_new_common (s, t, blank); /* Detect conflicts. */
487 return s;
490 /* Declare a FUNCTION program unit (with distinct RESULT() name).
492 Retrieves or creates the ffesymbol for the specified function. Doesn't
493 actually ensure the named item is a function; the caller must handle
494 that.
496 If FUNCTION with RESULT() is specified but the names are the same,
497 pretend as though RESULT() was not specified, and don't call this
498 function; use ffesymbol_declare_funcunit() instead. */
500 ffesymbol
501 ffesymbol_declare_funcnotresunit (ffelexToken t)
503 ffename n;
504 ffesymbol s;
506 assert (t != NULL);
507 assert (!ffesymbol_retractable_);
509 n = ffename_lookup (ffesymbol_local_, t);
510 if (n != NULL)
511 return ffename_symbol (n); /* This will become an error. */
513 n = ffename_find (ffesymbol_global_, t);
514 s = ffename_symbol (n);
515 if (s != NULL)
517 ffesymbol_check (s, t, FALSE);
518 return s;
521 s = ffesymbol_new_ (n);
522 ffesymbol_check (s, t, FALSE);
524 /* A FUNCTION program unit name also is in the local name space; handle it
525 here since RESULT() is a different name and is handled separately. */
527 n = ffename_find (ffesymbol_local_, t);
528 ffename_set_symbol (n, s);
529 s->other_space_name = n;
531 ffeglobal_new_function (s, t);/* Detect conflicts, when appropriate. */
533 return s;
536 /* Declare a function result.
538 Retrieves or creates the ffesymbol for the specified function result,
539 whether specified via a distinct RESULT() or by default in a FUNCTION or
540 ENTRY statement. */
542 ffesymbol
543 ffesymbol_declare_funcresult (ffelexToken t)
545 ffename n;
546 ffesymbol s;
548 assert (t != NULL);
549 assert (!ffesymbol_retractable_);
551 n = ffename_find (ffesymbol_local_, t);
552 s = ffename_symbol (n);
553 if (s != NULL)
554 return s;
556 return ffesymbol_new_ (n);
559 /* Declare a FUNCTION program unit with no RESULT().
561 Retrieves or creates the ffesymbol for the specified function. Doesn't
562 actually ensure the named item is a function; the caller must handle
563 that.
565 This is the function to call when the FUNCTION or ENTRY statement has
566 no separate and distinct name specified via RESULT(). That's because
567 this function enters the global name of the function in only the global
568 name space. ffesymbol_declare_funcresult() must still be called to
569 declare the name for the function result in the local name space. */
571 ffesymbol
572 ffesymbol_declare_funcunit (ffelexToken t)
574 ffename n;
575 ffesymbol s;
577 assert (t != NULL);
578 assert (!ffesymbol_retractable_);
580 n = ffename_find (ffesymbol_global_, t);
581 s = ffename_symbol (n);
582 if (s != NULL)
584 ffesymbol_check (s, t, FALSE);
585 return s;
588 s = ffesymbol_new_ (n);
589 ffesymbol_check (s, t, FALSE);
591 ffeglobal_new_function (s, t);/* Detect conflicts. */
593 return s;
596 /* Declare a local entity.
598 Retrieves or creates the ffesymbol for the specified local entity.
599 Set maybe_intrin TRUE if this name might turn out to name an
600 intrinsic (legitimately); otherwise if the name doesn't meet the
601 requirements for a user-defined symbol name, a diagnostic will be
602 issued right away rather than waiting until the intrinsicness of the
603 symbol is determined. */
605 ffesymbol
606 ffesymbol_declare_local (ffelexToken t, bool maybe_intrin)
608 ffename n;
609 ffesymbol s;
611 assert (t != NULL);
613 /* If we're parsing within a statement function definition, return the
614 symbol if already known (a dummy argument for the statement function).
615 Otherwise continue on, which means the symbol is declared within the
616 containing (local) program unit rather than the statement function
617 definition. */
619 if ((ffesymbol_sfunc_ != NULL)
620 && ((n = ffename_lookup (ffesymbol_sfunc_, t)) != NULL))
621 return ffename_symbol (n);
623 n = ffename_find (ffesymbol_local_, t);
624 s = ffename_symbol (n);
625 if (s != NULL)
627 ffesymbol_check (s, t, maybe_intrin);
628 return s;
631 s = ffesymbol_new_ (n);
632 ffesymbol_check (s, t, maybe_intrin);
633 return s;
636 /* Declare a main program unit.
638 Retrieves or creates the ffesymbol for the specified main program unit
639 (unnamed main program unit if t is NULL). Doesn't actually ensure the
640 named item is a program; the caller must handle that. */
642 ffesymbol
643 ffesymbol_declare_programunit (ffelexToken t, ffewhereLine wl,
644 ffewhereColumn wc)
646 ffename n;
647 ffesymbol s;
648 bool user = (t != NULL);
650 assert (!ffesymbol_retractable_);
652 if (t == NULL)
654 if (ffesymbol_token_unnamed_main_ == NULL)
655 ffesymbol_token_unnamed_main_
656 = ffelex_token_new_name (FFETARGET_nameUNNAMED_MAIN, wl, wc);
657 t = ffesymbol_token_unnamed_main_;
660 n = ffename_lookup (ffesymbol_local_, t);
661 if (n != NULL)
662 return ffename_symbol (n); /* This will become an error. */
664 n = ffename_find (ffesymbol_global_, t);
665 s = ffename_symbol (n);
666 if (s != NULL)
668 if (user)
669 ffesymbol_check (s, t, FALSE);
670 return s;
673 s = ffesymbol_new_ (n);
674 if (user)
675 ffesymbol_check (s, t, FALSE);
677 /* A program unit name also is in the local name space. */
679 n = ffename_find (ffesymbol_local_, t);
680 ffename_set_symbol (n, s);
681 s->other_space_name = n;
683 ffeglobal_new_program (s, t); /* Detect conflicts. */
685 return s;
688 /* Declare a statement-function dummy.
690 Retrieves or creates the ffesymbol for the specified statement
691 function dummy. Also ensures that it has a link to the parent (local)
692 ffesymbol with the same name, creating it if necessary. */
694 ffesymbol
695 ffesymbol_declare_sfdummy (ffelexToken t)
697 ffename n;
698 ffesymbol s;
699 ffesymbol sp; /* Parent symbol in local area. */
701 assert (t != NULL);
703 n = ffename_find (ffesymbol_local_, t);
704 sp = ffename_symbol (n);
705 if (sp == NULL)
706 sp = ffesymbol_new_ (n);
707 ffesymbol_check (sp, t, FALSE);
709 n = ffename_find (ffesymbol_sfunc_, t);
710 s = ffename_symbol (n);
711 if (s == NULL)
713 s = ffesymbol_new_ (n);
714 s->sfa_dummy_parent = sp;
716 else
717 assert (s->sfa_dummy_parent == sp);
719 return s;
722 /* Declare a subroutine program unit.
724 Retrieves or creates the ffesymbol for the specified subroutine
725 Doesn't actually ensure the named item is a subroutine; the caller must
726 handle that. */
728 ffesymbol
729 ffesymbol_declare_subrunit (ffelexToken t)
731 ffename n;
732 ffesymbol s;
734 assert (!ffesymbol_retractable_);
735 assert (t != NULL);
737 n = ffename_lookup (ffesymbol_local_, t);
738 if (n != NULL)
739 return ffename_symbol (n); /* This will become an error. */
741 n = ffename_find (ffesymbol_global_, t);
742 s = ffename_symbol (n);
743 if (s != NULL)
745 ffesymbol_check (s, t, FALSE);
746 return s;
749 s = ffesymbol_new_ (n);
750 ffesymbol_check (s, t, FALSE);
752 /* A program unit name also is in the local name space. */
754 n = ffename_find (ffesymbol_local_, t);
755 ffename_set_symbol (n, s);
756 s->other_space_name = n;
758 ffeglobal_new_subroutine (s, t); /* Detect conflicts, when
759 appropriate. */
761 return s;
764 /* Call given fn with all local/global symbols.
766 ffesymbol (*fn) (ffesymbol s);
767 ffesymbol_drive (fn); */
769 void
770 ffesymbol_drive (ffesymbol (*fn) (ffesymbol))
772 assert (ffesymbol_sfunc_ == NULL); /* Might be ok, but not for current
773 uses. */
774 ffename_space_drive_symbol (ffesymbol_local_, fn);
775 ffename_space_drive_symbol (ffesymbol_global_, fn);
778 /* Call given fn with all sfunc-only symbols.
780 ffesymbol (*fn) (ffesymbol s);
781 ffesymbol_drive_sfnames (fn); */
783 void
784 ffesymbol_drive_sfnames (ffesymbol (*fn) (ffesymbol))
786 ffename_space_drive_symbol (ffesymbol_sfunc_, fn);
789 /* Produce generic error message about a symbol.
791 For now, just output error message using symbol's name and pointing to
792 the token. */
794 void
795 ffesymbol_error (ffesymbol s, ffelexToken t)
797 if ((t != NULL)
798 && ffest_ffebad_start (FFEBAD_SYMERR))
800 ffebad_string (ffesymbol_text (s));
801 ffebad_here (0, ffelex_token_where_line (t),
802 ffelex_token_where_column (t));
803 ffebad_here (1, ffesymbol_where_line (s), ffesymbol_where_column (s));
804 ffebad_finish ();
807 if (ffesymbol_attr (s, FFESYMBOL_attrANY))
808 return;
810 ffesymbol_signal_change (s); /* May need to back up to previous version. */
811 if ((ffesymbol_attrs (s) & FFESYMBOL_attrsCBLOCK)
812 || (ffesymbol_kind (s) == FFEINFO_kindNAMELIST))
813 ffebld_end_list (ffesymbol_ptr_to_listbottom (s));
814 ffesymbol_set_attr (s, FFESYMBOL_attrANY);
815 ffesymbol_set_info (s, ffeinfo_new_any ());
816 ffesymbol_set_state (s, FFESYMBOL_stateUNDERSTOOD);
817 if (s->check_state == FFESYMBOL_checkstatePENDING_)
818 ffelex_token_kill (s->check_token);
819 s->check_state = FFESYMBOL_checkstateCHECKED_;
820 s = ffecom_sym_learned (s);
821 ffesymbol_signal_unreported (s);
824 void
825 ffesymbol_init_0 ()
827 ffesymbolAttrs attrs = FFESYMBOL_attrsetNONE;
829 assert (FFESYMBOL_state == ARRAY_SIZE (ffesymbol_state_name_));
830 assert (FFESYMBOL_attr == ARRAY_SIZE (ffesymbol_attr_name_));
831 assert (attrs == FFESYMBOL_attrsetNONE);
832 attrs = ((ffesymbolAttrs) 1 << FFESYMBOL_attr);
833 assert (attrs != 0);
836 void
837 ffesymbol_init_1 ()
839 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalFILE_
840 ffesymbol_global_ = ffename_space_new (ffe_pool_file ());
841 #endif
844 void
845 ffesymbol_init_2 ()
849 void
850 ffesymbol_init_3 ()
852 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalPROGUNIT_
853 ffesymbol_global_ = ffename_space_new (ffe_pool_program_unit ());
854 #endif
855 ffesymbol_local_ = ffename_space_new (ffe_pool_program_unit ());
858 void
859 ffesymbol_init_4 ()
861 ffesymbol_sfunc_ = ffename_space_new (ffe_pool_program_unit ());
864 /* Look up a local entity.
866 Retrieves the ffesymbol for the specified local entity, or returns NULL
867 if no local entity by that name exists. */
869 ffesymbol
870 ffesymbol_lookup_local (ffelexToken t)
872 ffename n;
873 ffesymbol s;
875 assert (t != NULL);
877 n = ffename_lookup (ffesymbol_local_, t);
878 if (n == NULL)
879 return NULL;
881 s = ffename_symbol (n);
882 return s; /* May be NULL here, too. */
885 /* Registers the symbol as one that is referenced by the
886 current program unit. Currently applies only to
887 symbols known to have global interest (globals and
888 intrinsics).
890 s is the (global/intrinsic) symbol referenced; t is the
891 referencing token; explicit is TRUE if the reference
892 is, e.g., INTRINSIC FOO. */
894 void
895 ffesymbol_reference (ffesymbol s, ffelexToken t, bool explicit)
897 ffename gn;
898 ffesymbol gs = NULL;
899 ffeinfoKind kind;
900 ffeinfoWhere where;
901 bool okay;
903 if (ffesymbol_retractable_)
904 return;
906 if (t == NULL)
907 t = ffename_token (s->name); /* Use the first reference in this program unit. */
909 kind = ffesymbol_kind (s);
910 where = ffesymbol_where (s);
912 if (where == FFEINFO_whereINTRINSIC)
914 ffeglobal_ref_intrinsic (s, t,
915 explicit
916 || s->explicit_where
917 || ffeintrin_is_standard (s->generic, s->specific));
918 return;
921 if ((where != FFEINFO_whereGLOBAL)
922 && ((where != FFEINFO_whereLOCAL)
923 || ((kind != FFEINFO_kindFUNCTION)
924 && (kind != FFEINFO_kindSUBROUTINE))))
925 return;
927 gn = ffename_lookup (ffesymbol_global_, t);
928 if (gn != NULL)
929 gs = ffename_symbol (gn);
930 if ((gs != NULL) && (gs != s))
932 /* We have just discovered another global symbol with the same name
933 but a different `nature'. Complain. Note that COMMON /FOO/ can
934 coexist with local symbol FOO, e.g. local variable, just not with
935 CALL FOO, hence the separate namespaces. */
937 ffesymbol_error (gs, t);
938 ffesymbol_error (s, NULL);
939 return;
942 switch (kind)
944 case FFEINFO_kindBLOCKDATA:
945 okay = ffeglobal_ref_blockdata (s, t);
946 break;
948 case FFEINFO_kindSUBROUTINE:
949 okay = ffeglobal_ref_subroutine (s, t);
950 break;
952 case FFEINFO_kindFUNCTION:
953 okay = ffeglobal_ref_function (s, t);
954 break;
956 case FFEINFO_kindNONE:
957 okay = ffeglobal_ref_external (s, t);
958 break;
960 default:
961 assert ("bad kind in global ref" == NULL);
962 return;
965 if (! okay)
966 ffesymbol_error (s, NULL);
969 /* Resolve symbol that has become known intrinsic or non-intrinsic. */
971 void
972 ffesymbol_resolve_intrin (ffesymbol s)
974 char c;
975 ffebad bad;
977 if (!ffesrc_check_symbol ())
978 return;
979 if (s->check_state != FFESYMBOL_checkstatePENDING_)
980 return;
981 if (ffebad_inhibit ())
982 return; /* We'll get back to this later. */
984 if (ffesymbol_where (s) != FFEINFO_whereINTRINSIC)
986 bad = ffesymbol_check_token_ (s->check_token, &c);
987 assert (bad != FFEBAD); /* How did this suddenly become ok? */
988 ffesymbol_whine_state_ (bad, s->check_token, c);
991 s->check_state = FFESYMBOL_checkstateCHECKED_;
992 ffelex_token_kill (s->check_token);
995 /* Retract or cancel retract list. */
997 void
998 ffesymbol_retract (bool retract)
1000 ffesymbolRetract_ r;
1001 ffename name;
1002 ffename other_space_name;
1003 ffesymbol ls;
1004 ffesymbol os;
1006 assert (ffesymbol_retractable_);
1008 ffesymbol_retractable_ = FALSE;
1010 for (r = ffesymbol_retract_first_; r != NULL; r = r->next)
1012 ls = r->live;
1013 os = r->symbol;
1014 switch (r->command)
1016 case FFESYMBOL_retractcommandDELETE_:
1017 if (retract)
1019 ffecom_sym_retract (ls);
1020 name = ls->name;
1021 other_space_name = ls->other_space_name;
1022 ffesymbol_unhook_ (ls);
1023 malloc_kill_ks (FFESYMBOL_SPACE_POOL_, ls, sizeof (*ls));
1024 if (name != NULL)
1025 ffename_set_symbol (name, NULL);
1026 if (other_space_name != NULL)
1027 ffename_set_symbol (other_space_name, NULL);
1029 else
1031 ffecom_sym_commit (ls);
1032 ls->have_old = FALSE;
1034 break;
1036 case FFESYMBOL_retractcommandRETRACT_:
1037 if (retract)
1039 ffecom_sym_retract (ls);
1040 ffesymbol_unhook_ (ls);
1041 *ls = *os;
1042 malloc_kill_ks (FFESYMBOL_SPACE_POOL_, os, sizeof (*os));
1044 else
1046 ffecom_sym_commit (ls);
1047 ffesymbol_unhook_ (os);
1048 malloc_kill_ks (FFESYMBOL_SPACE_POOL_, os, sizeof (*os));
1049 ls->have_old = FALSE;
1051 break;
1053 default:
1054 assert ("bad command" == NULL);
1055 break;
1060 /* Return retractable flag. */
1062 bool
1063 ffesymbol_retractable ()
1065 return ffesymbol_retractable_;
1068 /* Set retractable flag, retract pool.
1070 Between this call and ffesymbol_retract, any changes made to existing
1071 symbols cause the previous versions of those symbols to be saved, and any
1072 newly created symbols to have their previous nonexistence saved. When
1073 ffesymbol_retract is called, this information either is used to retract
1074 the changes and new symbols, or is discarded. */
1076 void
1077 ffesymbol_set_retractable (mallocPool pool)
1079 assert (!ffesymbol_retractable_);
1081 ffesymbol_retractable_ = TRUE;
1082 ffesymbol_retract_pool_ = pool;
1083 ffesymbol_retract_list_ = &ffesymbol_retract_first_;
1084 ffesymbol_retract_first_ = NULL;
1087 /* Existing symbol about to be changed; save?
1089 Call this function before changing a symbol if it is possible that
1090 the current actions may need to be undone (i.e. one of several possible
1091 statement forms are being used to analyze the current system).
1093 If the "retractable" flag is not set, just return.
1094 Else, if the symbol's "have_old" flag is set, just return.
1095 Else, make a copy of the symbol and add it to the "retract" list, set
1096 the "have_old" flag, and return. */
1098 void
1099 ffesymbol_signal_change (ffesymbol s)
1101 ffesymbolRetract_ r;
1102 ffesymbol sym;
1104 if (!ffesymbol_retractable_ || s->have_old)
1105 return;
1107 r = (ffesymbolRetract_) malloc_new_kp (ffesymbol_retract_pool_,
1108 "FFESYMBOL retract", sizeof (*r));
1109 r->next = NULL;
1110 r->command = FFESYMBOL_retractcommandRETRACT_;
1111 r->live = s;
1112 r->symbol = sym = (ffesymbol) malloc_new_ks (FFESYMBOL_SPACE_POOL_,
1113 "FFESYMBOL", sizeof (*sym));
1114 *sym = *s; /* Make an exact copy of the symbol in case
1115 we need it back. */
1116 sym->info = ffeinfo_use (s->info);
1117 if (s->check_state == FFESYMBOL_checkstatePENDING_)
1118 sym->check_token = ffelex_token_use (s->check_token);
1120 *ffesymbol_retract_list_ = r;
1121 ffesymbol_retract_list_ = &r->next;
1123 s->have_old = TRUE;
1126 /* Returns the string based on the state. */
1128 const char *
1129 ffesymbol_state_string (ffesymbolState state)
1131 if (state >= ARRAY_SIZE (ffesymbol_state_name_))
1132 return "?\?\?";
1133 return ffesymbol_state_name_[state];
1136 void
1137 ffesymbol_terminate_0 ()
1141 void
1142 ffesymbol_terminate_1 ()
1144 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalFILE_
1145 ffename_space_drive_symbol (ffesymbol_global_, ffesymbol_unhook_);
1146 ffename_space_kill (ffesymbol_global_);
1147 ffesymbol_global_ = NULL;
1149 ffesymbol_kill_manifest_ ();
1150 #endif
1153 void
1154 ffesymbol_terminate_2 ()
1156 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalPROGUNIT_
1157 ffesymbol_kill_manifest_ ();
1158 #endif
1161 void
1162 ffesymbol_terminate_3 ()
1164 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalPROGUNIT_
1165 ffename_space_drive_symbol (ffesymbol_global_, ffesymbol_unhook_);
1166 ffename_space_kill (ffesymbol_global_);
1167 #endif
1168 ffename_space_drive_symbol (ffesymbol_local_, ffesymbol_unhook_);
1169 ffename_space_kill (ffesymbol_local_);
1170 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalPROGUNIT_
1171 ffesymbol_global_ = NULL;
1172 #endif
1173 ffesymbol_local_ = NULL;
1176 void
1177 ffesymbol_terminate_4 ()
1179 ffename_space_drive_symbol (ffesymbol_sfunc_, ffesymbol_unhook_);
1180 ffename_space_kill (ffesymbol_sfunc_);
1181 ffesymbol_sfunc_ = NULL;
1184 /* Update INIT info to TRUE and all equiv/storage too.
1186 If INIT flag is TRUE, does nothing. Else sets it to TRUE and calls
1187 on the ffeequiv and ffestorag modules to update their INIT flags if
1188 the <s> symbol has those objects, and also updates the common area if
1189 it exists. */
1191 void
1192 ffesymbol_update_init (ffesymbol s)
1194 ffebld item;
1196 if (s->is_init)
1197 return;
1199 s->is_init = TRUE;
1201 if ((s->equiv != NULL)
1202 && !ffeequiv_is_init (s->equiv))
1203 ffeequiv_update_init (s->equiv);
1205 if ((s->storage != NULL)
1206 && !ffestorag_is_init (s->storage))
1207 ffestorag_update_init (s->storage);
1209 if ((s->common != NULL)
1210 && (!ffesymbol_is_init (s->common)))
1211 ffesymbol_update_init (s->common);
1213 for (item = s->common_list; item != NULL; item = ffebld_trail (item))
1215 if (!ffesymbol_is_init (ffebld_symter (ffebld_head (item))))
1216 ffesymbol_update_init (ffebld_symter (ffebld_head (item)));
1220 /* Update SAVE info to TRUE and all equiv/storage too.
1222 If SAVE flag is TRUE, does nothing. Else sets it to TRUE and calls
1223 on the ffeequiv and ffestorag modules to update their SAVE flags if
1224 the <s> symbol has those objects, and also updates the common area if
1225 it exists. */
1227 void
1228 ffesymbol_update_save (ffesymbol s)
1230 ffebld item;
1232 if (s->is_save)
1233 return;
1235 s->is_save = TRUE;
1237 if ((s->equiv != NULL)
1238 && !ffeequiv_is_save (s->equiv))
1239 ffeequiv_update_save (s->equiv);
1241 if ((s->storage != NULL)
1242 && !ffestorag_is_save (s->storage))
1243 ffestorag_update_save (s->storage);
1245 if ((s->common != NULL)
1246 && (!ffesymbol_is_save (s->common)))
1247 ffesymbol_update_save (s->common);
1249 for (item = s->common_list; item != NULL; item = ffebld_trail (item))
1251 if (!ffesymbol_is_save (ffebld_symter (ffebld_head (item))))
1252 ffesymbol_update_save (ffebld_symter (ffebld_head (item)));