xref: /openbsd/gnu/usr.bin/gcc/gcc/f/symbol.c (revision c87b03e5)
1 /* Implementation of Fortran symbol manager
2    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
3    Contributed by James Craig Burley.
4 
5 This file is part of GNU Fortran.
6 
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.
11 
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.
16 
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.  */
21 
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"
38 
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.  */
44 
45 #define FFESYMBOL_globalPROGUNIT_ 1
46 #define FFESYMBOL_globalFILE_ 2
47 
48 /* Choose how to handle global symbols here.  */
49 
50 /* Would be good to understand why PROGUNIT in this case too.
51    (1995-08-22).  */
52 #define FFESYMBOL_globalCURRENT_ FFESYMBOL_globalPROGUNIT_
53 
54 /* Choose how to handle memory pools based on global symbol stuff.  */
55 
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
63 
64 /* What kind of retraction is needed for a symbol?  */
65 
66 enum _ffesymbol_retractcommand_
67   {
68     FFESYMBOL_retractcommandDELETE_,
69     FFESYMBOL_retractcommandRETRACT_,
70     FFESYMBOL_retractcommand_
71   };
72 typedef enum _ffesymbol_retractcommand_ ffesymbolRetractCommand_;
73 
74 /* This object keeps track of retraction for a symbol and links to the next
75    such object.  */
76 
77 typedef struct _ffesymbol_retract_ *ffesymbolRetract_;
78 struct _ffesymbol_retract_
79   {
80     ffesymbolRetract_ next;
81     ffesymbolRetractCommand_ command;
82     ffesymbol live;		/* Live symbol. */
83     ffesymbol symbol;		/* Backup copy of symbol. */
84   };
85 
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);
91 
92 /* Manifest names for unnamed things (as tokens) so we make them only
93    once.  */
94 
95 static ffelexToken ffesymbol_token_blank_common_ = NULL;
96 static ffelexToken ffesymbol_token_unnamed_main_ = NULL;
97 static ffelexToken ffesymbol_token_unnamed_blockdata_ = NULL;
98 
99 /* Name spaces currently in force.  */
100 
101 static ffenameSpace ffesymbol_global_ = NULL;
102 static ffenameSpace ffesymbol_local_ = NULL;
103 static ffenameSpace ffesymbol_sfunc_ = NULL;
104 
105 /* Keep track of retraction.  */
106 
107 static bool ffesymbol_retractable_ = FALSE;
108 static mallocPool ffesymbol_retract_pool_;
109 static ffesymbolRetract_ ffesymbol_retract_first_;
110 static ffesymbolRetract_ *ffesymbol_retract_list_;
111 
112 /* List of state names. */
113 
114 static const char *const ffesymbol_state_name_[] =
115 {
116   "?",
117   "@",
118   "&",
119   "$",
120 };
121 
122 /* List of attribute names. */
123 
124 static const char *const ffesymbol_attr_name_[] =
125 {
126 #define DEFATTR(ATTR,ATTRS,NAME) NAME,
127 #include "symbol.def"
128 #undef DEFATTR
129 };
130 
131 
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.  */
136 
137 static ffebad
ffesymbol_check_token_(ffelexToken t,char * c)138 ffesymbol_check_token_ (ffelexToken t, char *c)
139 {
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;
150 
151   bad = ffesrc_bad_char_symbol_init (*p);
152   if (bad == FFEBAD)
153     {
154       for (++i, ++p; i < len; ++i, ++p)
155 	{
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. */
163 	}
164     }
165 
166   if (bad != FFEBAD)
167     {
168       if (i >= len)
169 	*c = *(ffelex_token_text (t));
170       else
171 	*c = *p;
172     }
173 
174   return bad;
175 }
176 
177 /* Kill manifest (g77-picked) names.  */
178 
179 static void
ffesymbol_kill_manifest_()180 ffesymbol_kill_manifest_ ()
181 {
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_);
188 
189   ffesymbol_token_blank_common_ = NULL;
190   ffesymbol_token_unnamed_main_ = NULL;
191   ffesymbol_token_unnamed_blockdata_ = NULL;
192 }
193 
194 /* Make new symbol.
195 
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.  */
199 
200 static ffesymbol
ffesymbol_new_(ffename n)201 ffesymbol_new_ (ffename n)
202 {
203   ffesymbol s;
204   ffesymbolRetract_ r;
205 
206   assert (n != NULL);
207 
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;
253 
254   ffename_set_symbol (n, s);
255 
256   if (!ffesymbol_retractable_)
257     {
258       s->have_old = FALSE;
259       return s;
260     }
261 
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. */
268 
269   *ffesymbol_retract_list_ = r;
270   ffesymbol_retract_list_ = &r->next;
271 
272   s->have_old = TRUE;
273   return s;
274 }
275 
276 /* Unhook a symbol from its (soon-to-be-killed) name obj.
277 
278    NULLify the names to which this symbol points.  Do other cleanup as
279    needed.  */
280 
281 static ffesymbol
ffesymbol_unhook_(ffesymbol s)282 ffesymbol_unhook_ (ffesymbol s)
283 {
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);
290 
291   return s;
292 }
293 
294 /* Issue diagnostic about bad character in token representing user-defined
295    symbol name.	 */
296 
297 static void
ffesymbol_whine_state_(ffebad bad,ffelexToken t,char c)298 ffesymbol_whine_state_ (ffebad bad, ffelexToken t, char c)
299 {
300   char badstr[2];
301 
302   badstr[0] = c;
303   badstr[1] = '\0';
304 
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 ();
310 }
311 
312 /* Returns a string representing the attributes set.  */
313 
314 const char *
ffesymbol_attrs_string(ffesymbolAttrs attrs)315 ffesymbol_attrs_string (ffesymbolAttrs attrs)
316 {
317   static char string[FFESYMBOL_attr * 12 + 20];
318   char *p;
319   ffesymbolAttr attr;
320 
321   p = &string[0];
322 
323   if (attrs == FFESYMBOL_attrsetNONE)
324     {
325       strcpy (p, "NONE");
326       return &string[0];
327     }
328 
329   for (attr = 0; attr < FFESYMBOL_attr; ++attr)
330     {
331       if (attrs & ((ffesymbolAttrs) 1 << attr))
332 	{
333 	  attrs &= ~((ffesymbolAttrs) 1 << attr);
334 	  strcpy (p, ffesymbol_attr_name_[attr]);
335 	  while (*p)
336 	    ++p;
337 	  *(p++) = '|';
338 	}
339     }
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];
346 }
347 
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.  */
350 
351 void
ffesymbol_check(ffesymbol s,ffelexToken t,bool maybe_intrin)352 ffesymbol_check (ffesymbol s, ffelexToken t, bool maybe_intrin)
353 {
354   char c;
355   ffebad bad;
356   ffeintrinGen gen;
357   ffeintrinSpec spec;
358   ffeintrinImp imp;
359 
360   if (!ffesrc_check_symbol ()
361       || ((s->check_state != FFESYMBOL_checkstateNONE_)
362 	  && ((s->check_state != FFESYMBOL_checkstateINHIBITED_)
363 	      || ffebad_inhibit ())))
364     return;
365 
366   bad = ffesymbol_check_token_ (t, &c);
367 
368   if (bad == FFEBAD)
369     {
370       s->check_state = FFESYMBOL_checkstateCHECKED_;
371       return;
372     }
373 
374   if (maybe_intrin
375       && ffeintrin_is_intrinsic (ffelex_token_text (t), NULL, FALSE,
376 				 &gen, &spec, &imp))
377     {
378       s->check_state = FFESYMBOL_checkstatePENDING_;
379       s->check_token = ffelex_token_use (t);
380       return;
381     }
382 
383   if (ffebad_inhibit ())
384     {
385       s->check_state = FFESYMBOL_checkstateINHIBITED_;
386       return;			/* Don't complain now, do it later. */
387     }
388 
389   s->check_state = FFESYMBOL_checkstateCHECKED_;
390 
391   ffesymbol_whine_state_ (bad, t, c);
392 }
393 
394 /* Declare a BLOCKDATA unit.
395 
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.  */
399 
400 ffesymbol
ffesymbol_declare_blockdataunit(ffelexToken t,ffewhereLine wl,ffewhereColumn wc)401 ffesymbol_declare_blockdataunit (ffelexToken t, ffewhereLine wl,
402 				 ffewhereColumn wc)
403 {
404   ffename n;
405   ffesymbol s;
406   bool user = (t != NULL);
407 
408   assert (!ffesymbol_retractable_);
409 
410   if (t == NULL)
411     {
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_;
416     }
417 
418   n = ffename_lookup (ffesymbol_local_, t);
419   if (n != NULL)
420     return ffename_symbol (n);	/* This will become an error. */
421 
422   n = ffename_find (ffesymbol_global_, t);
423   s = ffename_symbol (n);
424   if (s != NULL)
425     {
426       if (user)
427 	ffesymbol_check (s, t, FALSE);
428       return s;
429     }
430 
431   s = ffesymbol_new_ (n);
432   if (user)
433     ffesymbol_check (s, t, FALSE);
434 
435   /* A program unit name also is in the local name space. */
436 
437   n = ffename_find (ffesymbol_local_, t);
438   ffename_set_symbol (n, s);
439   s->other_space_name = n;
440 
441   ffeglobal_new_blockdata (s, t);	/* Detect conflicts, when
442 					   appropriate. */
443 
444   return s;
445 }
446 
447 /* Declare a common block (named or unnamed).
448 
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.  */
452 
453 ffesymbol
ffesymbol_declare_cblock(ffelexToken t,ffewhereLine wl,ffewhereColumn wc)454 ffesymbol_declare_cblock (ffelexToken t, ffewhereLine wl, ffewhereColumn wc)
455 {
456   ffename n;
457   ffesymbol s;
458   bool blank;
459 
460   assert (!ffesymbol_retractable_);
461 
462   if (t == NULL)
463     {
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_;
469     }
470   else
471     blank = FALSE;
472 
473   n = ffename_find (ffesymbol_global_, t);
474   s = ffename_symbol (n);
475   if (s != NULL)
476     {
477       if (!blank)
478 	ffesymbol_check (s, t, FALSE);
479       return s;
480     }
481 
482   s = ffesymbol_new_ (n);
483   if (!blank)
484     ffesymbol_check (s, t, FALSE);
485 
486   ffeglobal_new_common (s, t, blank);	/* Detect conflicts. */
487 
488   return s;
489 }
490 
491 /* Declare a FUNCTION program unit (with distinct RESULT() name).
492 
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.
496 
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.	*/
500 
501 ffesymbol
ffesymbol_declare_funcnotresunit(ffelexToken t)502 ffesymbol_declare_funcnotresunit (ffelexToken t)
503 {
504   ffename n;
505   ffesymbol s;
506 
507   assert (t != NULL);
508   assert (!ffesymbol_retractable_);
509 
510   n = ffename_lookup (ffesymbol_local_, t);
511   if (n != NULL)
512     return ffename_symbol (n);	/* This will become an error. */
513 
514   n = ffename_find (ffesymbol_global_, t);
515   s = ffename_symbol (n);
516   if (s != NULL)
517     {
518       ffesymbol_check (s, t, FALSE);
519       return s;
520     }
521 
522   s = ffesymbol_new_ (n);
523   ffesymbol_check (s, t, FALSE);
524 
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. */
527 
528   n = ffename_find (ffesymbol_local_, t);
529   ffename_set_symbol (n, s);
530   s->other_space_name = n;
531 
532   ffeglobal_new_function (s, t);/* Detect conflicts, when appropriate. */
533 
534   return s;
535 }
536 
537 /* Declare a function result.
538 
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.  */
542 
543 ffesymbol
ffesymbol_declare_funcresult(ffelexToken t)544 ffesymbol_declare_funcresult (ffelexToken t)
545 {
546   ffename n;
547   ffesymbol s;
548 
549   assert (t != NULL);
550   assert (!ffesymbol_retractable_);
551 
552   n = ffename_find (ffesymbol_local_, t);
553   s = ffename_symbol (n);
554   if (s != NULL)
555     return s;
556 
557   return ffesymbol_new_ (n);
558 }
559 
560 /* Declare a FUNCTION program unit with no RESULT().
561 
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.
565 
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.  */
571 
572 ffesymbol
ffesymbol_declare_funcunit(ffelexToken t)573 ffesymbol_declare_funcunit (ffelexToken t)
574 {
575   ffename n;
576   ffesymbol s;
577 
578   assert (t != NULL);
579   assert (!ffesymbol_retractable_);
580 
581   n = ffename_find (ffesymbol_global_, t);
582   s = ffename_symbol (n);
583   if (s != NULL)
584     {
585       ffesymbol_check (s, t, FALSE);
586       return s;
587     }
588 
589   s = ffesymbol_new_ (n);
590   ffesymbol_check (s, t, FALSE);
591 
592   ffeglobal_new_function (s, t);/* Detect conflicts. */
593 
594   return s;
595 }
596 
597 /* Declare a local entity.
598 
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.  */
605 
606 ffesymbol
ffesymbol_declare_local(ffelexToken t,bool maybe_intrin)607 ffesymbol_declare_local (ffelexToken t, bool maybe_intrin)
608 {
609   ffename n;
610   ffesymbol s;
611 
612   assert (t != NULL);
613 
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.  */
619 
620   if ((ffesymbol_sfunc_ != NULL)
621       && ((n = ffename_lookup (ffesymbol_sfunc_, t)) != NULL))
622     return ffename_symbol (n);
623 
624   n = ffename_find (ffesymbol_local_, t);
625   s = ffename_symbol (n);
626   if (s != NULL)
627     {
628       ffesymbol_check (s, t, maybe_intrin);
629       return s;
630     }
631 
632   s = ffesymbol_new_ (n);
633   ffesymbol_check (s, t, maybe_intrin);
634   return s;
635 }
636 
637 /* Declare a main program unit.
638 
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.  */
642 
643 ffesymbol
ffesymbol_declare_programunit(ffelexToken t,ffewhereLine wl,ffewhereColumn wc)644 ffesymbol_declare_programunit (ffelexToken t, ffewhereLine wl,
645 			       ffewhereColumn wc)
646 {
647   ffename n;
648   ffesymbol s;
649   bool user = (t != NULL);
650 
651   assert (!ffesymbol_retractable_);
652 
653   if (t == NULL)
654     {
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_;
659     }
660 
661   n = ffename_lookup (ffesymbol_local_, t);
662   if (n != NULL)
663     return ffename_symbol (n);	/* This will become an error. */
664 
665   n = ffename_find (ffesymbol_global_, t);
666   s = ffename_symbol (n);
667   if (s != NULL)
668     {
669       if (user)
670 	ffesymbol_check (s, t, FALSE);
671       return s;
672     }
673 
674   s = ffesymbol_new_ (n);
675   if (user)
676     ffesymbol_check (s, t, FALSE);
677 
678   /* A program unit name also is in the local name space. */
679 
680   n = ffename_find (ffesymbol_local_, t);
681   ffename_set_symbol (n, s);
682   s->other_space_name = n;
683 
684   ffeglobal_new_program (s, t);	/* Detect conflicts. */
685 
686   return s;
687 }
688 
689 /* Declare a statement-function dummy.
690 
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.  */
694 
695 ffesymbol
ffesymbol_declare_sfdummy(ffelexToken t)696 ffesymbol_declare_sfdummy (ffelexToken t)
697 {
698   ffename n;
699   ffesymbol s;
700   ffesymbol sp;			/* Parent symbol in local area. */
701 
702   assert (t != NULL);
703 
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);
709 
710   n = ffename_find (ffesymbol_sfunc_, t);
711   s = ffename_symbol (n);
712   if (s == NULL)
713     {
714       s = ffesymbol_new_ (n);
715       s->sfa_dummy_parent = sp;
716     }
717   else
718     assert (s->sfa_dummy_parent == sp);
719 
720   return s;
721 }
722 
723 /* Declare a subroutine program unit.
724 
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.  */
728 
729 ffesymbol
ffesymbol_declare_subrunit(ffelexToken t)730 ffesymbol_declare_subrunit (ffelexToken t)
731 {
732   ffename n;
733   ffesymbol s;
734 
735   assert (!ffesymbol_retractable_);
736   assert (t != NULL);
737 
738   n = ffename_lookup (ffesymbol_local_, t);
739   if (n != NULL)
740     return ffename_symbol (n);	/* This will become an error. */
741 
742   n = ffename_find (ffesymbol_global_, t);
743   s = ffename_symbol (n);
744   if (s != NULL)
745     {
746       ffesymbol_check (s, t, FALSE);
747       return s;
748     }
749 
750   s = ffesymbol_new_ (n);
751   ffesymbol_check (s, t, FALSE);
752 
753   /* A program unit name also is in the local name space. */
754 
755   n = ffename_find (ffesymbol_local_, t);
756   ffename_set_symbol (n, s);
757   s->other_space_name = n;
758 
759   ffeglobal_new_subroutine (s, t);	/* Detect conflicts, when
760 					   appropriate. */
761 
762   return s;
763 }
764 
765 /* Call given fn with all local/global symbols.
766 
767    ffesymbol (*fn) (ffesymbol s);
768    ffesymbol_drive (fn);  */
769 
770 void
ffesymbol_drive(ffesymbol (* fn)(ffesymbol))771 ffesymbol_drive (ffesymbol (*fn) (ffesymbol))
772 {
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);
777 }
778 
779 /* Call given fn with all sfunc-only symbols.
780 
781    ffesymbol (*fn) (ffesymbol s);
782    ffesymbol_drive_sfnames (fn);  */
783 
784 void
ffesymbol_drive_sfnames(ffesymbol (* fn)(ffesymbol))785 ffesymbol_drive_sfnames (ffesymbol (*fn) (ffesymbol))
786 {
787   ffename_space_drive_symbol (ffesymbol_sfunc_, fn);
788 }
789 
790 /* Produce generic error message about a symbol.
791 
792    For now, just output error message using symbol's name and pointing to
793    the token.  */
794 
795 void
ffesymbol_error(ffesymbol s,ffelexToken t)796 ffesymbol_error (ffesymbol s, ffelexToken t)
797 {
798   if ((t != NULL)
799       && ffest_ffebad_start (FFEBAD_SYMERR))
800     {
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 ();
806     }
807 
808   if (ffesymbol_attr (s, FFESYMBOL_attrANY))
809     return;
810 
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);
823 }
824 
825 void
ffesymbol_init_0()826 ffesymbol_init_0 ()
827 {
828   ffesymbolAttrs attrs = FFESYMBOL_attrsetNONE;
829 
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);
835 }
836 
837 void
ffesymbol_init_1()838 ffesymbol_init_1 ()
839 {
840 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalFILE_
841   ffesymbol_global_ = ffename_space_new (ffe_pool_file ());
842 #endif
843 }
844 
845 void
ffesymbol_init_2()846 ffesymbol_init_2 ()
847 {
848 }
849 
850 void
ffesymbol_init_3()851 ffesymbol_init_3 ()
852 {
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 ());
857 }
858 
859 void
ffesymbol_init_4()860 ffesymbol_init_4 ()
861 {
862   ffesymbol_sfunc_ = ffename_space_new (ffe_pool_program_unit ());
863 }
864 
865 /* Look up a local entity.
866 
867    Retrieves the ffesymbol for the specified local entity, or returns NULL
868    if no local entity by that name exists.  */
869 
870 ffesymbol
ffesymbol_lookup_local(ffelexToken t)871 ffesymbol_lookup_local (ffelexToken t)
872 {
873   ffename n;
874   ffesymbol s;
875 
876   assert (t != NULL);
877 
878   n = ffename_lookup (ffesymbol_local_, t);
879   if (n == NULL)
880     return NULL;
881 
882   s = ffename_symbol (n);
883   return s;			/* May be NULL here, too. */
884 }
885 
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).
890 
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.  */
894 
895 void
ffesymbol_reference(ffesymbol s,ffelexToken t,bool explicit)896 ffesymbol_reference (ffesymbol s, ffelexToken t, bool explicit)
897 {
898   ffename gn;
899   ffesymbol gs = NULL;
900   ffeinfoKind kind;
901   ffeinfoWhere where;
902   bool okay;
903 
904   if (ffesymbol_retractable_)
905     return;
906 
907   if (t == NULL)
908     t = ffename_token (s->name);	/* Use the first reference in this program unit. */
909 
910   kind = ffesymbol_kind (s);
911   where = ffesymbol_where (s);
912 
913   if (where == FFEINFO_whereINTRINSIC)
914     {
915       ffeglobal_ref_intrinsic (s, t,
916 			       explicit
917 			       || s->explicit_where
918 			       || ffeintrin_is_standard (s->generic, s->specific));
919       return;
920     }
921 
922   if ((where != FFEINFO_whereGLOBAL)
923       && ((where != FFEINFO_whereLOCAL)
924 	  || ((kind != FFEINFO_kindFUNCTION)
925 	      && (kind != FFEINFO_kindSUBROUTINE))))
926     return;
927 
928   gn = ffename_lookup (ffesymbol_global_, t);
929   if (gn != NULL)
930     gs = ffename_symbol (gn);
931   if ((gs != NULL) && (gs != s))
932     {
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.  */
937 
938       ffesymbol_error (gs, t);
939       ffesymbol_error (s, NULL);
940       return;
941     }
942 
943   switch (kind)
944     {
945     case FFEINFO_kindBLOCKDATA:
946       okay = ffeglobal_ref_blockdata (s, t);
947       break;
948 
949     case FFEINFO_kindSUBROUTINE:
950       okay = ffeglobal_ref_subroutine (s, t);
951       break;
952 
953     case FFEINFO_kindFUNCTION:
954       okay = ffeglobal_ref_function (s, t);
955       break;
956 
957     case FFEINFO_kindNONE:
958       okay = ffeglobal_ref_external (s, t);
959       break;
960 
961     default:
962       assert ("bad kind in global ref" == NULL);
963       return;
964     }
965 
966   if (! okay)
967     ffesymbol_error (s, NULL);
968 }
969 
970 /* Resolve symbol that has become known intrinsic or non-intrinsic.  */
971 
972 void
ffesymbol_resolve_intrin(ffesymbol s)973 ffesymbol_resolve_intrin (ffesymbol s)
974 {
975   char c;
976   ffebad bad;
977 
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. */
984 
985   if (ffesymbol_where (s) != FFEINFO_whereINTRINSIC)
986     {
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);
990     }
991 
992   s->check_state = FFESYMBOL_checkstateCHECKED_;
993   ffelex_token_kill (s->check_token);
994 }
995 
996 /* Retract or cancel retract list.  */
997 
998 void
ffesymbol_retract(bool retract)999 ffesymbol_retract (bool retract)
1000 {
1001   ffesymbolRetract_ r;
1002   ffename name;
1003   ffename other_space_name;
1004   ffesymbol ls;
1005   ffesymbol os;
1006 
1007   assert (ffesymbol_retractable_);
1008 
1009   ffesymbol_retractable_ = FALSE;
1010 
1011   for (r = ffesymbol_retract_first_; r != NULL; r = r->next)
1012     {
1013       ls = r->live;
1014       os = r->symbol;
1015       switch (r->command)
1016 	{
1017 	case FFESYMBOL_retractcommandDELETE_:
1018 	  if (retract)
1019 	    {
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);
1029 	    }
1030 	  else
1031 	    {
1032 	      ffecom_sym_commit (ls);
1033 	      ls->have_old = FALSE;
1034 	    }
1035 	  break;
1036 
1037 	case FFESYMBOL_retractcommandRETRACT_:
1038 	  if (retract)
1039 	    {
1040 	      ffecom_sym_retract (ls);
1041 	      ffesymbol_unhook_ (ls);
1042 	      *ls = *os;
1043 	      malloc_kill_ks (FFESYMBOL_SPACE_POOL_, os, sizeof (*os));
1044 	    }
1045 	  else
1046 	    {
1047 	      ffecom_sym_commit (ls);
1048 	      ffesymbol_unhook_ (os);
1049 	      malloc_kill_ks (FFESYMBOL_SPACE_POOL_, os, sizeof (*os));
1050 	      ls->have_old = FALSE;
1051 	    }
1052 	  break;
1053 
1054 	default:
1055 	  assert ("bad command" == NULL);
1056 	  break;
1057 	}
1058     }
1059 }
1060 
1061 /* Return retractable flag.  */
1062 
1063 bool
ffesymbol_retractable()1064 ffesymbol_retractable ()
1065 {
1066   return ffesymbol_retractable_;
1067 }
1068 
1069 /* Set retractable flag, retract pool.
1070 
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.  */
1076 
1077 void
ffesymbol_set_retractable(mallocPool pool)1078 ffesymbol_set_retractable (mallocPool pool)
1079 {
1080   assert (!ffesymbol_retractable_);
1081 
1082   ffesymbol_retractable_ = TRUE;
1083   ffesymbol_retract_pool_ = pool;
1084   ffesymbol_retract_list_ = &ffesymbol_retract_first_;
1085   ffesymbol_retract_first_ = NULL;
1086 }
1087 
1088 /* Existing symbol about to be changed; save?
1089 
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).
1093 
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.  */
1098 
1099 void
ffesymbol_signal_change(ffesymbol s)1100 ffesymbol_signal_change (ffesymbol s)
1101 {
1102   ffesymbolRetract_ r;
1103   ffesymbol sym;
1104 
1105   if (!ffesymbol_retractable_ || s->have_old)
1106     return;
1107 
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);
1120 
1121   *ffesymbol_retract_list_ = r;
1122   ffesymbol_retract_list_ = &r->next;
1123 
1124   s->have_old = TRUE;
1125 }
1126 
1127 /* Returns the string based on the state.  */
1128 
1129 const char *
ffesymbol_state_string(ffesymbolState state)1130 ffesymbol_state_string (ffesymbolState state)
1131 {
1132   if (state >= ARRAY_SIZE (ffesymbol_state_name_))
1133     return "?\?\?";
1134   return ffesymbol_state_name_[state];
1135 }
1136 
1137 void
ffesymbol_terminate_0()1138 ffesymbol_terminate_0 ()
1139 {
1140 }
1141 
1142 void
ffesymbol_terminate_1()1143 ffesymbol_terminate_1 ()
1144 {
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;
1149 
1150   ffesymbol_kill_manifest_ ();
1151 #endif
1152 }
1153 
1154 void
ffesymbol_terminate_2()1155 ffesymbol_terminate_2 ()
1156 {
1157 #if FFESYMBOL_globalCURRENT_ == FFESYMBOL_globalPROGUNIT_
1158   ffesymbol_kill_manifest_ ();
1159 #endif
1160 }
1161 
1162 void
ffesymbol_terminate_3()1163 ffesymbol_terminate_3 ()
1164 {
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;
1175 }
1176 
1177 void
ffesymbol_terminate_4()1178 ffesymbol_terminate_4 ()
1179 {
1180   ffename_space_drive_symbol (ffesymbol_sfunc_, ffesymbol_unhook_);
1181   ffename_space_kill (ffesymbol_sfunc_);
1182   ffesymbol_sfunc_ = NULL;
1183 }
1184 
1185 /* Update INIT info to TRUE and all equiv/storage too.
1186 
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.  */
1191 
1192 void
ffesymbol_update_init(ffesymbol s)1193 ffesymbol_update_init (ffesymbol s)
1194 {
1195   ffebld item;
1196 
1197   if (s->is_init)
1198     return;
1199 
1200   s->is_init = TRUE;
1201 
1202   if ((s->equiv != NULL)
1203       && !ffeequiv_is_init (s->equiv))
1204     ffeequiv_update_init (s->equiv);
1205 
1206   if ((s->storage != NULL)
1207       && !ffestorag_is_init (s->storage))
1208     ffestorag_update_init (s->storage);
1209 
1210   if ((s->common != NULL)
1211       && (!ffesymbol_is_init (s->common)))
1212     ffesymbol_update_init (s->common);
1213 
1214   for (item = s->common_list; item != NULL; item = ffebld_trail (item))
1215     {
1216       if (!ffesymbol_is_init (ffebld_symter (ffebld_head (item))))
1217 	ffesymbol_update_init (ffebld_symter (ffebld_head (item)));
1218     }
1219 }
1220 
1221 /* Update SAVE info to TRUE and all equiv/storage too.
1222 
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.  */
1227 
1228 void
ffesymbol_update_save(ffesymbol s)1229 ffesymbol_update_save (ffesymbol s)
1230 {
1231   ffebld item;
1232 
1233   if (s->is_save)
1234     return;
1235 
1236   s->is_save = TRUE;
1237 
1238   if ((s->equiv != NULL)
1239       && !ffeequiv_is_save (s->equiv))
1240     ffeequiv_update_save (s->equiv);
1241 
1242   if ((s->storage != NULL)
1243       && !ffestorag_is_save (s->storage))
1244     ffestorag_update_save (s->storage);
1245 
1246   if ((s->common != NULL)
1247       && (!ffesymbol_is_save (s->common)))
1248     ffesymbol_update_save (s->common);
1249 
1250   for (item = s->common_list; item != NULL; item = ffebld_trail (item))
1251     {
1252       if (!ffesymbol_is_save (ffebld_symter (ffebld_head (item))))
1253 	ffesymbol_update_save (ffebld_symter (ffebld_head (item)));
1254     }
1255 }
1256