xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/fortran/module.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1627f7eb2Smrg /* Handle modules, which amounts to loading and saving symbols and
2627f7eb2Smrg    their attendant structures.
3*4c3eb207Smrg    Copyright (C) 2000-2020 Free Software Foundation, Inc.
4627f7eb2Smrg    Contributed by Andy Vaught
5627f7eb2Smrg 
6627f7eb2Smrg This file is part of GCC.
7627f7eb2Smrg 
8627f7eb2Smrg GCC is free software; you can redistribute it and/or modify it under
9627f7eb2Smrg the terms of the GNU General Public License as published by the Free
10627f7eb2Smrg Software Foundation; either version 3, or (at your option) any later
11627f7eb2Smrg version.
12627f7eb2Smrg 
13627f7eb2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14627f7eb2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
15627f7eb2Smrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16627f7eb2Smrg for more details.
17627f7eb2Smrg 
18627f7eb2Smrg You should have received a copy of the GNU General Public License
19627f7eb2Smrg along with GCC; see the file COPYING3.  If not see
20627f7eb2Smrg <http://www.gnu.org/licenses/>.  */
21627f7eb2Smrg 
22627f7eb2Smrg /* The syntax of gfortran modules resembles that of lisp lists, i.e. a
23627f7eb2Smrg    sequence of atoms, which can be left or right parenthesis, names,
24627f7eb2Smrg    integers or strings.  Parenthesis are always matched which allows
25627f7eb2Smrg    us to skip over sections at high speed without having to know
26627f7eb2Smrg    anything about the internal structure of the lists.  A "name" is
27627f7eb2Smrg    usually a fortran 95 identifier, but can also start with '@' in
28627f7eb2Smrg    order to reference a hidden symbol.
29627f7eb2Smrg 
30627f7eb2Smrg    The first line of a module is an informational message about what
31627f7eb2Smrg    created the module, the file it came from and when it was created.
32627f7eb2Smrg    The second line is a warning for people not to edit the module.
33627f7eb2Smrg    The rest of the module looks like:
34627f7eb2Smrg 
35627f7eb2Smrg    ( ( <Interface info for UPLUS> )
36627f7eb2Smrg      ( <Interface info for UMINUS> )
37627f7eb2Smrg      ...
38627f7eb2Smrg    )
39627f7eb2Smrg    ( ( <name of operator interface> <module of op interface> <i/f1> ... )
40627f7eb2Smrg      ...
41627f7eb2Smrg    )
42627f7eb2Smrg    ( ( <name of generic interface> <module of generic interface> <i/f1> ... )
43627f7eb2Smrg      ...
44627f7eb2Smrg    )
45627f7eb2Smrg    ( ( <common name> <symbol> <saved flag>)
46627f7eb2Smrg      ...
47627f7eb2Smrg    )
48627f7eb2Smrg 
49627f7eb2Smrg    ( equivalence list )
50627f7eb2Smrg 
51627f7eb2Smrg    ( <Symbol Number (in no particular order)>
52627f7eb2Smrg      <True name of symbol>
53627f7eb2Smrg      <Module name of symbol>
54627f7eb2Smrg      ( <symbol information> )
55627f7eb2Smrg      ...
56627f7eb2Smrg    )
57627f7eb2Smrg    ( <Symtree name>
58627f7eb2Smrg      <Ambiguous flag>
59627f7eb2Smrg      <Symbol number>
60627f7eb2Smrg      ...
61627f7eb2Smrg    )
62627f7eb2Smrg 
63627f7eb2Smrg    In general, symbols refer to other symbols by their symbol number,
64627f7eb2Smrg    which are zero based.  Symbols are written to the module in no
65627f7eb2Smrg    particular order.  */
66627f7eb2Smrg 
67627f7eb2Smrg #include "config.h"
68627f7eb2Smrg #include "system.h"
69627f7eb2Smrg #include "coretypes.h"
70627f7eb2Smrg #include "options.h"
71627f7eb2Smrg #include "tree.h"
72627f7eb2Smrg #include "gfortran.h"
73627f7eb2Smrg #include "stringpool.h"
74627f7eb2Smrg #include "arith.h"
75627f7eb2Smrg #include "match.h"
76627f7eb2Smrg #include "parse.h" /* FIXME */
77627f7eb2Smrg #include "constructor.h"
78627f7eb2Smrg #include "cpp.h"
79627f7eb2Smrg #include "scanner.h"
80627f7eb2Smrg #include <zlib.h>
81627f7eb2Smrg 
82627f7eb2Smrg #define MODULE_EXTENSION ".mod"
83627f7eb2Smrg #define SUBMODULE_EXTENSION ".smod"
84627f7eb2Smrg 
85627f7eb2Smrg /* Don't put any single quote (') in MOD_VERSION, if you want it to be
86627f7eb2Smrg    recognized.  */
87627f7eb2Smrg #define MOD_VERSION "15"
88627f7eb2Smrg 
89627f7eb2Smrg 
90627f7eb2Smrg /* Structure that describes a position within a module file.  */
91627f7eb2Smrg 
92627f7eb2Smrg typedef struct
93627f7eb2Smrg {
94627f7eb2Smrg   int column, line;
95627f7eb2Smrg   long pos;
96627f7eb2Smrg }
97627f7eb2Smrg module_locus;
98627f7eb2Smrg 
99627f7eb2Smrg /* Structure for list of symbols of intrinsic modules.  */
100627f7eb2Smrg typedef struct
101627f7eb2Smrg {
102627f7eb2Smrg   int id;
103627f7eb2Smrg   const char *name;
104627f7eb2Smrg   int value;
105627f7eb2Smrg   int standard;
106627f7eb2Smrg }
107627f7eb2Smrg intmod_sym;
108627f7eb2Smrg 
109627f7eb2Smrg 
110627f7eb2Smrg typedef enum
111627f7eb2Smrg {
112627f7eb2Smrg   P_UNKNOWN = 0, P_OTHER, P_NAMESPACE, P_COMPONENT, P_SYMBOL
113627f7eb2Smrg }
114627f7eb2Smrg pointer_t;
115627f7eb2Smrg 
116627f7eb2Smrg /* The fixup structure lists pointers to pointers that have to
117627f7eb2Smrg    be updated when a pointer value becomes known.  */
118627f7eb2Smrg 
119627f7eb2Smrg typedef struct fixup_t
120627f7eb2Smrg {
121627f7eb2Smrg   void **pointer;
122627f7eb2Smrg   struct fixup_t *next;
123627f7eb2Smrg }
124627f7eb2Smrg fixup_t;
125627f7eb2Smrg 
126627f7eb2Smrg 
127627f7eb2Smrg /* Structure for holding extra info needed for pointers being read.  */
128627f7eb2Smrg 
129627f7eb2Smrg enum gfc_rsym_state
130627f7eb2Smrg {
131627f7eb2Smrg   UNUSED,
132627f7eb2Smrg   NEEDED,
133627f7eb2Smrg   USED
134627f7eb2Smrg };
135627f7eb2Smrg 
136627f7eb2Smrg enum gfc_wsym_state
137627f7eb2Smrg {
138627f7eb2Smrg   UNREFERENCED = 0,
139627f7eb2Smrg   NEEDS_WRITE,
140627f7eb2Smrg   WRITTEN
141627f7eb2Smrg };
142627f7eb2Smrg 
143627f7eb2Smrg typedef struct pointer_info
144627f7eb2Smrg {
145627f7eb2Smrg   BBT_HEADER (pointer_info);
146627f7eb2Smrg   HOST_WIDE_INT integer;
147627f7eb2Smrg   pointer_t type;
148627f7eb2Smrg 
149627f7eb2Smrg   /* The first component of each member of the union is the pointer
150627f7eb2Smrg      being stored.  */
151627f7eb2Smrg 
152627f7eb2Smrg   fixup_t *fixup;
153627f7eb2Smrg 
154627f7eb2Smrg   union
155627f7eb2Smrg   {
156627f7eb2Smrg     void *pointer;	/* Member for doing pointer searches.  */
157627f7eb2Smrg 
158627f7eb2Smrg     struct
159627f7eb2Smrg     {
160627f7eb2Smrg       gfc_symbol *sym;
161627f7eb2Smrg       char *true_name, *module, *binding_label;
162627f7eb2Smrg       fixup_t *stfixup;
163627f7eb2Smrg       gfc_symtree *symtree;
164627f7eb2Smrg       enum gfc_rsym_state state;
165627f7eb2Smrg       int ns, referenced, renamed;
166627f7eb2Smrg       module_locus where;
167627f7eb2Smrg     }
168627f7eb2Smrg     rsym;
169627f7eb2Smrg 
170627f7eb2Smrg     struct
171627f7eb2Smrg     {
172627f7eb2Smrg       gfc_symbol *sym;
173627f7eb2Smrg       enum gfc_wsym_state state;
174627f7eb2Smrg     }
175627f7eb2Smrg     wsym;
176627f7eb2Smrg   }
177627f7eb2Smrg   u;
178627f7eb2Smrg 
179627f7eb2Smrg }
180627f7eb2Smrg pointer_info;
181627f7eb2Smrg 
182627f7eb2Smrg #define gfc_get_pointer_info() XCNEW (pointer_info)
183627f7eb2Smrg 
184627f7eb2Smrg 
185627f7eb2Smrg /* Local variables */
186627f7eb2Smrg 
187627f7eb2Smrg /* The gzFile for the module we're reading or writing.  */
188627f7eb2Smrg static gzFile module_fp;
189627f7eb2Smrg 
190*4c3eb207Smrg /* Fully qualified module path */
191*4c3eb207Smrg static char *module_fullpath = NULL;
192627f7eb2Smrg 
193627f7eb2Smrg /* The name of the module we're reading (USE'ing) or writing.  */
194627f7eb2Smrg static const char *module_name;
195627f7eb2Smrg /* The name of the .smod file that the submodule will write to.  */
196627f7eb2Smrg static const char *submodule_name;
197627f7eb2Smrg 
198627f7eb2Smrg static gfc_use_list *module_list;
199627f7eb2Smrg 
200627f7eb2Smrg /* If we're reading an intrinsic module, this is its ID.  */
201627f7eb2Smrg static intmod_id current_intmod;
202627f7eb2Smrg 
203627f7eb2Smrg /* Content of module.  */
204627f7eb2Smrg static char* module_content;
205627f7eb2Smrg 
206627f7eb2Smrg static long module_pos;
207627f7eb2Smrg static int module_line, module_column, only_flag;
208627f7eb2Smrg static int prev_module_line, prev_module_column;
209627f7eb2Smrg 
210627f7eb2Smrg static enum
211627f7eb2Smrg { IO_INPUT, IO_OUTPUT }
212627f7eb2Smrg iomode;
213627f7eb2Smrg 
214627f7eb2Smrg static gfc_use_rename *gfc_rename_list;
215627f7eb2Smrg static pointer_info *pi_root;
216627f7eb2Smrg static int symbol_number;	/* Counter for assigning symbol numbers */
217627f7eb2Smrg 
218627f7eb2Smrg /* Tells mio_expr_ref to make symbols for unused equivalence members.  */
219627f7eb2Smrg static bool in_load_equiv;
220627f7eb2Smrg 
221627f7eb2Smrg 
222627f7eb2Smrg 
223627f7eb2Smrg /*****************************************************************/
224627f7eb2Smrg 
225627f7eb2Smrg /* Pointer/integer conversion.  Pointers between structures are stored
226627f7eb2Smrg    as integers in the module file.  The next couple of subroutines
227627f7eb2Smrg    handle this translation for reading and writing.  */
228627f7eb2Smrg 
229627f7eb2Smrg /* Recursively free the tree of pointer structures.  */
230627f7eb2Smrg 
231627f7eb2Smrg static void
free_pi_tree(pointer_info * p)232627f7eb2Smrg free_pi_tree (pointer_info *p)
233627f7eb2Smrg {
234627f7eb2Smrg   if (p == NULL)
235627f7eb2Smrg     return;
236627f7eb2Smrg 
237627f7eb2Smrg   if (p->fixup != NULL)
238627f7eb2Smrg     gfc_internal_error ("free_pi_tree(): Unresolved fixup");
239627f7eb2Smrg 
240627f7eb2Smrg   free_pi_tree (p->left);
241627f7eb2Smrg   free_pi_tree (p->right);
242627f7eb2Smrg 
243627f7eb2Smrg   if (iomode == IO_INPUT)
244627f7eb2Smrg     {
245627f7eb2Smrg       XDELETEVEC (p->u.rsym.true_name);
246627f7eb2Smrg       XDELETEVEC (p->u.rsym.module);
247627f7eb2Smrg       XDELETEVEC (p->u.rsym.binding_label);
248627f7eb2Smrg     }
249627f7eb2Smrg 
250627f7eb2Smrg   free (p);
251627f7eb2Smrg }
252627f7eb2Smrg 
253627f7eb2Smrg 
254627f7eb2Smrg /* Compare pointers when searching by pointer.  Used when writing a
255627f7eb2Smrg    module.  */
256627f7eb2Smrg 
257627f7eb2Smrg static int
compare_pointers(void * _sn1,void * _sn2)258627f7eb2Smrg compare_pointers (void *_sn1, void *_sn2)
259627f7eb2Smrg {
260627f7eb2Smrg   pointer_info *sn1, *sn2;
261627f7eb2Smrg 
262627f7eb2Smrg   sn1 = (pointer_info *) _sn1;
263627f7eb2Smrg   sn2 = (pointer_info *) _sn2;
264627f7eb2Smrg 
265627f7eb2Smrg   if (sn1->u.pointer < sn2->u.pointer)
266627f7eb2Smrg     return -1;
267627f7eb2Smrg   if (sn1->u.pointer > sn2->u.pointer)
268627f7eb2Smrg     return 1;
269627f7eb2Smrg 
270627f7eb2Smrg   return 0;
271627f7eb2Smrg }
272627f7eb2Smrg 
273627f7eb2Smrg 
274627f7eb2Smrg /* Compare integers when searching by integer.  Used when reading a
275627f7eb2Smrg    module.  */
276627f7eb2Smrg 
277627f7eb2Smrg static int
compare_integers(void * _sn1,void * _sn2)278627f7eb2Smrg compare_integers (void *_sn1, void *_sn2)
279627f7eb2Smrg {
280627f7eb2Smrg   pointer_info *sn1, *sn2;
281627f7eb2Smrg 
282627f7eb2Smrg   sn1 = (pointer_info *) _sn1;
283627f7eb2Smrg   sn2 = (pointer_info *) _sn2;
284627f7eb2Smrg 
285627f7eb2Smrg   if (sn1->integer < sn2->integer)
286627f7eb2Smrg     return -1;
287627f7eb2Smrg   if (sn1->integer > sn2->integer)
288627f7eb2Smrg     return 1;
289627f7eb2Smrg 
290627f7eb2Smrg   return 0;
291627f7eb2Smrg }
292627f7eb2Smrg 
293627f7eb2Smrg 
294627f7eb2Smrg /* Initialize the pointer_info tree.  */
295627f7eb2Smrg 
296627f7eb2Smrg static void
init_pi_tree(void)297627f7eb2Smrg init_pi_tree (void)
298627f7eb2Smrg {
299627f7eb2Smrg   compare_fn compare;
300627f7eb2Smrg   pointer_info *p;
301627f7eb2Smrg 
302627f7eb2Smrg   pi_root = NULL;
303627f7eb2Smrg   compare = (iomode == IO_INPUT) ? compare_integers : compare_pointers;
304627f7eb2Smrg 
305627f7eb2Smrg   /* Pointer 0 is the NULL pointer.  */
306627f7eb2Smrg   p = gfc_get_pointer_info ();
307627f7eb2Smrg   p->u.pointer = NULL;
308627f7eb2Smrg   p->integer = 0;
309627f7eb2Smrg   p->type = P_OTHER;
310627f7eb2Smrg 
311627f7eb2Smrg   gfc_insert_bbt (&pi_root, p, compare);
312627f7eb2Smrg 
313627f7eb2Smrg   /* Pointer 1 is the current namespace.  */
314627f7eb2Smrg   p = gfc_get_pointer_info ();
315627f7eb2Smrg   p->u.pointer = gfc_current_ns;
316627f7eb2Smrg   p->integer = 1;
317627f7eb2Smrg   p->type = P_NAMESPACE;
318627f7eb2Smrg 
319627f7eb2Smrg   gfc_insert_bbt (&pi_root, p, compare);
320627f7eb2Smrg 
321627f7eb2Smrg   symbol_number = 2;
322627f7eb2Smrg }
323627f7eb2Smrg 
324627f7eb2Smrg 
325627f7eb2Smrg /* During module writing, call here with a pointer to something,
326627f7eb2Smrg    returning the pointer_info node.  */
327627f7eb2Smrg 
328627f7eb2Smrg static pointer_info *
find_pointer(void * gp)329627f7eb2Smrg find_pointer (void *gp)
330627f7eb2Smrg {
331627f7eb2Smrg   pointer_info *p;
332627f7eb2Smrg 
333627f7eb2Smrg   p = pi_root;
334627f7eb2Smrg   while (p != NULL)
335627f7eb2Smrg     {
336627f7eb2Smrg       if (p->u.pointer == gp)
337627f7eb2Smrg 	break;
338627f7eb2Smrg       p = (gp < p->u.pointer) ? p->left : p->right;
339627f7eb2Smrg     }
340627f7eb2Smrg 
341627f7eb2Smrg   return p;
342627f7eb2Smrg }
343627f7eb2Smrg 
344627f7eb2Smrg 
345627f7eb2Smrg /* Given a pointer while writing, returns the pointer_info tree node,
346627f7eb2Smrg    creating it if it doesn't exist.  */
347627f7eb2Smrg 
348627f7eb2Smrg static pointer_info *
get_pointer(void * gp)349627f7eb2Smrg get_pointer (void *gp)
350627f7eb2Smrg {
351627f7eb2Smrg   pointer_info *p;
352627f7eb2Smrg 
353627f7eb2Smrg   p = find_pointer (gp);
354627f7eb2Smrg   if (p != NULL)
355627f7eb2Smrg     return p;
356627f7eb2Smrg 
357627f7eb2Smrg   /* Pointer doesn't have an integer.  Give it one.  */
358627f7eb2Smrg   p = gfc_get_pointer_info ();
359627f7eb2Smrg 
360627f7eb2Smrg   p->u.pointer = gp;
361627f7eb2Smrg   p->integer = symbol_number++;
362627f7eb2Smrg 
363627f7eb2Smrg   gfc_insert_bbt (&pi_root, p, compare_pointers);
364627f7eb2Smrg 
365627f7eb2Smrg   return p;
366627f7eb2Smrg }
367627f7eb2Smrg 
368627f7eb2Smrg 
369627f7eb2Smrg /* Given an integer during reading, find it in the pointer_info tree,
370627f7eb2Smrg    creating the node if not found.  */
371627f7eb2Smrg 
372627f7eb2Smrg static pointer_info *
get_integer(HOST_WIDE_INT integer)373627f7eb2Smrg get_integer (HOST_WIDE_INT integer)
374627f7eb2Smrg {
375627f7eb2Smrg   pointer_info *p, t;
376627f7eb2Smrg   int c;
377627f7eb2Smrg 
378627f7eb2Smrg   t.integer = integer;
379627f7eb2Smrg 
380627f7eb2Smrg   p = pi_root;
381627f7eb2Smrg   while (p != NULL)
382627f7eb2Smrg     {
383627f7eb2Smrg       c = compare_integers (&t, p);
384627f7eb2Smrg       if (c == 0)
385627f7eb2Smrg 	break;
386627f7eb2Smrg 
387627f7eb2Smrg       p = (c < 0) ? p->left : p->right;
388627f7eb2Smrg     }
389627f7eb2Smrg 
390627f7eb2Smrg   if (p != NULL)
391627f7eb2Smrg     return p;
392627f7eb2Smrg 
393627f7eb2Smrg   p = gfc_get_pointer_info ();
394627f7eb2Smrg   p->integer = integer;
395627f7eb2Smrg   p->u.pointer = NULL;
396627f7eb2Smrg 
397627f7eb2Smrg   gfc_insert_bbt (&pi_root, p, compare_integers);
398627f7eb2Smrg 
399627f7eb2Smrg   return p;
400627f7eb2Smrg }
401627f7eb2Smrg 
402627f7eb2Smrg 
403627f7eb2Smrg /* Resolve any fixups using a known pointer.  */
404627f7eb2Smrg 
405627f7eb2Smrg static void
resolve_fixups(fixup_t * f,void * gp)406627f7eb2Smrg resolve_fixups (fixup_t *f, void *gp)
407627f7eb2Smrg {
408627f7eb2Smrg   fixup_t *next;
409627f7eb2Smrg 
410627f7eb2Smrg   for (; f; f = next)
411627f7eb2Smrg     {
412627f7eb2Smrg       next = f->next;
413627f7eb2Smrg       *(f->pointer) = gp;
414627f7eb2Smrg       free (f);
415627f7eb2Smrg     }
416627f7eb2Smrg }
417627f7eb2Smrg 
418627f7eb2Smrg 
419627f7eb2Smrg /* Convert a string such that it starts with a lower-case character. Used
420627f7eb2Smrg    to convert the symtree name of a derived-type to the symbol name or to
421627f7eb2Smrg    the name of the associated generic function.  */
422627f7eb2Smrg 
423627f7eb2Smrg const char *
gfc_dt_lower_string(const char * name)424627f7eb2Smrg gfc_dt_lower_string (const char *name)
425627f7eb2Smrg {
426627f7eb2Smrg   if (name[0] != (char) TOLOWER ((unsigned char) name[0]))
427627f7eb2Smrg     return gfc_get_string ("%c%s", (char) TOLOWER ((unsigned char) name[0]),
428627f7eb2Smrg 			   &name[1]);
429627f7eb2Smrg   return gfc_get_string ("%s", name);
430627f7eb2Smrg }
431627f7eb2Smrg 
432627f7eb2Smrg 
433627f7eb2Smrg /* Convert a string such that it starts with an upper-case character. Used to
434627f7eb2Smrg    return the symtree-name for a derived type; the symbol name itself and the
435627f7eb2Smrg    symtree/symbol name of the associated generic function start with a lower-
436627f7eb2Smrg    case character.  */
437627f7eb2Smrg 
438627f7eb2Smrg const char *
gfc_dt_upper_string(const char * name)439627f7eb2Smrg gfc_dt_upper_string (const char *name)
440627f7eb2Smrg {
441627f7eb2Smrg   if (name[0] != (char) TOUPPER ((unsigned char) name[0]))
442627f7eb2Smrg     return gfc_get_string ("%c%s", (char) TOUPPER ((unsigned char) name[0]),
443627f7eb2Smrg 			   &name[1]);
444627f7eb2Smrg   return gfc_get_string ("%s", name);
445627f7eb2Smrg }
446627f7eb2Smrg 
447627f7eb2Smrg /* Call here during module reading when we know what pointer to
448627f7eb2Smrg    associate with an integer.  Any fixups that exist are resolved at
449627f7eb2Smrg    this time.  */
450627f7eb2Smrg 
451627f7eb2Smrg static void
associate_integer_pointer(pointer_info * p,void * gp)452627f7eb2Smrg associate_integer_pointer (pointer_info *p, void *gp)
453627f7eb2Smrg {
454627f7eb2Smrg   if (p->u.pointer != NULL)
455627f7eb2Smrg     gfc_internal_error ("associate_integer_pointer(): Already associated");
456627f7eb2Smrg 
457627f7eb2Smrg   p->u.pointer = gp;
458627f7eb2Smrg 
459627f7eb2Smrg   resolve_fixups (p->fixup, gp);
460627f7eb2Smrg 
461627f7eb2Smrg   p->fixup = NULL;
462627f7eb2Smrg }
463627f7eb2Smrg 
464627f7eb2Smrg 
465627f7eb2Smrg /* During module reading, given an integer and a pointer to a pointer,
466627f7eb2Smrg    either store the pointer from an already-known value or create a
467627f7eb2Smrg    fixup structure in order to store things later.  Returns zero if
468627f7eb2Smrg    the reference has been actually stored, or nonzero if the reference
469627f7eb2Smrg    must be fixed later (i.e., associate_integer_pointer must be called
470627f7eb2Smrg    sometime later.  Returns the pointer_info structure.  */
471627f7eb2Smrg 
472627f7eb2Smrg static pointer_info *
add_fixup(HOST_WIDE_INT integer,void * gp)473627f7eb2Smrg add_fixup (HOST_WIDE_INT integer, void *gp)
474627f7eb2Smrg {
475627f7eb2Smrg   pointer_info *p;
476627f7eb2Smrg   fixup_t *f;
477627f7eb2Smrg   char **cp;
478627f7eb2Smrg 
479627f7eb2Smrg   p = get_integer (integer);
480627f7eb2Smrg 
481627f7eb2Smrg   if (p->integer == 0 || p->u.pointer != NULL)
482627f7eb2Smrg     {
483627f7eb2Smrg       cp = (char **) gp;
484627f7eb2Smrg       *cp = (char *) p->u.pointer;
485627f7eb2Smrg     }
486627f7eb2Smrg   else
487627f7eb2Smrg     {
488627f7eb2Smrg       f = XCNEW (fixup_t);
489627f7eb2Smrg 
490627f7eb2Smrg       f->next = p->fixup;
491627f7eb2Smrg       p->fixup = f;
492627f7eb2Smrg 
493627f7eb2Smrg       f->pointer = (void **) gp;
494627f7eb2Smrg     }
495627f7eb2Smrg 
496627f7eb2Smrg   return p;
497627f7eb2Smrg }
498627f7eb2Smrg 
499627f7eb2Smrg 
500627f7eb2Smrg /*****************************************************************/
501627f7eb2Smrg 
502627f7eb2Smrg /* Parser related subroutines */
503627f7eb2Smrg 
504627f7eb2Smrg /* Free the rename list left behind by a USE statement.  */
505627f7eb2Smrg 
506627f7eb2Smrg static void
free_rename(gfc_use_rename * list)507627f7eb2Smrg free_rename (gfc_use_rename *list)
508627f7eb2Smrg {
509627f7eb2Smrg   gfc_use_rename *next;
510627f7eb2Smrg 
511627f7eb2Smrg   for (; list; list = next)
512627f7eb2Smrg     {
513627f7eb2Smrg       next = list->next;
514627f7eb2Smrg       free (list);
515627f7eb2Smrg     }
516627f7eb2Smrg }
517627f7eb2Smrg 
518627f7eb2Smrg 
519627f7eb2Smrg /* Match a USE statement.  */
520627f7eb2Smrg 
521627f7eb2Smrg match
gfc_match_use(void)522627f7eb2Smrg gfc_match_use (void)
523627f7eb2Smrg {
524627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1], module_nature[GFC_MAX_SYMBOL_LEN + 1];
525627f7eb2Smrg   gfc_use_rename *tail = NULL, *new_use;
526627f7eb2Smrg   interface_type type, type2;
527627f7eb2Smrg   gfc_intrinsic_op op;
528627f7eb2Smrg   match m;
529627f7eb2Smrg   gfc_use_list *use_list;
530627f7eb2Smrg   gfc_symtree *st;
531627f7eb2Smrg   locus loc;
532627f7eb2Smrg 
533627f7eb2Smrg   use_list = gfc_get_use_list ();
534627f7eb2Smrg 
535627f7eb2Smrg   if (gfc_match (" , ") == MATCH_YES)
536627f7eb2Smrg     {
537627f7eb2Smrg       if ((m = gfc_match (" %n ::", module_nature)) == MATCH_YES)
538627f7eb2Smrg 	{
539627f7eb2Smrg 	  if (!gfc_notify_std (GFC_STD_F2003, "module "
540627f7eb2Smrg 			       "nature in USE statement at %C"))
541627f7eb2Smrg 	    goto cleanup;
542627f7eb2Smrg 
543627f7eb2Smrg 	  if (strcmp (module_nature, "intrinsic") == 0)
544627f7eb2Smrg 	    use_list->intrinsic = true;
545627f7eb2Smrg 	  else
546627f7eb2Smrg 	    {
547627f7eb2Smrg 	      if (strcmp (module_nature, "non_intrinsic") == 0)
548627f7eb2Smrg 		use_list->non_intrinsic = true;
549627f7eb2Smrg 	      else
550627f7eb2Smrg 		{
551627f7eb2Smrg 		  gfc_error ("Module nature in USE statement at %C shall "
552627f7eb2Smrg 			     "be either INTRINSIC or NON_INTRINSIC");
553627f7eb2Smrg 		  goto cleanup;
554627f7eb2Smrg 		}
555627f7eb2Smrg 	    }
556627f7eb2Smrg 	}
557627f7eb2Smrg       else
558627f7eb2Smrg 	{
559627f7eb2Smrg 	  /* Help output a better error message than "Unclassifiable
560627f7eb2Smrg 	     statement".  */
561627f7eb2Smrg 	  gfc_match (" %n", module_nature);
562627f7eb2Smrg 	  if (strcmp (module_nature, "intrinsic") == 0
563627f7eb2Smrg 	      || strcmp (module_nature, "non_intrinsic") == 0)
564627f7eb2Smrg 	    gfc_error ("\"::\" was expected after module nature at %C "
565627f7eb2Smrg 		       "but was not found");
566627f7eb2Smrg 	  free (use_list);
567627f7eb2Smrg 	  return m;
568627f7eb2Smrg 	}
569627f7eb2Smrg     }
570627f7eb2Smrg   else
571627f7eb2Smrg     {
572627f7eb2Smrg       m = gfc_match (" ::");
573627f7eb2Smrg       if (m == MATCH_YES &&
574627f7eb2Smrg 	  !gfc_notify_std(GFC_STD_F2003, "\"USE :: module\" at %C"))
575627f7eb2Smrg 	goto cleanup;
576627f7eb2Smrg 
577627f7eb2Smrg       if (m != MATCH_YES)
578627f7eb2Smrg 	{
579627f7eb2Smrg 	  m = gfc_match ("% ");
580627f7eb2Smrg 	  if (m != MATCH_YES)
581627f7eb2Smrg 	    {
582627f7eb2Smrg 	      free (use_list);
583627f7eb2Smrg 	      return m;
584627f7eb2Smrg 	    }
585627f7eb2Smrg 	}
586627f7eb2Smrg     }
587627f7eb2Smrg 
588627f7eb2Smrg   use_list->where = gfc_current_locus;
589627f7eb2Smrg 
590627f7eb2Smrg   m = gfc_match_name (name);
591627f7eb2Smrg   if (m != MATCH_YES)
592627f7eb2Smrg     {
593627f7eb2Smrg       free (use_list);
594627f7eb2Smrg       return m;
595627f7eb2Smrg     }
596627f7eb2Smrg 
597627f7eb2Smrg   use_list->module_name = gfc_get_string ("%s", name);
598627f7eb2Smrg 
599627f7eb2Smrg   if (gfc_match_eos () == MATCH_YES)
600627f7eb2Smrg     goto done;
601627f7eb2Smrg 
602627f7eb2Smrg   if (gfc_match_char (',') != MATCH_YES)
603627f7eb2Smrg     goto syntax;
604627f7eb2Smrg 
605627f7eb2Smrg   if (gfc_match (" only :") == MATCH_YES)
606627f7eb2Smrg     use_list->only_flag = true;
607627f7eb2Smrg 
608627f7eb2Smrg   if (gfc_match_eos () == MATCH_YES)
609627f7eb2Smrg     goto done;
610627f7eb2Smrg 
611627f7eb2Smrg   for (;;)
612627f7eb2Smrg     {
613627f7eb2Smrg       /* Get a new rename struct and add it to the rename list.  */
614627f7eb2Smrg       new_use = gfc_get_use_rename ();
615627f7eb2Smrg       new_use->where = gfc_current_locus;
616627f7eb2Smrg       new_use->found = 0;
617627f7eb2Smrg 
618627f7eb2Smrg       if (use_list->rename == NULL)
619627f7eb2Smrg 	use_list->rename = new_use;
620627f7eb2Smrg       else
621627f7eb2Smrg 	tail->next = new_use;
622627f7eb2Smrg       tail = new_use;
623627f7eb2Smrg 
624627f7eb2Smrg       /* See what kind of interface we're dealing with.  Assume it is
625627f7eb2Smrg 	 not an operator.  */
626627f7eb2Smrg       new_use->op = INTRINSIC_NONE;
627627f7eb2Smrg       if (gfc_match_generic_spec (&type, name, &op) == MATCH_ERROR)
628627f7eb2Smrg 	goto cleanup;
629627f7eb2Smrg 
630627f7eb2Smrg       switch (type)
631627f7eb2Smrg 	{
632627f7eb2Smrg 	case INTERFACE_NAMELESS:
633627f7eb2Smrg 	  gfc_error ("Missing generic specification in USE statement at %C");
634627f7eb2Smrg 	  goto cleanup;
635627f7eb2Smrg 
636627f7eb2Smrg 	case INTERFACE_USER_OP:
637627f7eb2Smrg 	case INTERFACE_GENERIC:
638627f7eb2Smrg 	case INTERFACE_DTIO:
639627f7eb2Smrg 	  loc = gfc_current_locus;
640627f7eb2Smrg 
641627f7eb2Smrg 	  m = gfc_match (" =>");
642627f7eb2Smrg 
643627f7eb2Smrg 	  if (type == INTERFACE_USER_OP && m == MATCH_YES
644627f7eb2Smrg 	      && (!gfc_notify_std(GFC_STD_F2003, "Renaming "
645627f7eb2Smrg 				  "operators in USE statements at %C")))
646627f7eb2Smrg 	    goto cleanup;
647627f7eb2Smrg 
648627f7eb2Smrg 	  if (type == INTERFACE_USER_OP)
649627f7eb2Smrg 	    new_use->op = INTRINSIC_USER;
650627f7eb2Smrg 
651627f7eb2Smrg 	  if (use_list->only_flag)
652627f7eb2Smrg 	    {
653627f7eb2Smrg 	      if (m != MATCH_YES)
654627f7eb2Smrg 		strcpy (new_use->use_name, name);
655627f7eb2Smrg 	      else
656627f7eb2Smrg 		{
657627f7eb2Smrg 		  strcpy (new_use->local_name, name);
658627f7eb2Smrg 		  m = gfc_match_generic_spec (&type2, new_use->use_name, &op);
659627f7eb2Smrg 		  if (type != type2)
660627f7eb2Smrg 		    goto syntax;
661627f7eb2Smrg 		  if (m == MATCH_NO)
662627f7eb2Smrg 		    goto syntax;
663627f7eb2Smrg 		  if (m == MATCH_ERROR)
664627f7eb2Smrg 		    goto cleanup;
665627f7eb2Smrg 		}
666627f7eb2Smrg 	    }
667627f7eb2Smrg 	  else
668627f7eb2Smrg 	    {
669627f7eb2Smrg 	      if (m != MATCH_YES)
670627f7eb2Smrg 		goto syntax;
671627f7eb2Smrg 	      strcpy (new_use->local_name, name);
672627f7eb2Smrg 
673627f7eb2Smrg 	      m = gfc_match_generic_spec (&type2, new_use->use_name, &op);
674627f7eb2Smrg 	      if (type != type2)
675627f7eb2Smrg 		goto syntax;
676627f7eb2Smrg 	      if (m == MATCH_NO)
677627f7eb2Smrg 		goto syntax;
678627f7eb2Smrg 	      if (m == MATCH_ERROR)
679627f7eb2Smrg 		goto cleanup;
680627f7eb2Smrg 	    }
681627f7eb2Smrg 
682*4c3eb207Smrg 	  st = gfc_find_symtree (gfc_current_ns->sym_root, name);
683*4c3eb207Smrg 	  if (st && type != INTERFACE_USER_OP
684*4c3eb207Smrg 	      && (st->n.sym->module != use_list->module_name
685*4c3eb207Smrg 		  || strcmp (st->n.sym->name, new_use->use_name) != 0))
686*4c3eb207Smrg 	    {
687*4c3eb207Smrg 	      if (m == MATCH_YES)
688*4c3eb207Smrg 		gfc_error ("Symbol %qs at %L conflicts with the rename symbol "
689*4c3eb207Smrg 			   "at %L", name, &st->n.sym->declared_at, &loc);
690*4c3eb207Smrg 	      else
691*4c3eb207Smrg 		gfc_error ("Symbol %qs at %L conflicts with the symbol "
692*4c3eb207Smrg 			   "at %L", name, &st->n.sym->declared_at, &loc);
693*4c3eb207Smrg 	      goto cleanup;
694*4c3eb207Smrg 	    }
695*4c3eb207Smrg 
696627f7eb2Smrg 	  if (strcmp (new_use->use_name, use_list->module_name) == 0
697627f7eb2Smrg 	      || strcmp (new_use->local_name, use_list->module_name) == 0)
698627f7eb2Smrg 	    {
699627f7eb2Smrg 	      gfc_error ("The name %qs at %C has already been used as "
700627f7eb2Smrg 			 "an external module name", use_list->module_name);
701627f7eb2Smrg 	      goto cleanup;
702627f7eb2Smrg 	    }
703627f7eb2Smrg 	  break;
704627f7eb2Smrg 
705627f7eb2Smrg 	case INTERFACE_INTRINSIC_OP:
706627f7eb2Smrg 	  new_use->op = op;
707627f7eb2Smrg 	  break;
708627f7eb2Smrg 
709627f7eb2Smrg 	default:
710627f7eb2Smrg 	  gcc_unreachable ();
711627f7eb2Smrg 	}
712627f7eb2Smrg 
713627f7eb2Smrg       if (gfc_match_eos () == MATCH_YES)
714627f7eb2Smrg 	break;
715627f7eb2Smrg       if (gfc_match_char (',') != MATCH_YES)
716627f7eb2Smrg 	goto syntax;
717627f7eb2Smrg     }
718627f7eb2Smrg 
719627f7eb2Smrg done:
720627f7eb2Smrg   if (module_list)
721627f7eb2Smrg     {
722627f7eb2Smrg       gfc_use_list *last = module_list;
723627f7eb2Smrg       while (last->next)
724627f7eb2Smrg 	last = last->next;
725627f7eb2Smrg       last->next = use_list;
726627f7eb2Smrg     }
727627f7eb2Smrg   else
728627f7eb2Smrg     module_list = use_list;
729627f7eb2Smrg 
730627f7eb2Smrg   return MATCH_YES;
731627f7eb2Smrg 
732627f7eb2Smrg syntax:
733627f7eb2Smrg   gfc_syntax_error (ST_USE);
734627f7eb2Smrg 
735627f7eb2Smrg cleanup:
736627f7eb2Smrg   free_rename (use_list->rename);
737627f7eb2Smrg   free (use_list);
738627f7eb2Smrg   return MATCH_ERROR;
739627f7eb2Smrg }
740627f7eb2Smrg 
741627f7eb2Smrg 
742627f7eb2Smrg /* Match a SUBMODULE statement.
743627f7eb2Smrg 
744627f7eb2Smrg    According to F2008:11.2.3.2, "The submodule identifier is the
745627f7eb2Smrg    ordered pair whose first element is the ancestor module name and
746627f7eb2Smrg    whose second element is the submodule name. 'Submodule_name' is
747627f7eb2Smrg    used for the submodule filename and uses '@' as a separator, whilst
748*4c3eb207Smrg    the name of the symbol for the module uses '.' as a separator.
749627f7eb2Smrg    The reasons for these choices are:
750627f7eb2Smrg    (i) To follow another leading brand in the submodule filenames;
751627f7eb2Smrg    (ii) Since '.' is not particularly visible in the filenames; and
752627f7eb2Smrg    (iii) The linker does not permit '@' in mnemonics.  */
753627f7eb2Smrg 
754627f7eb2Smrg match
gfc_match_submodule(void)755627f7eb2Smrg gfc_match_submodule (void)
756627f7eb2Smrg {
757627f7eb2Smrg   match m;
758627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
759627f7eb2Smrg   gfc_use_list *use_list;
760627f7eb2Smrg   bool seen_colon = false;
761627f7eb2Smrg 
762627f7eb2Smrg   if (!gfc_notify_std (GFC_STD_F2008, "SUBMODULE declaration at %C"))
763627f7eb2Smrg     return MATCH_ERROR;
764627f7eb2Smrg 
765627f7eb2Smrg   if (gfc_current_state () != COMP_NONE)
766627f7eb2Smrg     {
767627f7eb2Smrg       gfc_error ("SUBMODULE declaration at %C cannot appear within "
768627f7eb2Smrg 		 "another scoping unit");
769627f7eb2Smrg       return MATCH_ERROR;
770627f7eb2Smrg     }
771627f7eb2Smrg 
772627f7eb2Smrg   gfc_new_block = NULL;
773627f7eb2Smrg   gcc_assert (module_list == NULL);
774627f7eb2Smrg 
775627f7eb2Smrg   if (gfc_match_char ('(') != MATCH_YES)
776627f7eb2Smrg     goto syntax;
777627f7eb2Smrg 
778627f7eb2Smrg   while (1)
779627f7eb2Smrg     {
780627f7eb2Smrg       m = gfc_match (" %n", name);
781627f7eb2Smrg       if (m != MATCH_YES)
782627f7eb2Smrg 	goto syntax;
783627f7eb2Smrg 
784627f7eb2Smrg       use_list = gfc_get_use_list ();
785627f7eb2Smrg       use_list->where = gfc_current_locus;
786627f7eb2Smrg 
787627f7eb2Smrg       if (module_list)
788627f7eb2Smrg 	{
789627f7eb2Smrg 	  gfc_use_list *last = module_list;
790627f7eb2Smrg 	  while (last->next)
791627f7eb2Smrg 	    last = last->next;
792627f7eb2Smrg 	  last->next = use_list;
793627f7eb2Smrg 	  use_list->module_name
794627f7eb2Smrg 		= gfc_get_string ("%s.%s", module_list->module_name, name);
795627f7eb2Smrg 	  use_list->submodule_name
796627f7eb2Smrg 		= gfc_get_string ("%s@%s", module_list->module_name, name);
797627f7eb2Smrg 	}
798627f7eb2Smrg       else
799627f7eb2Smrg 	{
800627f7eb2Smrg 	  module_list = use_list;
801627f7eb2Smrg 	  use_list->module_name = gfc_get_string ("%s", name);
802627f7eb2Smrg 	  use_list->submodule_name = use_list->module_name;
803627f7eb2Smrg 	}
804627f7eb2Smrg 
805627f7eb2Smrg       if (gfc_match_char (')') == MATCH_YES)
806627f7eb2Smrg 	break;
807627f7eb2Smrg 
808627f7eb2Smrg       if (gfc_match_char (':') != MATCH_YES
809627f7eb2Smrg 	  || seen_colon)
810627f7eb2Smrg 	goto syntax;
811627f7eb2Smrg 
812627f7eb2Smrg       seen_colon = true;
813627f7eb2Smrg     }
814627f7eb2Smrg 
815627f7eb2Smrg   m = gfc_match (" %s%t", &gfc_new_block);
816627f7eb2Smrg   if (m != MATCH_YES)
817627f7eb2Smrg     goto syntax;
818627f7eb2Smrg 
819627f7eb2Smrg   submodule_name = gfc_get_string ("%s@%s", module_list->module_name,
820627f7eb2Smrg 				   gfc_new_block->name);
821627f7eb2Smrg 
822627f7eb2Smrg   gfc_new_block->name = gfc_get_string ("%s.%s",
823627f7eb2Smrg 					module_list->module_name,
824627f7eb2Smrg 					gfc_new_block->name);
825627f7eb2Smrg 
826627f7eb2Smrg   if (!gfc_add_flavor (&gfc_new_block->attr, FL_MODULE,
827627f7eb2Smrg 		       gfc_new_block->name, NULL))
828627f7eb2Smrg     return MATCH_ERROR;
829627f7eb2Smrg 
830627f7eb2Smrg   /* Just retain the ultimate .(s)mod file for reading, since it
831627f7eb2Smrg      contains all the information in its ancestors.  */
832627f7eb2Smrg   use_list = module_list;
833627f7eb2Smrg   for (; module_list->next; use_list = module_list)
834627f7eb2Smrg     {
835627f7eb2Smrg       module_list = use_list->next;
836627f7eb2Smrg       free (use_list);
837627f7eb2Smrg     }
838627f7eb2Smrg 
839627f7eb2Smrg   return MATCH_YES;
840627f7eb2Smrg 
841627f7eb2Smrg syntax:
842627f7eb2Smrg   gfc_error ("Syntax error in SUBMODULE statement at %C");
843627f7eb2Smrg   return MATCH_ERROR;
844627f7eb2Smrg }
845627f7eb2Smrg 
846627f7eb2Smrg 
847627f7eb2Smrg /* Given a name and a number, inst, return the inst name
848627f7eb2Smrg    under which to load this symbol. Returns NULL if this
849627f7eb2Smrg    symbol shouldn't be loaded. If inst is zero, returns
850627f7eb2Smrg    the number of instances of this name. If interface is
851627f7eb2Smrg    true, a user-defined operator is sought, otherwise only
852627f7eb2Smrg    non-operators are sought.  */
853627f7eb2Smrg 
854627f7eb2Smrg static const char *
find_use_name_n(const char * name,int * inst,bool interface)855627f7eb2Smrg find_use_name_n (const char *name, int *inst, bool interface)
856627f7eb2Smrg {
857627f7eb2Smrg   gfc_use_rename *u;
858627f7eb2Smrg   const char *low_name = NULL;
859627f7eb2Smrg   int i;
860627f7eb2Smrg 
861627f7eb2Smrg   /* For derived types.  */
862627f7eb2Smrg   if (name[0] != (char) TOLOWER ((unsigned char) name[0]))
863627f7eb2Smrg     low_name = gfc_dt_lower_string (name);
864627f7eb2Smrg 
865627f7eb2Smrg   i = 0;
866627f7eb2Smrg   for (u = gfc_rename_list; u; u = u->next)
867627f7eb2Smrg     {
868627f7eb2Smrg       if ((!low_name && strcmp (u->use_name, name) != 0)
869627f7eb2Smrg 	  || (low_name && strcmp (u->use_name, low_name) != 0)
870627f7eb2Smrg 	  || (u->op == INTRINSIC_USER && !interface)
871627f7eb2Smrg 	  || (u->op != INTRINSIC_USER &&  interface))
872627f7eb2Smrg 	continue;
873627f7eb2Smrg       if (++i == *inst)
874627f7eb2Smrg 	break;
875627f7eb2Smrg     }
876627f7eb2Smrg 
877627f7eb2Smrg   if (!*inst)
878627f7eb2Smrg     {
879627f7eb2Smrg       *inst = i;
880627f7eb2Smrg       return NULL;
881627f7eb2Smrg     }
882627f7eb2Smrg 
883627f7eb2Smrg   if (u == NULL)
884627f7eb2Smrg     return only_flag ? NULL : name;
885627f7eb2Smrg 
886627f7eb2Smrg   u->found = 1;
887627f7eb2Smrg 
888627f7eb2Smrg   if (low_name)
889627f7eb2Smrg     {
890627f7eb2Smrg       if (u->local_name[0] == '\0')
891627f7eb2Smrg 	return name;
892627f7eb2Smrg       return gfc_dt_upper_string (u->local_name);
893627f7eb2Smrg     }
894627f7eb2Smrg 
895627f7eb2Smrg   return (u->local_name[0] != '\0') ? u->local_name : name;
896627f7eb2Smrg }
897627f7eb2Smrg 
898627f7eb2Smrg 
899627f7eb2Smrg /* Given a name, return the name under which to load this symbol.
900627f7eb2Smrg    Returns NULL if this symbol shouldn't be loaded.  */
901627f7eb2Smrg 
902627f7eb2Smrg static const char *
find_use_name(const char * name,bool interface)903627f7eb2Smrg find_use_name (const char *name, bool interface)
904627f7eb2Smrg {
905627f7eb2Smrg   int i = 1;
906627f7eb2Smrg   return find_use_name_n (name, &i, interface);
907627f7eb2Smrg }
908627f7eb2Smrg 
909627f7eb2Smrg 
910627f7eb2Smrg /* Given a real name, return the number of use names associated with it.  */
911627f7eb2Smrg 
912627f7eb2Smrg static int
number_use_names(const char * name,bool interface)913627f7eb2Smrg number_use_names (const char *name, bool interface)
914627f7eb2Smrg {
915627f7eb2Smrg   int i = 0;
916627f7eb2Smrg   find_use_name_n (name, &i, interface);
917627f7eb2Smrg   return i;
918627f7eb2Smrg }
919627f7eb2Smrg 
920627f7eb2Smrg 
921627f7eb2Smrg /* Try to find the operator in the current list.  */
922627f7eb2Smrg 
923627f7eb2Smrg static gfc_use_rename *
find_use_operator(gfc_intrinsic_op op)924627f7eb2Smrg find_use_operator (gfc_intrinsic_op op)
925627f7eb2Smrg {
926627f7eb2Smrg   gfc_use_rename *u;
927627f7eb2Smrg 
928627f7eb2Smrg   for (u = gfc_rename_list; u; u = u->next)
929627f7eb2Smrg     if (u->op == op)
930627f7eb2Smrg       return u;
931627f7eb2Smrg 
932627f7eb2Smrg   return NULL;
933627f7eb2Smrg }
934627f7eb2Smrg 
935627f7eb2Smrg 
936627f7eb2Smrg /*****************************************************************/
937627f7eb2Smrg 
938627f7eb2Smrg /* The next couple of subroutines maintain a tree used to avoid a
939627f7eb2Smrg    brute-force search for a combination of true name and module name.
940627f7eb2Smrg    While symtree names, the name that a particular symbol is known by
941627f7eb2Smrg    can changed with USE statements, we still have to keep track of the
942627f7eb2Smrg    true names to generate the correct reference, and also avoid
943627f7eb2Smrg    loading the same real symbol twice in a program unit.
944627f7eb2Smrg 
945627f7eb2Smrg    When we start reading, the true name tree is built and maintained
946627f7eb2Smrg    as symbols are read.  The tree is searched as we load new symbols
947627f7eb2Smrg    to see if it already exists someplace in the namespace.  */
948627f7eb2Smrg 
949627f7eb2Smrg typedef struct true_name
950627f7eb2Smrg {
951627f7eb2Smrg   BBT_HEADER (true_name);
952627f7eb2Smrg   const char *name;
953627f7eb2Smrg   gfc_symbol *sym;
954627f7eb2Smrg }
955627f7eb2Smrg true_name;
956627f7eb2Smrg 
957627f7eb2Smrg static true_name *true_name_root;
958627f7eb2Smrg 
959627f7eb2Smrg 
960627f7eb2Smrg /* Compare two true_name structures.  */
961627f7eb2Smrg 
962627f7eb2Smrg static int
compare_true_names(void * _t1,void * _t2)963627f7eb2Smrg compare_true_names (void *_t1, void *_t2)
964627f7eb2Smrg {
965627f7eb2Smrg   true_name *t1, *t2;
966627f7eb2Smrg   int c;
967627f7eb2Smrg 
968627f7eb2Smrg   t1 = (true_name *) _t1;
969627f7eb2Smrg   t2 = (true_name *) _t2;
970627f7eb2Smrg 
971627f7eb2Smrg   c = ((t1->sym->module > t2->sym->module)
972627f7eb2Smrg        - (t1->sym->module < t2->sym->module));
973627f7eb2Smrg   if (c != 0)
974627f7eb2Smrg     return c;
975627f7eb2Smrg 
976627f7eb2Smrg   return strcmp (t1->name, t2->name);
977627f7eb2Smrg }
978627f7eb2Smrg 
979627f7eb2Smrg 
980627f7eb2Smrg /* Given a true name, search the true name tree to see if it exists
981627f7eb2Smrg    within the main namespace.  */
982627f7eb2Smrg 
983627f7eb2Smrg static gfc_symbol *
find_true_name(const char * name,const char * module)984627f7eb2Smrg find_true_name (const char *name, const char *module)
985627f7eb2Smrg {
986627f7eb2Smrg   true_name t, *p;
987627f7eb2Smrg   gfc_symbol sym;
988627f7eb2Smrg   int c;
989627f7eb2Smrg 
990627f7eb2Smrg   t.name = gfc_get_string ("%s", name);
991627f7eb2Smrg   if (module != NULL)
992627f7eb2Smrg     sym.module = gfc_get_string ("%s", module);
993627f7eb2Smrg   else
994627f7eb2Smrg     sym.module = NULL;
995627f7eb2Smrg   t.sym = &sym;
996627f7eb2Smrg 
997627f7eb2Smrg   p = true_name_root;
998627f7eb2Smrg   while (p != NULL)
999627f7eb2Smrg     {
1000627f7eb2Smrg       c = compare_true_names ((void *) (&t), (void *) p);
1001627f7eb2Smrg       if (c == 0)
1002627f7eb2Smrg 	return p->sym;
1003627f7eb2Smrg 
1004627f7eb2Smrg       p = (c < 0) ? p->left : p->right;
1005627f7eb2Smrg     }
1006627f7eb2Smrg 
1007627f7eb2Smrg   return NULL;
1008627f7eb2Smrg }
1009627f7eb2Smrg 
1010627f7eb2Smrg 
1011627f7eb2Smrg /* Given a gfc_symbol pointer that is not in the true name tree, add it.  */
1012627f7eb2Smrg 
1013627f7eb2Smrg static void
add_true_name(gfc_symbol * sym)1014627f7eb2Smrg add_true_name (gfc_symbol *sym)
1015627f7eb2Smrg {
1016627f7eb2Smrg   true_name *t;
1017627f7eb2Smrg 
1018627f7eb2Smrg   t = XCNEW (true_name);
1019627f7eb2Smrg   t->sym = sym;
1020627f7eb2Smrg   if (gfc_fl_struct (sym->attr.flavor))
1021627f7eb2Smrg     t->name = gfc_dt_upper_string (sym->name);
1022627f7eb2Smrg   else
1023627f7eb2Smrg     t->name = sym->name;
1024627f7eb2Smrg 
1025627f7eb2Smrg   gfc_insert_bbt (&true_name_root, t, compare_true_names);
1026627f7eb2Smrg }
1027627f7eb2Smrg 
1028627f7eb2Smrg 
1029627f7eb2Smrg /* Recursive function to build the initial true name tree by
1030627f7eb2Smrg    recursively traversing the current namespace.  */
1031627f7eb2Smrg 
1032627f7eb2Smrg static void
build_tnt(gfc_symtree * st)1033627f7eb2Smrg build_tnt (gfc_symtree *st)
1034627f7eb2Smrg {
1035627f7eb2Smrg   const char *name;
1036627f7eb2Smrg   if (st == NULL)
1037627f7eb2Smrg     return;
1038627f7eb2Smrg 
1039627f7eb2Smrg   build_tnt (st->left);
1040627f7eb2Smrg   build_tnt (st->right);
1041627f7eb2Smrg 
1042627f7eb2Smrg   if (gfc_fl_struct (st->n.sym->attr.flavor))
1043627f7eb2Smrg     name = gfc_dt_upper_string (st->n.sym->name);
1044627f7eb2Smrg   else
1045627f7eb2Smrg     name = st->n.sym->name;
1046627f7eb2Smrg 
1047627f7eb2Smrg   if (find_true_name (name, st->n.sym->module) != NULL)
1048627f7eb2Smrg     return;
1049627f7eb2Smrg 
1050627f7eb2Smrg   add_true_name (st->n.sym);
1051627f7eb2Smrg }
1052627f7eb2Smrg 
1053627f7eb2Smrg 
1054627f7eb2Smrg /* Initialize the true name tree with the current namespace.  */
1055627f7eb2Smrg 
1056627f7eb2Smrg static void
init_true_name_tree(void)1057627f7eb2Smrg init_true_name_tree (void)
1058627f7eb2Smrg {
1059627f7eb2Smrg   true_name_root = NULL;
1060627f7eb2Smrg   build_tnt (gfc_current_ns->sym_root);
1061627f7eb2Smrg }
1062627f7eb2Smrg 
1063627f7eb2Smrg 
1064627f7eb2Smrg /* Recursively free a true name tree node.  */
1065627f7eb2Smrg 
1066627f7eb2Smrg static void
free_true_name(true_name * t)1067627f7eb2Smrg free_true_name (true_name *t)
1068627f7eb2Smrg {
1069627f7eb2Smrg   if (t == NULL)
1070627f7eb2Smrg     return;
1071627f7eb2Smrg   free_true_name (t->left);
1072627f7eb2Smrg   free_true_name (t->right);
1073627f7eb2Smrg 
1074627f7eb2Smrg   free (t);
1075627f7eb2Smrg }
1076627f7eb2Smrg 
1077627f7eb2Smrg 
1078627f7eb2Smrg /*****************************************************************/
1079627f7eb2Smrg 
1080627f7eb2Smrg /* Module reading and writing.  */
1081627f7eb2Smrg 
1082627f7eb2Smrg /* The following are versions similar to the ones in scanner.c, but
1083627f7eb2Smrg    for dealing with compressed module files.  */
1084627f7eb2Smrg 
1085627f7eb2Smrg static gzFile
gzopen_included_file_1(const char * name,gfc_directorylist * list,bool module,bool system)1086627f7eb2Smrg gzopen_included_file_1 (const char *name, gfc_directorylist *list,
1087627f7eb2Smrg                      bool module, bool system)
1088627f7eb2Smrg {
1089627f7eb2Smrg   char *fullname;
1090627f7eb2Smrg   gfc_directorylist *p;
1091627f7eb2Smrg   gzFile f;
1092627f7eb2Smrg 
1093627f7eb2Smrg   for (p = list; p; p = p->next)
1094627f7eb2Smrg     {
1095627f7eb2Smrg       if (module && !p->use_for_modules)
1096627f7eb2Smrg        continue;
1097627f7eb2Smrg 
1098627f7eb2Smrg       fullname = (char *) alloca(strlen (p->path) + strlen (name) + 1);
1099627f7eb2Smrg       strcpy (fullname, p->path);
1100627f7eb2Smrg       strcat (fullname, name);
1101627f7eb2Smrg 
1102627f7eb2Smrg       f = gzopen (fullname, "r");
1103627f7eb2Smrg       if (f != NULL)
1104627f7eb2Smrg        {
1105627f7eb2Smrg          if (gfc_cpp_makedep ())
1106627f7eb2Smrg            gfc_cpp_add_dep (fullname, system);
1107627f7eb2Smrg 
1108*4c3eb207Smrg 	 free (module_fullpath);
1109*4c3eb207Smrg 	 module_fullpath = xstrdup (fullname);
1110627f7eb2Smrg          return f;
1111627f7eb2Smrg        }
1112627f7eb2Smrg     }
1113627f7eb2Smrg 
1114627f7eb2Smrg   return NULL;
1115627f7eb2Smrg }
1116627f7eb2Smrg 
1117627f7eb2Smrg static gzFile
gzopen_included_file(const char * name,bool include_cwd,bool module)1118627f7eb2Smrg gzopen_included_file (const char *name, bool include_cwd, bool module)
1119627f7eb2Smrg {
1120627f7eb2Smrg   gzFile f = NULL;
1121627f7eb2Smrg 
1122627f7eb2Smrg   if (IS_ABSOLUTE_PATH (name) || include_cwd)
1123627f7eb2Smrg     {
1124627f7eb2Smrg       f = gzopen (name, "r");
1125*4c3eb207Smrg       if (f)
1126*4c3eb207Smrg 	{
1127*4c3eb207Smrg 	  if (gfc_cpp_makedep ())
1128627f7eb2Smrg 	    gfc_cpp_add_dep (name, false);
1129*4c3eb207Smrg 
1130*4c3eb207Smrg 	  free (module_fullpath);
1131*4c3eb207Smrg 	  module_fullpath = xstrdup (name);
1132*4c3eb207Smrg 	}
1133627f7eb2Smrg     }
1134627f7eb2Smrg 
1135627f7eb2Smrg   if (!f)
1136627f7eb2Smrg     f = gzopen_included_file_1 (name, include_dirs, module, false);
1137627f7eb2Smrg 
1138627f7eb2Smrg   return f;
1139627f7eb2Smrg }
1140627f7eb2Smrg 
1141627f7eb2Smrg static gzFile
gzopen_intrinsic_module(const char * name)1142627f7eb2Smrg gzopen_intrinsic_module (const char* name)
1143627f7eb2Smrg {
1144627f7eb2Smrg   gzFile f = NULL;
1145627f7eb2Smrg 
1146627f7eb2Smrg   if (IS_ABSOLUTE_PATH (name))
1147627f7eb2Smrg     {
1148627f7eb2Smrg       f = gzopen (name, "r");
1149*4c3eb207Smrg       if (f)
1150*4c3eb207Smrg 	{
1151*4c3eb207Smrg 	  if (gfc_cpp_makedep ())
1152627f7eb2Smrg 	    gfc_cpp_add_dep (name, true);
1153*4c3eb207Smrg 
1154*4c3eb207Smrg 	  free (module_fullpath);
1155*4c3eb207Smrg 	  module_fullpath = xstrdup (name);
1156*4c3eb207Smrg 	}
1157627f7eb2Smrg     }
1158627f7eb2Smrg 
1159627f7eb2Smrg   if (!f)
1160627f7eb2Smrg     f = gzopen_included_file_1 (name, intrinsic_modules_dirs, true, true);
1161627f7eb2Smrg 
1162627f7eb2Smrg   return f;
1163627f7eb2Smrg }
1164627f7eb2Smrg 
1165627f7eb2Smrg 
1166627f7eb2Smrg enum atom_type
1167627f7eb2Smrg {
1168627f7eb2Smrg   ATOM_NAME, ATOM_LPAREN, ATOM_RPAREN, ATOM_INTEGER, ATOM_STRING
1169627f7eb2Smrg };
1170627f7eb2Smrg 
1171627f7eb2Smrg static atom_type last_atom;
1172627f7eb2Smrg 
1173627f7eb2Smrg 
1174627f7eb2Smrg /* The name buffer must be at least as long as a symbol name.  Right
1175627f7eb2Smrg    now it's not clear how we're going to store numeric constants--
1176627f7eb2Smrg    probably as a hexadecimal string, since this will allow the exact
1177627f7eb2Smrg    number to be preserved (this can't be done by a decimal
1178627f7eb2Smrg    representation).  Worry about that later.  TODO!  */
1179627f7eb2Smrg 
1180627f7eb2Smrg #define MAX_ATOM_SIZE 100
1181627f7eb2Smrg 
1182627f7eb2Smrg static HOST_WIDE_INT atom_int;
1183627f7eb2Smrg static char *atom_string, atom_name[MAX_ATOM_SIZE];
1184627f7eb2Smrg 
1185627f7eb2Smrg 
1186627f7eb2Smrg /* Report problems with a module.  Error reporting is not very
1187627f7eb2Smrg    elaborate, since this sorts of errors shouldn't really happen.
1188627f7eb2Smrg    This subroutine never returns.  */
1189627f7eb2Smrg 
1190627f7eb2Smrg static void bad_module (const char *) ATTRIBUTE_NORETURN;
1191627f7eb2Smrg 
1192627f7eb2Smrg static void
bad_module(const char * msgid)1193627f7eb2Smrg bad_module (const char *msgid)
1194627f7eb2Smrg {
1195627f7eb2Smrg   XDELETEVEC (module_content);
1196627f7eb2Smrg   module_content = NULL;
1197627f7eb2Smrg 
1198627f7eb2Smrg   switch (iomode)
1199627f7eb2Smrg     {
1200627f7eb2Smrg     case IO_INPUT:
1201627f7eb2Smrg       gfc_fatal_error ("Reading module %qs at line %d column %d: %s",
1202*4c3eb207Smrg 	  	       module_fullpath, module_line, module_column, msgid);
1203627f7eb2Smrg       break;
1204627f7eb2Smrg     case IO_OUTPUT:
1205627f7eb2Smrg       gfc_fatal_error ("Writing module %qs at line %d column %d: %s",
1206627f7eb2Smrg 	  	       module_name, module_line, module_column, msgid);
1207627f7eb2Smrg       break;
1208627f7eb2Smrg     default:
1209627f7eb2Smrg       gfc_fatal_error ("Module %qs at line %d column %d: %s",
1210627f7eb2Smrg 	  	       module_name, module_line, module_column, msgid);
1211627f7eb2Smrg       break;
1212627f7eb2Smrg     }
1213627f7eb2Smrg }
1214627f7eb2Smrg 
1215627f7eb2Smrg 
1216627f7eb2Smrg /* Set the module's input pointer.  */
1217627f7eb2Smrg 
1218627f7eb2Smrg static void
set_module_locus(module_locus * m)1219627f7eb2Smrg set_module_locus (module_locus *m)
1220627f7eb2Smrg {
1221627f7eb2Smrg   module_column = m->column;
1222627f7eb2Smrg   module_line = m->line;
1223627f7eb2Smrg   module_pos = m->pos;
1224627f7eb2Smrg }
1225627f7eb2Smrg 
1226627f7eb2Smrg 
1227627f7eb2Smrg /* Get the module's input pointer so that we can restore it later.  */
1228627f7eb2Smrg 
1229627f7eb2Smrg static void
get_module_locus(module_locus * m)1230627f7eb2Smrg get_module_locus (module_locus *m)
1231627f7eb2Smrg {
1232627f7eb2Smrg   m->column = module_column;
1233627f7eb2Smrg   m->line = module_line;
1234627f7eb2Smrg   m->pos = module_pos;
1235627f7eb2Smrg }
1236627f7eb2Smrg 
1237627f7eb2Smrg 
1238627f7eb2Smrg /* Get the next character in the module, updating our reckoning of
1239627f7eb2Smrg    where we are.  */
1240627f7eb2Smrg 
1241627f7eb2Smrg static int
module_char(void)1242627f7eb2Smrg module_char (void)
1243627f7eb2Smrg {
1244627f7eb2Smrg   const char c = module_content[module_pos++];
1245627f7eb2Smrg   if (c == '\0')
1246627f7eb2Smrg     bad_module ("Unexpected EOF");
1247627f7eb2Smrg 
1248627f7eb2Smrg   prev_module_line = module_line;
1249627f7eb2Smrg   prev_module_column = module_column;
1250627f7eb2Smrg 
1251627f7eb2Smrg   if (c == '\n')
1252627f7eb2Smrg     {
1253627f7eb2Smrg       module_line++;
1254627f7eb2Smrg       module_column = 0;
1255627f7eb2Smrg     }
1256627f7eb2Smrg 
1257627f7eb2Smrg   module_column++;
1258627f7eb2Smrg   return c;
1259627f7eb2Smrg }
1260627f7eb2Smrg 
1261627f7eb2Smrg /* Unget a character while remembering the line and column.  Works for
1262627f7eb2Smrg    a single character only.  */
1263627f7eb2Smrg 
1264627f7eb2Smrg static void
module_unget_char(void)1265627f7eb2Smrg module_unget_char (void)
1266627f7eb2Smrg {
1267627f7eb2Smrg   module_line = prev_module_line;
1268627f7eb2Smrg   module_column = prev_module_column;
1269627f7eb2Smrg   module_pos--;
1270627f7eb2Smrg }
1271627f7eb2Smrg 
1272627f7eb2Smrg /* Parse a string constant.  The delimiter is guaranteed to be a
1273627f7eb2Smrg    single quote.  */
1274627f7eb2Smrg 
1275627f7eb2Smrg static void
parse_string(void)1276627f7eb2Smrg parse_string (void)
1277627f7eb2Smrg {
1278627f7eb2Smrg   int c;
1279627f7eb2Smrg   size_t cursz = 30;
1280627f7eb2Smrg   size_t len = 0;
1281627f7eb2Smrg 
1282627f7eb2Smrg   atom_string = XNEWVEC (char, cursz);
1283627f7eb2Smrg 
1284627f7eb2Smrg   for ( ; ; )
1285627f7eb2Smrg     {
1286627f7eb2Smrg       c = module_char ();
1287627f7eb2Smrg 
1288627f7eb2Smrg       if (c == '\'')
1289627f7eb2Smrg 	{
1290627f7eb2Smrg 	  int c2 = module_char ();
1291627f7eb2Smrg 	  if (c2 != '\'')
1292627f7eb2Smrg 	    {
1293627f7eb2Smrg 	      module_unget_char ();
1294627f7eb2Smrg 	      break;
1295627f7eb2Smrg 	    }
1296627f7eb2Smrg 	}
1297627f7eb2Smrg 
1298627f7eb2Smrg       if (len >= cursz)
1299627f7eb2Smrg 	{
1300627f7eb2Smrg 	  cursz *= 2;
1301627f7eb2Smrg 	  atom_string = XRESIZEVEC (char, atom_string, cursz);
1302627f7eb2Smrg 	}
1303627f7eb2Smrg       atom_string[len] = c;
1304627f7eb2Smrg       len++;
1305627f7eb2Smrg     }
1306627f7eb2Smrg 
1307627f7eb2Smrg   atom_string = XRESIZEVEC (char, atom_string, len + 1);
1308627f7eb2Smrg   atom_string[len] = '\0'; 	/* C-style string for debug purposes.  */
1309627f7eb2Smrg }
1310627f7eb2Smrg 
1311627f7eb2Smrg 
1312627f7eb2Smrg /* Parse an integer. Should fit in a HOST_WIDE_INT.  */
1313627f7eb2Smrg 
1314627f7eb2Smrg static void
parse_integer(int c)1315627f7eb2Smrg parse_integer (int c)
1316627f7eb2Smrg {
1317627f7eb2Smrg   atom_int = c - '0';
1318627f7eb2Smrg 
1319627f7eb2Smrg   for (;;)
1320627f7eb2Smrg     {
1321627f7eb2Smrg       c = module_char ();
1322627f7eb2Smrg       if (!ISDIGIT (c))
1323627f7eb2Smrg 	{
1324627f7eb2Smrg 	  module_unget_char ();
1325627f7eb2Smrg 	  break;
1326627f7eb2Smrg 	}
1327627f7eb2Smrg 
1328627f7eb2Smrg       atom_int = 10 * atom_int + c - '0';
1329627f7eb2Smrg     }
1330627f7eb2Smrg 
1331627f7eb2Smrg }
1332627f7eb2Smrg 
1333627f7eb2Smrg 
1334627f7eb2Smrg /* Parse a name.  */
1335627f7eb2Smrg 
1336627f7eb2Smrg static void
parse_name(int c)1337627f7eb2Smrg parse_name (int c)
1338627f7eb2Smrg {
1339627f7eb2Smrg   char *p;
1340627f7eb2Smrg   int len;
1341627f7eb2Smrg 
1342627f7eb2Smrg   p = atom_name;
1343627f7eb2Smrg 
1344627f7eb2Smrg   *p++ = c;
1345627f7eb2Smrg   len = 1;
1346627f7eb2Smrg 
1347627f7eb2Smrg   for (;;)
1348627f7eb2Smrg     {
1349627f7eb2Smrg       c = module_char ();
1350627f7eb2Smrg       if (!ISALNUM (c) && c != '_' && c != '-')
1351627f7eb2Smrg 	{
1352627f7eb2Smrg 	  module_unget_char ();
1353627f7eb2Smrg 	  break;
1354627f7eb2Smrg 	}
1355627f7eb2Smrg 
1356627f7eb2Smrg       *p++ = c;
1357627f7eb2Smrg       if (++len > GFC_MAX_SYMBOL_LEN)
1358627f7eb2Smrg 	bad_module ("Name too long");
1359627f7eb2Smrg     }
1360627f7eb2Smrg 
1361627f7eb2Smrg   *p = '\0';
1362627f7eb2Smrg 
1363627f7eb2Smrg }
1364627f7eb2Smrg 
1365627f7eb2Smrg 
1366627f7eb2Smrg /* Read the next atom in the module's input stream.  */
1367627f7eb2Smrg 
1368627f7eb2Smrg static atom_type
parse_atom(void)1369627f7eb2Smrg parse_atom (void)
1370627f7eb2Smrg {
1371627f7eb2Smrg   int c;
1372627f7eb2Smrg 
1373627f7eb2Smrg   do
1374627f7eb2Smrg     {
1375627f7eb2Smrg       c = module_char ();
1376627f7eb2Smrg     }
1377627f7eb2Smrg   while (c == ' ' || c == '\r' || c == '\n');
1378627f7eb2Smrg 
1379627f7eb2Smrg   switch (c)
1380627f7eb2Smrg     {
1381627f7eb2Smrg     case '(':
1382627f7eb2Smrg       return ATOM_LPAREN;
1383627f7eb2Smrg 
1384627f7eb2Smrg     case ')':
1385627f7eb2Smrg       return ATOM_RPAREN;
1386627f7eb2Smrg 
1387627f7eb2Smrg     case '\'':
1388627f7eb2Smrg       parse_string ();
1389627f7eb2Smrg       return ATOM_STRING;
1390627f7eb2Smrg 
1391627f7eb2Smrg     case '0':
1392627f7eb2Smrg     case '1':
1393627f7eb2Smrg     case '2':
1394627f7eb2Smrg     case '3':
1395627f7eb2Smrg     case '4':
1396627f7eb2Smrg     case '5':
1397627f7eb2Smrg     case '6':
1398627f7eb2Smrg     case '7':
1399627f7eb2Smrg     case '8':
1400627f7eb2Smrg     case '9':
1401627f7eb2Smrg       parse_integer (c);
1402627f7eb2Smrg       return ATOM_INTEGER;
1403627f7eb2Smrg 
1404627f7eb2Smrg     case 'a':
1405627f7eb2Smrg     case 'b':
1406627f7eb2Smrg     case 'c':
1407627f7eb2Smrg     case 'd':
1408627f7eb2Smrg     case 'e':
1409627f7eb2Smrg     case 'f':
1410627f7eb2Smrg     case 'g':
1411627f7eb2Smrg     case 'h':
1412627f7eb2Smrg     case 'i':
1413627f7eb2Smrg     case 'j':
1414627f7eb2Smrg     case 'k':
1415627f7eb2Smrg     case 'l':
1416627f7eb2Smrg     case 'm':
1417627f7eb2Smrg     case 'n':
1418627f7eb2Smrg     case 'o':
1419627f7eb2Smrg     case 'p':
1420627f7eb2Smrg     case 'q':
1421627f7eb2Smrg     case 'r':
1422627f7eb2Smrg     case 's':
1423627f7eb2Smrg     case 't':
1424627f7eb2Smrg     case 'u':
1425627f7eb2Smrg     case 'v':
1426627f7eb2Smrg     case 'w':
1427627f7eb2Smrg     case 'x':
1428627f7eb2Smrg     case 'y':
1429627f7eb2Smrg     case 'z':
1430627f7eb2Smrg     case 'A':
1431627f7eb2Smrg     case 'B':
1432627f7eb2Smrg     case 'C':
1433627f7eb2Smrg     case 'D':
1434627f7eb2Smrg     case 'E':
1435627f7eb2Smrg     case 'F':
1436627f7eb2Smrg     case 'G':
1437627f7eb2Smrg     case 'H':
1438627f7eb2Smrg     case 'I':
1439627f7eb2Smrg     case 'J':
1440627f7eb2Smrg     case 'K':
1441627f7eb2Smrg     case 'L':
1442627f7eb2Smrg     case 'M':
1443627f7eb2Smrg     case 'N':
1444627f7eb2Smrg     case 'O':
1445627f7eb2Smrg     case 'P':
1446627f7eb2Smrg     case 'Q':
1447627f7eb2Smrg     case 'R':
1448627f7eb2Smrg     case 'S':
1449627f7eb2Smrg     case 'T':
1450627f7eb2Smrg     case 'U':
1451627f7eb2Smrg     case 'V':
1452627f7eb2Smrg     case 'W':
1453627f7eb2Smrg     case 'X':
1454627f7eb2Smrg     case 'Y':
1455627f7eb2Smrg     case 'Z':
1456627f7eb2Smrg       parse_name (c);
1457627f7eb2Smrg       return ATOM_NAME;
1458627f7eb2Smrg 
1459627f7eb2Smrg     default:
1460627f7eb2Smrg       bad_module ("Bad name");
1461627f7eb2Smrg     }
1462627f7eb2Smrg 
1463627f7eb2Smrg   /* Not reached.  */
1464627f7eb2Smrg }
1465627f7eb2Smrg 
1466627f7eb2Smrg 
1467627f7eb2Smrg /* Peek at the next atom on the input.  */
1468627f7eb2Smrg 
1469627f7eb2Smrg static atom_type
peek_atom(void)1470627f7eb2Smrg peek_atom (void)
1471627f7eb2Smrg {
1472627f7eb2Smrg   int c;
1473627f7eb2Smrg 
1474627f7eb2Smrg   do
1475627f7eb2Smrg     {
1476627f7eb2Smrg       c = module_char ();
1477627f7eb2Smrg     }
1478627f7eb2Smrg   while (c == ' ' || c == '\r' || c == '\n');
1479627f7eb2Smrg 
1480627f7eb2Smrg   switch (c)
1481627f7eb2Smrg     {
1482627f7eb2Smrg     case '(':
1483627f7eb2Smrg       module_unget_char ();
1484627f7eb2Smrg       return ATOM_LPAREN;
1485627f7eb2Smrg 
1486627f7eb2Smrg     case ')':
1487627f7eb2Smrg       module_unget_char ();
1488627f7eb2Smrg       return ATOM_RPAREN;
1489627f7eb2Smrg 
1490627f7eb2Smrg     case '\'':
1491627f7eb2Smrg       module_unget_char ();
1492627f7eb2Smrg       return ATOM_STRING;
1493627f7eb2Smrg 
1494627f7eb2Smrg     case '0':
1495627f7eb2Smrg     case '1':
1496627f7eb2Smrg     case '2':
1497627f7eb2Smrg     case '3':
1498627f7eb2Smrg     case '4':
1499627f7eb2Smrg     case '5':
1500627f7eb2Smrg     case '6':
1501627f7eb2Smrg     case '7':
1502627f7eb2Smrg     case '8':
1503627f7eb2Smrg     case '9':
1504627f7eb2Smrg       module_unget_char ();
1505627f7eb2Smrg       return ATOM_INTEGER;
1506627f7eb2Smrg 
1507627f7eb2Smrg     case 'a':
1508627f7eb2Smrg     case 'b':
1509627f7eb2Smrg     case 'c':
1510627f7eb2Smrg     case 'd':
1511627f7eb2Smrg     case 'e':
1512627f7eb2Smrg     case 'f':
1513627f7eb2Smrg     case 'g':
1514627f7eb2Smrg     case 'h':
1515627f7eb2Smrg     case 'i':
1516627f7eb2Smrg     case 'j':
1517627f7eb2Smrg     case 'k':
1518627f7eb2Smrg     case 'l':
1519627f7eb2Smrg     case 'm':
1520627f7eb2Smrg     case 'n':
1521627f7eb2Smrg     case 'o':
1522627f7eb2Smrg     case 'p':
1523627f7eb2Smrg     case 'q':
1524627f7eb2Smrg     case 'r':
1525627f7eb2Smrg     case 's':
1526627f7eb2Smrg     case 't':
1527627f7eb2Smrg     case 'u':
1528627f7eb2Smrg     case 'v':
1529627f7eb2Smrg     case 'w':
1530627f7eb2Smrg     case 'x':
1531627f7eb2Smrg     case 'y':
1532627f7eb2Smrg     case 'z':
1533627f7eb2Smrg     case 'A':
1534627f7eb2Smrg     case 'B':
1535627f7eb2Smrg     case 'C':
1536627f7eb2Smrg     case 'D':
1537627f7eb2Smrg     case 'E':
1538627f7eb2Smrg     case 'F':
1539627f7eb2Smrg     case 'G':
1540627f7eb2Smrg     case 'H':
1541627f7eb2Smrg     case 'I':
1542627f7eb2Smrg     case 'J':
1543627f7eb2Smrg     case 'K':
1544627f7eb2Smrg     case 'L':
1545627f7eb2Smrg     case 'M':
1546627f7eb2Smrg     case 'N':
1547627f7eb2Smrg     case 'O':
1548627f7eb2Smrg     case 'P':
1549627f7eb2Smrg     case 'Q':
1550627f7eb2Smrg     case 'R':
1551627f7eb2Smrg     case 'S':
1552627f7eb2Smrg     case 'T':
1553627f7eb2Smrg     case 'U':
1554627f7eb2Smrg     case 'V':
1555627f7eb2Smrg     case 'W':
1556627f7eb2Smrg     case 'X':
1557627f7eb2Smrg     case 'Y':
1558627f7eb2Smrg     case 'Z':
1559627f7eb2Smrg       module_unget_char ();
1560627f7eb2Smrg       return ATOM_NAME;
1561627f7eb2Smrg 
1562627f7eb2Smrg     default:
1563627f7eb2Smrg       bad_module ("Bad name");
1564627f7eb2Smrg     }
1565627f7eb2Smrg }
1566627f7eb2Smrg 
1567627f7eb2Smrg 
1568627f7eb2Smrg /* Read the next atom from the input, requiring that it be a
1569627f7eb2Smrg    particular kind.  */
1570627f7eb2Smrg 
1571627f7eb2Smrg static void
require_atom(atom_type type)1572627f7eb2Smrg require_atom (atom_type type)
1573627f7eb2Smrg {
1574627f7eb2Smrg   atom_type t;
1575627f7eb2Smrg   const char *p;
1576627f7eb2Smrg   int column, line;
1577627f7eb2Smrg 
1578627f7eb2Smrg   column = module_column;
1579627f7eb2Smrg   line = module_line;
1580627f7eb2Smrg 
1581627f7eb2Smrg   t = parse_atom ();
1582627f7eb2Smrg   if (t != type)
1583627f7eb2Smrg     {
1584627f7eb2Smrg       switch (type)
1585627f7eb2Smrg 	{
1586627f7eb2Smrg 	case ATOM_NAME:
1587627f7eb2Smrg 	  p = _("Expected name");
1588627f7eb2Smrg 	  break;
1589627f7eb2Smrg 	case ATOM_LPAREN:
1590627f7eb2Smrg 	  p = _("Expected left parenthesis");
1591627f7eb2Smrg 	  break;
1592627f7eb2Smrg 	case ATOM_RPAREN:
1593627f7eb2Smrg 	  p = _("Expected right parenthesis");
1594627f7eb2Smrg 	  break;
1595627f7eb2Smrg 	case ATOM_INTEGER:
1596627f7eb2Smrg 	  p = _("Expected integer");
1597627f7eb2Smrg 	  break;
1598627f7eb2Smrg 	case ATOM_STRING:
1599627f7eb2Smrg 	  p = _("Expected string");
1600627f7eb2Smrg 	  break;
1601627f7eb2Smrg 	default:
1602627f7eb2Smrg 	  gfc_internal_error ("require_atom(): bad atom type required");
1603627f7eb2Smrg 	}
1604627f7eb2Smrg 
1605627f7eb2Smrg       module_column = column;
1606627f7eb2Smrg       module_line = line;
1607627f7eb2Smrg       bad_module (p);
1608627f7eb2Smrg     }
1609627f7eb2Smrg }
1610627f7eb2Smrg 
1611627f7eb2Smrg 
1612627f7eb2Smrg /* Given a pointer to an mstring array, require that the current input
1613627f7eb2Smrg    be one of the strings in the array.  We return the enum value.  */
1614627f7eb2Smrg 
1615627f7eb2Smrg static int
find_enum(const mstring * m)1616627f7eb2Smrg find_enum (const mstring *m)
1617627f7eb2Smrg {
1618627f7eb2Smrg   int i;
1619627f7eb2Smrg 
1620627f7eb2Smrg   i = gfc_string2code (m, atom_name);
1621627f7eb2Smrg   if (i >= 0)
1622627f7eb2Smrg     return i;
1623627f7eb2Smrg 
1624627f7eb2Smrg   bad_module ("find_enum(): Enum not found");
1625627f7eb2Smrg 
1626627f7eb2Smrg   /* Not reached.  */
1627627f7eb2Smrg }
1628627f7eb2Smrg 
1629627f7eb2Smrg 
1630627f7eb2Smrg /* Read a string. The caller is responsible for freeing.  */
1631627f7eb2Smrg 
1632627f7eb2Smrg static char*
read_string(void)1633627f7eb2Smrg read_string (void)
1634627f7eb2Smrg {
1635627f7eb2Smrg   char* p;
1636627f7eb2Smrg   require_atom (ATOM_STRING);
1637627f7eb2Smrg   p = atom_string;
1638627f7eb2Smrg   atom_string = NULL;
1639627f7eb2Smrg   return p;
1640627f7eb2Smrg }
1641627f7eb2Smrg 
1642627f7eb2Smrg 
1643627f7eb2Smrg /**************** Module output subroutines ***************************/
1644627f7eb2Smrg 
1645627f7eb2Smrg /* Output a character to a module file.  */
1646627f7eb2Smrg 
1647627f7eb2Smrg static void
write_char(char out)1648627f7eb2Smrg write_char (char out)
1649627f7eb2Smrg {
1650627f7eb2Smrg   if (gzputc (module_fp, out) == EOF)
1651627f7eb2Smrg     gfc_fatal_error ("Error writing modules file: %s", xstrerror (errno));
1652627f7eb2Smrg 
1653627f7eb2Smrg   if (out != '\n')
1654627f7eb2Smrg     module_column++;
1655627f7eb2Smrg   else
1656627f7eb2Smrg     {
1657627f7eb2Smrg       module_column = 1;
1658627f7eb2Smrg       module_line++;
1659627f7eb2Smrg     }
1660627f7eb2Smrg }
1661627f7eb2Smrg 
1662627f7eb2Smrg 
1663627f7eb2Smrg /* Write an atom to a module.  The line wrapping isn't perfect, but it
1664627f7eb2Smrg    should work most of the time.  This isn't that big of a deal, since
1665627f7eb2Smrg    the file really isn't meant to be read by people anyway.  */
1666627f7eb2Smrg 
1667627f7eb2Smrg static void
write_atom(atom_type atom,const void * v)1668627f7eb2Smrg write_atom (atom_type atom, const void *v)
1669627f7eb2Smrg {
1670627f7eb2Smrg   char buffer[32];
1671627f7eb2Smrg 
1672627f7eb2Smrg   /* Workaround -Wmaybe-uninitialized false positive during
1673627f7eb2Smrg      profiledbootstrap by initializing them.  */
1674627f7eb2Smrg   int len;
1675627f7eb2Smrg   HOST_WIDE_INT i = 0;
1676627f7eb2Smrg   const char *p;
1677627f7eb2Smrg 
1678627f7eb2Smrg   switch (atom)
1679627f7eb2Smrg     {
1680627f7eb2Smrg     case ATOM_STRING:
1681627f7eb2Smrg     case ATOM_NAME:
1682627f7eb2Smrg       p = (const char *) v;
1683627f7eb2Smrg       break;
1684627f7eb2Smrg 
1685627f7eb2Smrg     case ATOM_LPAREN:
1686627f7eb2Smrg       p = "(";
1687627f7eb2Smrg       break;
1688627f7eb2Smrg 
1689627f7eb2Smrg     case ATOM_RPAREN:
1690627f7eb2Smrg       p = ")";
1691627f7eb2Smrg       break;
1692627f7eb2Smrg 
1693627f7eb2Smrg     case ATOM_INTEGER:
1694627f7eb2Smrg       i = *((const HOST_WIDE_INT *) v);
1695627f7eb2Smrg 
1696627f7eb2Smrg       snprintf (buffer, sizeof (buffer), HOST_WIDE_INT_PRINT_DEC, i);
1697627f7eb2Smrg       p = buffer;
1698627f7eb2Smrg       break;
1699627f7eb2Smrg 
1700627f7eb2Smrg     default:
1701627f7eb2Smrg       gfc_internal_error ("write_atom(): Trying to write dab atom");
1702627f7eb2Smrg 
1703627f7eb2Smrg     }
1704627f7eb2Smrg 
1705627f7eb2Smrg   if(p == NULL || *p == '\0')
1706627f7eb2Smrg      len = 0;
1707627f7eb2Smrg   else
1708627f7eb2Smrg   len = strlen (p);
1709627f7eb2Smrg 
1710627f7eb2Smrg   if (atom != ATOM_RPAREN)
1711627f7eb2Smrg     {
1712627f7eb2Smrg       if (module_column + len > 72)
1713627f7eb2Smrg 	write_char ('\n');
1714627f7eb2Smrg       else
1715627f7eb2Smrg 	{
1716627f7eb2Smrg 
1717627f7eb2Smrg 	  if (last_atom != ATOM_LPAREN && module_column != 1)
1718627f7eb2Smrg 	    write_char (' ');
1719627f7eb2Smrg 	}
1720627f7eb2Smrg     }
1721627f7eb2Smrg 
1722627f7eb2Smrg   if (atom == ATOM_STRING)
1723627f7eb2Smrg     write_char ('\'');
1724627f7eb2Smrg 
1725627f7eb2Smrg   while (p != NULL && *p)
1726627f7eb2Smrg     {
1727627f7eb2Smrg       if (atom == ATOM_STRING && *p == '\'')
1728627f7eb2Smrg 	write_char ('\'');
1729627f7eb2Smrg       write_char (*p++);
1730627f7eb2Smrg     }
1731627f7eb2Smrg 
1732627f7eb2Smrg   if (atom == ATOM_STRING)
1733627f7eb2Smrg     write_char ('\'');
1734627f7eb2Smrg 
1735627f7eb2Smrg   last_atom = atom;
1736627f7eb2Smrg }
1737627f7eb2Smrg 
1738627f7eb2Smrg 
1739627f7eb2Smrg 
1740627f7eb2Smrg /***************** Mid-level I/O subroutines *****************/
1741627f7eb2Smrg 
1742627f7eb2Smrg /* These subroutines let their caller read or write atoms without
1743627f7eb2Smrg    caring about which of the two is actually happening.  This lets a
1744627f7eb2Smrg    subroutine concentrate on the actual format of the data being
1745627f7eb2Smrg    written.  */
1746627f7eb2Smrg 
1747627f7eb2Smrg static void mio_expr (gfc_expr **);
1748627f7eb2Smrg pointer_info *mio_symbol_ref (gfc_symbol **);
1749627f7eb2Smrg pointer_info *mio_interface_rest (gfc_interface **);
1750627f7eb2Smrg static void mio_symtree_ref (gfc_symtree **);
1751627f7eb2Smrg 
1752627f7eb2Smrg /* Read or write an enumerated value.  On writing, we return the input
1753627f7eb2Smrg    value for the convenience of callers.  We avoid using an integer
1754627f7eb2Smrg    pointer because enums are sometimes inside bitfields.  */
1755627f7eb2Smrg 
1756627f7eb2Smrg static int
mio_name(int t,const mstring * m)1757627f7eb2Smrg mio_name (int t, const mstring *m)
1758627f7eb2Smrg {
1759627f7eb2Smrg   if (iomode == IO_OUTPUT)
1760627f7eb2Smrg     write_atom (ATOM_NAME, gfc_code2string (m, t));
1761627f7eb2Smrg   else
1762627f7eb2Smrg     {
1763627f7eb2Smrg       require_atom (ATOM_NAME);
1764627f7eb2Smrg       t = find_enum (m);
1765627f7eb2Smrg     }
1766627f7eb2Smrg 
1767627f7eb2Smrg   return t;
1768627f7eb2Smrg }
1769627f7eb2Smrg 
1770627f7eb2Smrg /* Specialization of mio_name.  */
1771627f7eb2Smrg 
1772627f7eb2Smrg #define DECL_MIO_NAME(TYPE) \
1773627f7eb2Smrg  static inline TYPE \
1774627f7eb2Smrg  MIO_NAME(TYPE) (TYPE t, const mstring *m) \
1775627f7eb2Smrg  { \
1776627f7eb2Smrg    return (TYPE) mio_name ((int) t, m); \
1777627f7eb2Smrg  }
1778627f7eb2Smrg #define MIO_NAME(TYPE) mio_name_##TYPE
1779627f7eb2Smrg 
1780627f7eb2Smrg static void
mio_lparen(void)1781627f7eb2Smrg mio_lparen (void)
1782627f7eb2Smrg {
1783627f7eb2Smrg   if (iomode == IO_OUTPUT)
1784627f7eb2Smrg     write_atom (ATOM_LPAREN, NULL);
1785627f7eb2Smrg   else
1786627f7eb2Smrg     require_atom (ATOM_LPAREN);
1787627f7eb2Smrg }
1788627f7eb2Smrg 
1789627f7eb2Smrg 
1790627f7eb2Smrg static void
mio_rparen(void)1791627f7eb2Smrg mio_rparen (void)
1792627f7eb2Smrg {
1793627f7eb2Smrg   if (iomode == IO_OUTPUT)
1794627f7eb2Smrg     write_atom (ATOM_RPAREN, NULL);
1795627f7eb2Smrg   else
1796627f7eb2Smrg     require_atom (ATOM_RPAREN);
1797627f7eb2Smrg }
1798627f7eb2Smrg 
1799627f7eb2Smrg 
1800627f7eb2Smrg static void
mio_integer(int * ip)1801627f7eb2Smrg mio_integer (int *ip)
1802627f7eb2Smrg {
1803627f7eb2Smrg   if (iomode == IO_OUTPUT)
1804627f7eb2Smrg     {
1805627f7eb2Smrg       HOST_WIDE_INT hwi = *ip;
1806627f7eb2Smrg       write_atom (ATOM_INTEGER, &hwi);
1807627f7eb2Smrg     }
1808627f7eb2Smrg   else
1809627f7eb2Smrg     {
1810627f7eb2Smrg       require_atom (ATOM_INTEGER);
1811627f7eb2Smrg       *ip = atom_int;
1812627f7eb2Smrg     }
1813627f7eb2Smrg }
1814627f7eb2Smrg 
1815627f7eb2Smrg static void
mio_hwi(HOST_WIDE_INT * hwi)1816627f7eb2Smrg mio_hwi (HOST_WIDE_INT *hwi)
1817627f7eb2Smrg {
1818627f7eb2Smrg   if (iomode == IO_OUTPUT)
1819627f7eb2Smrg     write_atom (ATOM_INTEGER, hwi);
1820627f7eb2Smrg   else
1821627f7eb2Smrg     {
1822627f7eb2Smrg       require_atom (ATOM_INTEGER);
1823627f7eb2Smrg       *hwi = atom_int;
1824627f7eb2Smrg     }
1825627f7eb2Smrg }
1826627f7eb2Smrg 
1827627f7eb2Smrg 
1828627f7eb2Smrg /* Read or write a gfc_intrinsic_op value.  */
1829627f7eb2Smrg 
1830627f7eb2Smrg static void
mio_intrinsic_op(gfc_intrinsic_op * op)1831627f7eb2Smrg mio_intrinsic_op (gfc_intrinsic_op* op)
1832627f7eb2Smrg {
1833627f7eb2Smrg   /* FIXME: Would be nicer to do this via the operators symbolic name.  */
1834627f7eb2Smrg   if (iomode == IO_OUTPUT)
1835627f7eb2Smrg     {
1836627f7eb2Smrg       HOST_WIDE_INT converted = (HOST_WIDE_INT) *op;
1837627f7eb2Smrg       write_atom (ATOM_INTEGER, &converted);
1838627f7eb2Smrg     }
1839627f7eb2Smrg   else
1840627f7eb2Smrg     {
1841627f7eb2Smrg       require_atom (ATOM_INTEGER);
1842627f7eb2Smrg       *op = (gfc_intrinsic_op) atom_int;
1843627f7eb2Smrg     }
1844627f7eb2Smrg }
1845627f7eb2Smrg 
1846627f7eb2Smrg 
1847627f7eb2Smrg /* Read or write a character pointer that points to a string on the heap.  */
1848627f7eb2Smrg 
1849627f7eb2Smrg static const char *
mio_allocated_string(const char * s)1850627f7eb2Smrg mio_allocated_string (const char *s)
1851627f7eb2Smrg {
1852627f7eb2Smrg   if (iomode == IO_OUTPUT)
1853627f7eb2Smrg     {
1854627f7eb2Smrg       write_atom (ATOM_STRING, s);
1855627f7eb2Smrg       return s;
1856627f7eb2Smrg     }
1857627f7eb2Smrg   else
1858627f7eb2Smrg     {
1859627f7eb2Smrg       require_atom (ATOM_STRING);
1860627f7eb2Smrg       return atom_string;
1861627f7eb2Smrg     }
1862627f7eb2Smrg }
1863627f7eb2Smrg 
1864627f7eb2Smrg 
1865627f7eb2Smrg /* Functions for quoting and unquoting strings.  */
1866627f7eb2Smrg 
1867627f7eb2Smrg static char *
quote_string(const gfc_char_t * s,const size_t slength)1868627f7eb2Smrg quote_string (const gfc_char_t *s, const size_t slength)
1869627f7eb2Smrg {
1870627f7eb2Smrg   const gfc_char_t *p;
1871627f7eb2Smrg   char *res, *q;
1872627f7eb2Smrg   size_t len = 0, i;
1873627f7eb2Smrg 
1874627f7eb2Smrg   /* Calculate the length we'll need: a backslash takes two ("\\"),
1875627f7eb2Smrg      non-printable characters take 10 ("\Uxxxxxxxx") and others take 1.  */
1876627f7eb2Smrg   for (p = s, i = 0; i < slength; p++, i++)
1877627f7eb2Smrg     {
1878627f7eb2Smrg       if (*p == '\\')
1879627f7eb2Smrg 	len += 2;
1880627f7eb2Smrg       else if (!gfc_wide_is_printable (*p))
1881627f7eb2Smrg 	len += 10;
1882627f7eb2Smrg       else
1883627f7eb2Smrg 	len++;
1884627f7eb2Smrg     }
1885627f7eb2Smrg 
1886627f7eb2Smrg   q = res = XCNEWVEC (char, len + 1);
1887627f7eb2Smrg   for (p = s, i = 0; i < slength; p++, i++)
1888627f7eb2Smrg     {
1889627f7eb2Smrg       if (*p == '\\')
1890627f7eb2Smrg 	*q++ = '\\', *q++ = '\\';
1891627f7eb2Smrg       else if (!gfc_wide_is_printable (*p))
1892627f7eb2Smrg 	{
1893627f7eb2Smrg 	  sprintf (q, "\\U%08" HOST_WIDE_INT_PRINT "x",
1894627f7eb2Smrg 		   (unsigned HOST_WIDE_INT) *p);
1895627f7eb2Smrg 	  q += 10;
1896627f7eb2Smrg 	}
1897627f7eb2Smrg       else
1898627f7eb2Smrg 	*q++ = (unsigned char) *p;
1899627f7eb2Smrg     }
1900627f7eb2Smrg 
1901627f7eb2Smrg   res[len] = '\0';
1902627f7eb2Smrg   return res;
1903627f7eb2Smrg }
1904627f7eb2Smrg 
1905627f7eb2Smrg static gfc_char_t *
unquote_string(const char * s)1906627f7eb2Smrg unquote_string (const char *s)
1907627f7eb2Smrg {
1908627f7eb2Smrg   size_t len, i;
1909627f7eb2Smrg   const char *p;
1910627f7eb2Smrg   gfc_char_t *res;
1911627f7eb2Smrg 
1912627f7eb2Smrg   for (p = s, len = 0; *p; p++, len++)
1913627f7eb2Smrg     {
1914627f7eb2Smrg       if (*p != '\\')
1915627f7eb2Smrg 	continue;
1916627f7eb2Smrg 
1917627f7eb2Smrg       if (p[1] == '\\')
1918627f7eb2Smrg 	p++;
1919627f7eb2Smrg       else if (p[1] == 'U')
1920627f7eb2Smrg 	p += 9; /* That is a "\U????????".  */
1921627f7eb2Smrg       else
1922627f7eb2Smrg 	gfc_internal_error ("unquote_string(): got bad string");
1923627f7eb2Smrg     }
1924627f7eb2Smrg 
1925627f7eb2Smrg   res = gfc_get_wide_string (len + 1);
1926627f7eb2Smrg   for (i = 0, p = s; i < len; i++, p++)
1927627f7eb2Smrg     {
1928627f7eb2Smrg       gcc_assert (*p);
1929627f7eb2Smrg 
1930627f7eb2Smrg       if (*p != '\\')
1931627f7eb2Smrg 	res[i] = (unsigned char) *p;
1932627f7eb2Smrg       else if (p[1] == '\\')
1933627f7eb2Smrg 	{
1934627f7eb2Smrg 	  res[i] = (unsigned char) '\\';
1935627f7eb2Smrg 	  p++;
1936627f7eb2Smrg 	}
1937627f7eb2Smrg       else
1938627f7eb2Smrg 	{
1939627f7eb2Smrg 	  /* We read the 8-digits hexadecimal constant that follows.  */
1940627f7eb2Smrg 	  int j;
1941627f7eb2Smrg 	  unsigned n;
1942627f7eb2Smrg 	  gfc_char_t c = 0;
1943627f7eb2Smrg 
1944627f7eb2Smrg 	  gcc_assert (p[1] == 'U');
1945627f7eb2Smrg 	  for (j = 0; j < 8; j++)
1946627f7eb2Smrg 	    {
1947627f7eb2Smrg 	      c = c << 4;
1948627f7eb2Smrg 	      gcc_assert (sscanf (&p[j+2], "%01x", &n) == 1);
1949627f7eb2Smrg 	      c += n;
1950627f7eb2Smrg 	    }
1951627f7eb2Smrg 
1952627f7eb2Smrg 	  res[i] = c;
1953627f7eb2Smrg 	  p += 9;
1954627f7eb2Smrg 	}
1955627f7eb2Smrg     }
1956627f7eb2Smrg 
1957627f7eb2Smrg   res[len] = '\0';
1958627f7eb2Smrg   return res;
1959627f7eb2Smrg }
1960627f7eb2Smrg 
1961627f7eb2Smrg 
1962627f7eb2Smrg /* Read or write a character pointer that points to a wide string on the
1963627f7eb2Smrg    heap, performing quoting/unquoting of nonprintable characters using the
1964627f7eb2Smrg    form \U???????? (where each ? is a hexadecimal digit).
1965627f7eb2Smrg    Length is the length of the string, only known and used in output mode.  */
1966627f7eb2Smrg 
1967627f7eb2Smrg static const gfc_char_t *
mio_allocated_wide_string(const gfc_char_t * s,const size_t length)1968627f7eb2Smrg mio_allocated_wide_string (const gfc_char_t *s, const size_t length)
1969627f7eb2Smrg {
1970627f7eb2Smrg   if (iomode == IO_OUTPUT)
1971627f7eb2Smrg     {
1972627f7eb2Smrg       char *quoted = quote_string (s, length);
1973627f7eb2Smrg       write_atom (ATOM_STRING, quoted);
1974627f7eb2Smrg       free (quoted);
1975627f7eb2Smrg       return s;
1976627f7eb2Smrg     }
1977627f7eb2Smrg   else
1978627f7eb2Smrg     {
1979627f7eb2Smrg       gfc_char_t *unquoted;
1980627f7eb2Smrg 
1981627f7eb2Smrg       require_atom (ATOM_STRING);
1982627f7eb2Smrg       unquoted = unquote_string (atom_string);
1983627f7eb2Smrg       free (atom_string);
1984627f7eb2Smrg       return unquoted;
1985627f7eb2Smrg     }
1986627f7eb2Smrg }
1987627f7eb2Smrg 
1988627f7eb2Smrg 
1989627f7eb2Smrg /* Read or write a string that is in static memory.  */
1990627f7eb2Smrg 
1991627f7eb2Smrg static void
mio_pool_string(const char ** stringp)1992627f7eb2Smrg mio_pool_string (const char **stringp)
1993627f7eb2Smrg {
1994627f7eb2Smrg   /* TODO: one could write the string only once, and refer to it via a
1995627f7eb2Smrg      fixup pointer.  */
1996627f7eb2Smrg 
1997627f7eb2Smrg   /* As a special case we have to deal with a NULL string.  This
1998627f7eb2Smrg      happens for the 'module' member of 'gfc_symbol's that are not in a
1999627f7eb2Smrg      module.  We read / write these as the empty string.  */
2000627f7eb2Smrg   if (iomode == IO_OUTPUT)
2001627f7eb2Smrg     {
2002627f7eb2Smrg       const char *p = *stringp == NULL ? "" : *stringp;
2003627f7eb2Smrg       write_atom (ATOM_STRING, p);
2004627f7eb2Smrg     }
2005627f7eb2Smrg   else
2006627f7eb2Smrg     {
2007627f7eb2Smrg       require_atom (ATOM_STRING);
2008627f7eb2Smrg       *stringp = (atom_string[0] == '\0'
2009627f7eb2Smrg 		  ? NULL : gfc_get_string ("%s", atom_string));
2010627f7eb2Smrg       free (atom_string);
2011627f7eb2Smrg     }
2012627f7eb2Smrg }
2013627f7eb2Smrg 
2014627f7eb2Smrg 
2015627f7eb2Smrg /* Read or write a string that is inside of some already-allocated
2016627f7eb2Smrg    structure.  */
2017627f7eb2Smrg 
2018627f7eb2Smrg static void
mio_internal_string(char * string)2019627f7eb2Smrg mio_internal_string (char *string)
2020627f7eb2Smrg {
2021627f7eb2Smrg   if (iomode == IO_OUTPUT)
2022627f7eb2Smrg     write_atom (ATOM_STRING, string);
2023627f7eb2Smrg   else
2024627f7eb2Smrg     {
2025627f7eb2Smrg       require_atom (ATOM_STRING);
2026627f7eb2Smrg       strcpy (string, atom_string);
2027627f7eb2Smrg       free (atom_string);
2028627f7eb2Smrg     }
2029627f7eb2Smrg }
2030627f7eb2Smrg 
2031627f7eb2Smrg 
2032627f7eb2Smrg enum ab_attribute
2033627f7eb2Smrg { AB_ALLOCATABLE, AB_DIMENSION, AB_EXTERNAL, AB_INTRINSIC, AB_OPTIONAL,
2034627f7eb2Smrg   AB_POINTER, AB_TARGET, AB_DUMMY, AB_RESULT, AB_DATA,
2035627f7eb2Smrg   AB_IN_NAMELIST, AB_IN_COMMON, AB_FUNCTION, AB_SUBROUTINE, AB_SEQUENCE,
2036627f7eb2Smrg   AB_ELEMENTAL, AB_PURE, AB_RECURSIVE, AB_GENERIC, AB_ALWAYS_EXPLICIT,
2037627f7eb2Smrg   AB_CRAY_POINTER, AB_CRAY_POINTEE, AB_THREADPRIVATE,
2038627f7eb2Smrg   AB_ALLOC_COMP, AB_POINTER_COMP, AB_PROC_POINTER_COMP, AB_PRIVATE_COMP,
2039627f7eb2Smrg   AB_VALUE, AB_VOLATILE, AB_PROTECTED, AB_LOCK_COMP, AB_EVENT_COMP,
2040627f7eb2Smrg   AB_IS_BIND_C, AB_IS_C_INTEROP, AB_IS_ISO_C, AB_ABSTRACT, AB_ZERO_COMP,
2041627f7eb2Smrg   AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS, AB_CODIMENSION,
2042627f7eb2Smrg   AB_COARRAY_COMP, AB_VTYPE, AB_VTAB, AB_CONTIGUOUS, AB_CLASS_POINTER,
2043627f7eb2Smrg   AB_IMPLICIT_PURE, AB_ARTIFICIAL, AB_UNLIMITED_POLY, AB_OMP_DECLARE_TARGET,
2044627f7eb2Smrg   AB_ARRAY_OUTER_DEPENDENCY, AB_MODULE_PROCEDURE, AB_OACC_DECLARE_CREATE,
2045627f7eb2Smrg   AB_OACC_DECLARE_COPYIN, AB_OACC_DECLARE_DEVICEPTR,
2046627f7eb2Smrg   AB_OACC_DECLARE_DEVICE_RESIDENT, AB_OACC_DECLARE_LINK,
2047627f7eb2Smrg   AB_OMP_DECLARE_TARGET_LINK, AB_PDT_KIND, AB_PDT_LEN, AB_PDT_TYPE,
2048627f7eb2Smrg   AB_PDT_TEMPLATE, AB_PDT_ARRAY, AB_PDT_STRING,
2049627f7eb2Smrg   AB_OACC_ROUTINE_LOP_GANG, AB_OACC_ROUTINE_LOP_WORKER,
2050627f7eb2Smrg   AB_OACC_ROUTINE_LOP_VECTOR, AB_OACC_ROUTINE_LOP_SEQ
2051627f7eb2Smrg };
2052627f7eb2Smrg 
2053627f7eb2Smrg static const mstring attr_bits[] =
2054627f7eb2Smrg {
2055627f7eb2Smrg     minit ("ALLOCATABLE", AB_ALLOCATABLE),
2056627f7eb2Smrg     minit ("ARTIFICIAL", AB_ARTIFICIAL),
2057627f7eb2Smrg     minit ("ASYNCHRONOUS", AB_ASYNCHRONOUS),
2058627f7eb2Smrg     minit ("DIMENSION", AB_DIMENSION),
2059627f7eb2Smrg     minit ("CODIMENSION", AB_CODIMENSION),
2060627f7eb2Smrg     minit ("CONTIGUOUS", AB_CONTIGUOUS),
2061627f7eb2Smrg     minit ("EXTERNAL", AB_EXTERNAL),
2062627f7eb2Smrg     minit ("INTRINSIC", AB_INTRINSIC),
2063627f7eb2Smrg     minit ("OPTIONAL", AB_OPTIONAL),
2064627f7eb2Smrg     minit ("POINTER", AB_POINTER),
2065627f7eb2Smrg     minit ("VOLATILE", AB_VOLATILE),
2066627f7eb2Smrg     minit ("TARGET", AB_TARGET),
2067627f7eb2Smrg     minit ("THREADPRIVATE", AB_THREADPRIVATE),
2068627f7eb2Smrg     minit ("DUMMY", AB_DUMMY),
2069627f7eb2Smrg     minit ("RESULT", AB_RESULT),
2070627f7eb2Smrg     minit ("DATA", AB_DATA),
2071627f7eb2Smrg     minit ("IN_NAMELIST", AB_IN_NAMELIST),
2072627f7eb2Smrg     minit ("IN_COMMON", AB_IN_COMMON),
2073627f7eb2Smrg     minit ("FUNCTION", AB_FUNCTION),
2074627f7eb2Smrg     minit ("SUBROUTINE", AB_SUBROUTINE),
2075627f7eb2Smrg     minit ("SEQUENCE", AB_SEQUENCE),
2076627f7eb2Smrg     minit ("ELEMENTAL", AB_ELEMENTAL),
2077627f7eb2Smrg     minit ("PURE", AB_PURE),
2078627f7eb2Smrg     minit ("RECURSIVE", AB_RECURSIVE),
2079627f7eb2Smrg     minit ("GENERIC", AB_GENERIC),
2080627f7eb2Smrg     minit ("ALWAYS_EXPLICIT", AB_ALWAYS_EXPLICIT),
2081627f7eb2Smrg     minit ("CRAY_POINTER", AB_CRAY_POINTER),
2082627f7eb2Smrg     minit ("CRAY_POINTEE", AB_CRAY_POINTEE),
2083627f7eb2Smrg     minit ("IS_BIND_C", AB_IS_BIND_C),
2084627f7eb2Smrg     minit ("IS_C_INTEROP", AB_IS_C_INTEROP),
2085627f7eb2Smrg     minit ("IS_ISO_C", AB_IS_ISO_C),
2086627f7eb2Smrg     minit ("VALUE", AB_VALUE),
2087627f7eb2Smrg     minit ("ALLOC_COMP", AB_ALLOC_COMP),
2088627f7eb2Smrg     minit ("COARRAY_COMP", AB_COARRAY_COMP),
2089627f7eb2Smrg     minit ("LOCK_COMP", AB_LOCK_COMP),
2090627f7eb2Smrg     minit ("EVENT_COMP", AB_EVENT_COMP),
2091627f7eb2Smrg     minit ("POINTER_COMP", AB_POINTER_COMP),
2092627f7eb2Smrg     minit ("PROC_POINTER_COMP", AB_PROC_POINTER_COMP),
2093627f7eb2Smrg     minit ("PRIVATE_COMP", AB_PRIVATE_COMP),
2094627f7eb2Smrg     minit ("ZERO_COMP", AB_ZERO_COMP),
2095627f7eb2Smrg     minit ("PROTECTED", AB_PROTECTED),
2096627f7eb2Smrg     minit ("ABSTRACT", AB_ABSTRACT),
2097627f7eb2Smrg     minit ("IS_CLASS", AB_IS_CLASS),
2098627f7eb2Smrg     minit ("PROCEDURE", AB_PROCEDURE),
2099627f7eb2Smrg     minit ("PROC_POINTER", AB_PROC_POINTER),
2100627f7eb2Smrg     minit ("VTYPE", AB_VTYPE),
2101627f7eb2Smrg     minit ("VTAB", AB_VTAB),
2102627f7eb2Smrg     minit ("CLASS_POINTER", AB_CLASS_POINTER),
2103627f7eb2Smrg     minit ("IMPLICIT_PURE", AB_IMPLICIT_PURE),
2104627f7eb2Smrg     minit ("UNLIMITED_POLY", AB_UNLIMITED_POLY),
2105627f7eb2Smrg     minit ("OMP_DECLARE_TARGET", AB_OMP_DECLARE_TARGET),
2106627f7eb2Smrg     minit ("ARRAY_OUTER_DEPENDENCY", AB_ARRAY_OUTER_DEPENDENCY),
2107627f7eb2Smrg     minit ("MODULE_PROCEDURE", AB_MODULE_PROCEDURE),
2108627f7eb2Smrg     minit ("OACC_DECLARE_CREATE", AB_OACC_DECLARE_CREATE),
2109627f7eb2Smrg     minit ("OACC_DECLARE_COPYIN", AB_OACC_DECLARE_COPYIN),
2110627f7eb2Smrg     minit ("OACC_DECLARE_DEVICEPTR", AB_OACC_DECLARE_DEVICEPTR),
2111627f7eb2Smrg     minit ("OACC_DECLARE_DEVICE_RESIDENT", AB_OACC_DECLARE_DEVICE_RESIDENT),
2112627f7eb2Smrg     minit ("OACC_DECLARE_LINK", AB_OACC_DECLARE_LINK),
2113627f7eb2Smrg     minit ("OMP_DECLARE_TARGET_LINK", AB_OMP_DECLARE_TARGET_LINK),
2114627f7eb2Smrg     minit ("PDT_KIND", AB_PDT_KIND),
2115627f7eb2Smrg     minit ("PDT_LEN", AB_PDT_LEN),
2116627f7eb2Smrg     minit ("PDT_TYPE", AB_PDT_TYPE),
2117627f7eb2Smrg     minit ("PDT_TEMPLATE", AB_PDT_TEMPLATE),
2118627f7eb2Smrg     minit ("PDT_ARRAY", AB_PDT_ARRAY),
2119627f7eb2Smrg     minit ("PDT_STRING", AB_PDT_STRING),
2120627f7eb2Smrg     minit ("OACC_ROUTINE_LOP_GANG", AB_OACC_ROUTINE_LOP_GANG),
2121627f7eb2Smrg     minit ("OACC_ROUTINE_LOP_WORKER", AB_OACC_ROUTINE_LOP_WORKER),
2122627f7eb2Smrg     minit ("OACC_ROUTINE_LOP_VECTOR", AB_OACC_ROUTINE_LOP_VECTOR),
2123627f7eb2Smrg     minit ("OACC_ROUTINE_LOP_SEQ", AB_OACC_ROUTINE_LOP_SEQ),
2124627f7eb2Smrg     minit (NULL, -1)
2125627f7eb2Smrg };
2126627f7eb2Smrg 
2127627f7eb2Smrg /* For binding attributes.  */
2128627f7eb2Smrg static const mstring binding_passing[] =
2129627f7eb2Smrg {
2130627f7eb2Smrg     minit ("PASS", 0),
2131627f7eb2Smrg     minit ("NOPASS", 1),
2132627f7eb2Smrg     minit (NULL, -1)
2133627f7eb2Smrg };
2134627f7eb2Smrg static const mstring binding_overriding[] =
2135627f7eb2Smrg {
2136627f7eb2Smrg     minit ("OVERRIDABLE", 0),
2137627f7eb2Smrg     minit ("NON_OVERRIDABLE", 1),
2138627f7eb2Smrg     minit ("DEFERRED", 2),
2139627f7eb2Smrg     minit (NULL, -1)
2140627f7eb2Smrg };
2141627f7eb2Smrg static const mstring binding_generic[] =
2142627f7eb2Smrg {
2143627f7eb2Smrg     minit ("SPECIFIC", 0),
2144627f7eb2Smrg     minit ("GENERIC", 1),
2145627f7eb2Smrg     minit (NULL, -1)
2146627f7eb2Smrg };
2147627f7eb2Smrg static const mstring binding_ppc[] =
2148627f7eb2Smrg {
2149627f7eb2Smrg     minit ("NO_PPC", 0),
2150627f7eb2Smrg     minit ("PPC", 1),
2151627f7eb2Smrg     minit (NULL, -1)
2152627f7eb2Smrg };
2153627f7eb2Smrg 
2154627f7eb2Smrg /* Specialization of mio_name.  */
2155627f7eb2Smrg DECL_MIO_NAME (ab_attribute)
DECL_MIO_NAME(ar_type)2156627f7eb2Smrg DECL_MIO_NAME (ar_type)
2157627f7eb2Smrg DECL_MIO_NAME (array_type)
2158627f7eb2Smrg DECL_MIO_NAME (bt)
2159627f7eb2Smrg DECL_MIO_NAME (expr_t)
2160627f7eb2Smrg DECL_MIO_NAME (gfc_access)
2161627f7eb2Smrg DECL_MIO_NAME (gfc_intrinsic_op)
2162627f7eb2Smrg DECL_MIO_NAME (ifsrc)
2163627f7eb2Smrg DECL_MIO_NAME (save_state)
2164627f7eb2Smrg DECL_MIO_NAME (procedure_type)
2165627f7eb2Smrg DECL_MIO_NAME (ref_type)
2166627f7eb2Smrg DECL_MIO_NAME (sym_flavor)
2167627f7eb2Smrg DECL_MIO_NAME (sym_intent)
2168627f7eb2Smrg DECL_MIO_NAME (inquiry_type)
2169627f7eb2Smrg #undef DECL_MIO_NAME
2170627f7eb2Smrg 
2171627f7eb2Smrg /* Verify OACC_ROUTINE_LOP_NONE.  */
2172627f7eb2Smrg 
2173627f7eb2Smrg static void
2174627f7eb2Smrg verify_OACC_ROUTINE_LOP_NONE (enum oacc_routine_lop lop)
2175627f7eb2Smrg {
2176627f7eb2Smrg   if (lop != OACC_ROUTINE_LOP_NONE)
2177627f7eb2Smrg     bad_module ("Unsupported: multiple OpenACC 'routine' levels of parallelism");
2178627f7eb2Smrg }
2179627f7eb2Smrg 
2180627f7eb2Smrg /* Symbol attributes are stored in list with the first three elements
2181627f7eb2Smrg    being the enumerated fields, while the remaining elements (if any)
2182627f7eb2Smrg    indicate the individual attribute bits.  The access field is not
2183627f7eb2Smrg    saved-- it controls what symbols are exported when a module is
2184627f7eb2Smrg    written.  */
2185627f7eb2Smrg 
2186627f7eb2Smrg static void
mio_symbol_attribute(symbol_attribute * attr)2187627f7eb2Smrg mio_symbol_attribute (symbol_attribute *attr)
2188627f7eb2Smrg {
2189627f7eb2Smrg   atom_type t;
2190627f7eb2Smrg   unsigned ext_attr,extension_level;
2191627f7eb2Smrg 
2192627f7eb2Smrg   mio_lparen ();
2193627f7eb2Smrg 
2194627f7eb2Smrg   attr->flavor = MIO_NAME (sym_flavor) (attr->flavor, flavors);
2195627f7eb2Smrg   attr->intent = MIO_NAME (sym_intent) (attr->intent, intents);
2196627f7eb2Smrg   attr->proc = MIO_NAME (procedure_type) (attr->proc, procedures);
2197627f7eb2Smrg   attr->if_source = MIO_NAME (ifsrc) (attr->if_source, ifsrc_types);
2198627f7eb2Smrg   attr->save = MIO_NAME (save_state) (attr->save, save_status);
2199627f7eb2Smrg 
2200627f7eb2Smrg   ext_attr = attr->ext_attr;
2201627f7eb2Smrg   mio_integer ((int *) &ext_attr);
2202627f7eb2Smrg   attr->ext_attr = ext_attr;
2203627f7eb2Smrg 
2204627f7eb2Smrg   extension_level = attr->extension;
2205627f7eb2Smrg   mio_integer ((int *) &extension_level);
2206627f7eb2Smrg   attr->extension = extension_level;
2207627f7eb2Smrg 
2208627f7eb2Smrg   if (iomode == IO_OUTPUT)
2209627f7eb2Smrg     {
2210627f7eb2Smrg       if (attr->allocatable)
2211627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_ALLOCATABLE, attr_bits);
2212627f7eb2Smrg       if (attr->artificial)
2213627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_ARTIFICIAL, attr_bits);
2214627f7eb2Smrg       if (attr->asynchronous)
2215627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_ASYNCHRONOUS, attr_bits);
2216627f7eb2Smrg       if (attr->dimension)
2217627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_DIMENSION, attr_bits);
2218627f7eb2Smrg       if (attr->codimension)
2219627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_CODIMENSION, attr_bits);
2220627f7eb2Smrg       if (attr->contiguous)
2221627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_CONTIGUOUS, attr_bits);
2222627f7eb2Smrg       if (attr->external)
2223627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_EXTERNAL, attr_bits);
2224627f7eb2Smrg       if (attr->intrinsic)
2225627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_INTRINSIC, attr_bits);
2226627f7eb2Smrg       if (attr->optional)
2227627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_OPTIONAL, attr_bits);
2228627f7eb2Smrg       if (attr->pointer)
2229627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_POINTER, attr_bits);
2230627f7eb2Smrg       if (attr->class_pointer)
2231627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_CLASS_POINTER, attr_bits);
2232627f7eb2Smrg       if (attr->is_protected)
2233627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PROTECTED, attr_bits);
2234627f7eb2Smrg       if (attr->value)
2235627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_VALUE, attr_bits);
2236627f7eb2Smrg       if (attr->volatile_)
2237627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_VOLATILE, attr_bits);
2238627f7eb2Smrg       if (attr->target)
2239627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_TARGET, attr_bits);
2240627f7eb2Smrg       if (attr->threadprivate)
2241627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_THREADPRIVATE, attr_bits);
2242627f7eb2Smrg       if (attr->dummy)
2243627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_DUMMY, attr_bits);
2244627f7eb2Smrg       if (attr->result)
2245627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_RESULT, attr_bits);
2246627f7eb2Smrg       /* We deliberately don't preserve the "entry" flag.  */
2247627f7eb2Smrg 
2248627f7eb2Smrg       if (attr->data)
2249627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_DATA, attr_bits);
2250627f7eb2Smrg       if (attr->in_namelist)
2251627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_IN_NAMELIST, attr_bits);
2252627f7eb2Smrg       if (attr->in_common)
2253627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_IN_COMMON, attr_bits);
2254627f7eb2Smrg 
2255627f7eb2Smrg       if (attr->function)
2256627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_FUNCTION, attr_bits);
2257627f7eb2Smrg       if (attr->subroutine)
2258627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_SUBROUTINE, attr_bits);
2259627f7eb2Smrg       if (attr->generic)
2260627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_GENERIC, attr_bits);
2261627f7eb2Smrg       if (attr->abstract)
2262627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_ABSTRACT, attr_bits);
2263627f7eb2Smrg 
2264627f7eb2Smrg       if (attr->sequence)
2265627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_SEQUENCE, attr_bits);
2266627f7eb2Smrg       if (attr->elemental)
2267627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_ELEMENTAL, attr_bits);
2268627f7eb2Smrg       if (attr->pure)
2269627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PURE, attr_bits);
2270627f7eb2Smrg       if (attr->implicit_pure)
2271627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_IMPLICIT_PURE, attr_bits);
2272627f7eb2Smrg       if (attr->unlimited_polymorphic)
2273627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_UNLIMITED_POLY, attr_bits);
2274627f7eb2Smrg       if (attr->recursive)
2275627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_RECURSIVE, attr_bits);
2276627f7eb2Smrg       if (attr->always_explicit)
2277627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_ALWAYS_EXPLICIT, attr_bits);
2278627f7eb2Smrg       if (attr->cray_pointer)
2279627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_CRAY_POINTER, attr_bits);
2280627f7eb2Smrg       if (attr->cray_pointee)
2281627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_CRAY_POINTEE, attr_bits);
2282627f7eb2Smrg       if (attr->is_bind_c)
2283627f7eb2Smrg 	MIO_NAME(ab_attribute) (AB_IS_BIND_C, attr_bits);
2284627f7eb2Smrg       if (attr->is_c_interop)
2285627f7eb2Smrg 	MIO_NAME(ab_attribute) (AB_IS_C_INTEROP, attr_bits);
2286627f7eb2Smrg       if (attr->is_iso_c)
2287627f7eb2Smrg 	MIO_NAME(ab_attribute) (AB_IS_ISO_C, attr_bits);
2288627f7eb2Smrg       if (attr->alloc_comp)
2289627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_ALLOC_COMP, attr_bits);
2290627f7eb2Smrg       if (attr->pointer_comp)
2291627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_POINTER_COMP, attr_bits);
2292627f7eb2Smrg       if (attr->proc_pointer_comp)
2293627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PROC_POINTER_COMP, attr_bits);
2294627f7eb2Smrg       if (attr->private_comp)
2295627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PRIVATE_COMP, attr_bits);
2296627f7eb2Smrg       if (attr->coarray_comp)
2297627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_COARRAY_COMP, attr_bits);
2298627f7eb2Smrg       if (attr->lock_comp)
2299627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_LOCK_COMP, attr_bits);
2300627f7eb2Smrg       if (attr->event_comp)
2301627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_EVENT_COMP, attr_bits);
2302627f7eb2Smrg       if (attr->zero_comp)
2303627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_ZERO_COMP, attr_bits);
2304627f7eb2Smrg       if (attr->is_class)
2305627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_IS_CLASS, attr_bits);
2306627f7eb2Smrg       if (attr->procedure)
2307627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PROCEDURE, attr_bits);
2308627f7eb2Smrg       if (attr->proc_pointer)
2309627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PROC_POINTER, attr_bits);
2310627f7eb2Smrg       if (attr->vtype)
2311627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_VTYPE, attr_bits);
2312627f7eb2Smrg       if (attr->vtab)
2313627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_VTAB, attr_bits);
2314627f7eb2Smrg       if (attr->omp_declare_target)
2315627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_OMP_DECLARE_TARGET, attr_bits);
2316627f7eb2Smrg       if (attr->array_outer_dependency)
2317627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_ARRAY_OUTER_DEPENDENCY, attr_bits);
2318627f7eb2Smrg       if (attr->module_procedure)
2319627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_MODULE_PROCEDURE, attr_bits);
2320627f7eb2Smrg       if (attr->oacc_declare_create)
2321627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_OACC_DECLARE_CREATE, attr_bits);
2322627f7eb2Smrg       if (attr->oacc_declare_copyin)
2323627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_OACC_DECLARE_COPYIN, attr_bits);
2324627f7eb2Smrg       if (attr->oacc_declare_deviceptr)
2325627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_OACC_DECLARE_DEVICEPTR, attr_bits);
2326627f7eb2Smrg       if (attr->oacc_declare_device_resident)
2327627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_OACC_DECLARE_DEVICE_RESIDENT, attr_bits);
2328627f7eb2Smrg       if (attr->oacc_declare_link)
2329627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_OACC_DECLARE_LINK, attr_bits);
2330627f7eb2Smrg       if (attr->omp_declare_target_link)
2331627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_OMP_DECLARE_TARGET_LINK, attr_bits);
2332627f7eb2Smrg       if (attr->pdt_kind)
2333627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PDT_KIND, attr_bits);
2334627f7eb2Smrg       if (attr->pdt_len)
2335627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PDT_LEN, attr_bits);
2336627f7eb2Smrg       if (attr->pdt_type)
2337627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PDT_TYPE, attr_bits);
2338627f7eb2Smrg       if (attr->pdt_template)
2339627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PDT_TEMPLATE, attr_bits);
2340627f7eb2Smrg       if (attr->pdt_array)
2341627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PDT_ARRAY, attr_bits);
2342627f7eb2Smrg       if (attr->pdt_string)
2343627f7eb2Smrg 	MIO_NAME (ab_attribute) (AB_PDT_STRING, attr_bits);
2344627f7eb2Smrg       switch (attr->oacc_routine_lop)
2345627f7eb2Smrg 	{
2346627f7eb2Smrg 	case OACC_ROUTINE_LOP_NONE:
2347627f7eb2Smrg 	  /* This is the default anyway, and for maintaining compatibility with
2348627f7eb2Smrg 	     the current MOD_VERSION, we're not emitting anything in that
2349627f7eb2Smrg 	     case.  */
2350627f7eb2Smrg 	  break;
2351627f7eb2Smrg 	case OACC_ROUTINE_LOP_GANG:
2352627f7eb2Smrg 	  MIO_NAME (ab_attribute) (AB_OACC_ROUTINE_LOP_GANG, attr_bits);
2353627f7eb2Smrg 	  break;
2354627f7eb2Smrg 	case OACC_ROUTINE_LOP_WORKER:
2355627f7eb2Smrg 	  MIO_NAME (ab_attribute) (AB_OACC_ROUTINE_LOP_WORKER, attr_bits);
2356627f7eb2Smrg 	  break;
2357627f7eb2Smrg 	case OACC_ROUTINE_LOP_VECTOR:
2358627f7eb2Smrg 	  MIO_NAME (ab_attribute) (AB_OACC_ROUTINE_LOP_VECTOR, attr_bits);
2359627f7eb2Smrg 	  break;
2360627f7eb2Smrg 	case OACC_ROUTINE_LOP_SEQ:
2361627f7eb2Smrg 	  MIO_NAME (ab_attribute) (AB_OACC_ROUTINE_LOP_SEQ, attr_bits);
2362627f7eb2Smrg 	  break;
2363627f7eb2Smrg 	case OACC_ROUTINE_LOP_ERROR:
2364627f7eb2Smrg 	  /* ... intentionally omitted here; it's only unsed internally.  */
2365627f7eb2Smrg 	default:
2366627f7eb2Smrg 	  gcc_unreachable ();
2367627f7eb2Smrg 	}
2368627f7eb2Smrg 
2369627f7eb2Smrg       mio_rparen ();
2370627f7eb2Smrg 
2371627f7eb2Smrg     }
2372627f7eb2Smrg   else
2373627f7eb2Smrg     {
2374627f7eb2Smrg       for (;;)
2375627f7eb2Smrg 	{
2376627f7eb2Smrg 	  t = parse_atom ();
2377627f7eb2Smrg 	  if (t == ATOM_RPAREN)
2378627f7eb2Smrg 	    break;
2379627f7eb2Smrg 	  if (t != ATOM_NAME)
2380627f7eb2Smrg 	    bad_module ("Expected attribute bit name");
2381627f7eb2Smrg 
2382627f7eb2Smrg 	  switch ((ab_attribute) find_enum (attr_bits))
2383627f7eb2Smrg 	    {
2384627f7eb2Smrg 	    case AB_ALLOCATABLE:
2385627f7eb2Smrg 	      attr->allocatable = 1;
2386627f7eb2Smrg 	      break;
2387627f7eb2Smrg 	    case AB_ARTIFICIAL:
2388627f7eb2Smrg 	      attr->artificial = 1;
2389627f7eb2Smrg 	      break;
2390627f7eb2Smrg 	    case AB_ASYNCHRONOUS:
2391627f7eb2Smrg 	      attr->asynchronous = 1;
2392627f7eb2Smrg 	      break;
2393627f7eb2Smrg 	    case AB_DIMENSION:
2394627f7eb2Smrg 	      attr->dimension = 1;
2395627f7eb2Smrg 	      break;
2396627f7eb2Smrg 	    case AB_CODIMENSION:
2397627f7eb2Smrg 	      attr->codimension = 1;
2398627f7eb2Smrg 	      break;
2399627f7eb2Smrg 	    case AB_CONTIGUOUS:
2400627f7eb2Smrg 	      attr->contiguous = 1;
2401627f7eb2Smrg 	      break;
2402627f7eb2Smrg 	    case AB_EXTERNAL:
2403627f7eb2Smrg 	      attr->external = 1;
2404627f7eb2Smrg 	      break;
2405627f7eb2Smrg 	    case AB_INTRINSIC:
2406627f7eb2Smrg 	      attr->intrinsic = 1;
2407627f7eb2Smrg 	      break;
2408627f7eb2Smrg 	    case AB_OPTIONAL:
2409627f7eb2Smrg 	      attr->optional = 1;
2410627f7eb2Smrg 	      break;
2411627f7eb2Smrg 	    case AB_POINTER:
2412627f7eb2Smrg 	      attr->pointer = 1;
2413627f7eb2Smrg 	      break;
2414627f7eb2Smrg 	    case AB_CLASS_POINTER:
2415627f7eb2Smrg 	      attr->class_pointer = 1;
2416627f7eb2Smrg 	      break;
2417627f7eb2Smrg 	    case AB_PROTECTED:
2418627f7eb2Smrg 	      attr->is_protected = 1;
2419627f7eb2Smrg 	      break;
2420627f7eb2Smrg 	    case AB_VALUE:
2421627f7eb2Smrg 	      attr->value = 1;
2422627f7eb2Smrg 	      break;
2423627f7eb2Smrg 	    case AB_VOLATILE:
2424627f7eb2Smrg 	      attr->volatile_ = 1;
2425627f7eb2Smrg 	      break;
2426627f7eb2Smrg 	    case AB_TARGET:
2427627f7eb2Smrg 	      attr->target = 1;
2428627f7eb2Smrg 	      break;
2429627f7eb2Smrg 	    case AB_THREADPRIVATE:
2430627f7eb2Smrg 	      attr->threadprivate = 1;
2431627f7eb2Smrg 	      break;
2432627f7eb2Smrg 	    case AB_DUMMY:
2433627f7eb2Smrg 	      attr->dummy = 1;
2434627f7eb2Smrg 	      break;
2435627f7eb2Smrg 	    case AB_RESULT:
2436627f7eb2Smrg 	      attr->result = 1;
2437627f7eb2Smrg 	      break;
2438627f7eb2Smrg 	    case AB_DATA:
2439627f7eb2Smrg 	      attr->data = 1;
2440627f7eb2Smrg 	      break;
2441627f7eb2Smrg 	    case AB_IN_NAMELIST:
2442627f7eb2Smrg 	      attr->in_namelist = 1;
2443627f7eb2Smrg 	      break;
2444627f7eb2Smrg 	    case AB_IN_COMMON:
2445627f7eb2Smrg 	      attr->in_common = 1;
2446627f7eb2Smrg 	      break;
2447627f7eb2Smrg 	    case AB_FUNCTION:
2448627f7eb2Smrg 	      attr->function = 1;
2449627f7eb2Smrg 	      break;
2450627f7eb2Smrg 	    case AB_SUBROUTINE:
2451627f7eb2Smrg 	      attr->subroutine = 1;
2452627f7eb2Smrg 	      break;
2453627f7eb2Smrg 	    case AB_GENERIC:
2454627f7eb2Smrg 	      attr->generic = 1;
2455627f7eb2Smrg 	      break;
2456627f7eb2Smrg 	    case AB_ABSTRACT:
2457627f7eb2Smrg 	      attr->abstract = 1;
2458627f7eb2Smrg 	      break;
2459627f7eb2Smrg 	    case AB_SEQUENCE:
2460627f7eb2Smrg 	      attr->sequence = 1;
2461627f7eb2Smrg 	      break;
2462627f7eb2Smrg 	    case AB_ELEMENTAL:
2463627f7eb2Smrg 	      attr->elemental = 1;
2464627f7eb2Smrg 	      break;
2465627f7eb2Smrg 	    case AB_PURE:
2466627f7eb2Smrg 	      attr->pure = 1;
2467627f7eb2Smrg 	      break;
2468627f7eb2Smrg 	    case AB_IMPLICIT_PURE:
2469627f7eb2Smrg 	      attr->implicit_pure = 1;
2470627f7eb2Smrg 	      break;
2471627f7eb2Smrg 	    case AB_UNLIMITED_POLY:
2472627f7eb2Smrg 	      attr->unlimited_polymorphic = 1;
2473627f7eb2Smrg 	      break;
2474627f7eb2Smrg 	    case AB_RECURSIVE:
2475627f7eb2Smrg 	      attr->recursive = 1;
2476627f7eb2Smrg 	      break;
2477627f7eb2Smrg 	    case AB_ALWAYS_EXPLICIT:
2478627f7eb2Smrg 	      attr->always_explicit = 1;
2479627f7eb2Smrg 	      break;
2480627f7eb2Smrg 	    case AB_CRAY_POINTER:
2481627f7eb2Smrg 	      attr->cray_pointer = 1;
2482627f7eb2Smrg 	      break;
2483627f7eb2Smrg 	    case AB_CRAY_POINTEE:
2484627f7eb2Smrg 	      attr->cray_pointee = 1;
2485627f7eb2Smrg 	      break;
2486627f7eb2Smrg 	    case AB_IS_BIND_C:
2487627f7eb2Smrg 	      attr->is_bind_c = 1;
2488627f7eb2Smrg 	      break;
2489627f7eb2Smrg 	    case AB_IS_C_INTEROP:
2490627f7eb2Smrg 	      attr->is_c_interop = 1;
2491627f7eb2Smrg 	      break;
2492627f7eb2Smrg 	    case AB_IS_ISO_C:
2493627f7eb2Smrg 	      attr->is_iso_c = 1;
2494627f7eb2Smrg 	      break;
2495627f7eb2Smrg 	    case AB_ALLOC_COMP:
2496627f7eb2Smrg 	      attr->alloc_comp = 1;
2497627f7eb2Smrg 	      break;
2498627f7eb2Smrg 	    case AB_COARRAY_COMP:
2499627f7eb2Smrg 	      attr->coarray_comp = 1;
2500627f7eb2Smrg 	      break;
2501627f7eb2Smrg 	    case AB_LOCK_COMP:
2502627f7eb2Smrg 	      attr->lock_comp = 1;
2503627f7eb2Smrg 	      break;
2504627f7eb2Smrg 	    case AB_EVENT_COMP:
2505627f7eb2Smrg 	      attr->event_comp = 1;
2506627f7eb2Smrg 	      break;
2507627f7eb2Smrg 	    case AB_POINTER_COMP:
2508627f7eb2Smrg 	      attr->pointer_comp = 1;
2509627f7eb2Smrg 	      break;
2510627f7eb2Smrg 	    case AB_PROC_POINTER_COMP:
2511627f7eb2Smrg 	      attr->proc_pointer_comp = 1;
2512627f7eb2Smrg 	      break;
2513627f7eb2Smrg 	    case AB_PRIVATE_COMP:
2514627f7eb2Smrg 	      attr->private_comp = 1;
2515627f7eb2Smrg 	      break;
2516627f7eb2Smrg 	    case AB_ZERO_COMP:
2517627f7eb2Smrg 	      attr->zero_comp = 1;
2518627f7eb2Smrg 	      break;
2519627f7eb2Smrg 	    case AB_IS_CLASS:
2520627f7eb2Smrg 	      attr->is_class = 1;
2521627f7eb2Smrg 	      break;
2522627f7eb2Smrg 	    case AB_PROCEDURE:
2523627f7eb2Smrg 	      attr->procedure = 1;
2524627f7eb2Smrg 	      break;
2525627f7eb2Smrg 	    case AB_PROC_POINTER:
2526627f7eb2Smrg 	      attr->proc_pointer = 1;
2527627f7eb2Smrg 	      break;
2528627f7eb2Smrg 	    case AB_VTYPE:
2529627f7eb2Smrg 	      attr->vtype = 1;
2530627f7eb2Smrg 	      break;
2531627f7eb2Smrg 	    case AB_VTAB:
2532627f7eb2Smrg 	      attr->vtab = 1;
2533627f7eb2Smrg 	      break;
2534627f7eb2Smrg 	    case AB_OMP_DECLARE_TARGET:
2535627f7eb2Smrg 	      attr->omp_declare_target = 1;
2536627f7eb2Smrg 	      break;
2537627f7eb2Smrg 	    case AB_OMP_DECLARE_TARGET_LINK:
2538627f7eb2Smrg 	      attr->omp_declare_target_link = 1;
2539627f7eb2Smrg 	      break;
2540627f7eb2Smrg 	    case AB_ARRAY_OUTER_DEPENDENCY:
2541627f7eb2Smrg 	      attr->array_outer_dependency =1;
2542627f7eb2Smrg 	      break;
2543627f7eb2Smrg 	    case AB_MODULE_PROCEDURE:
2544627f7eb2Smrg 	      attr->module_procedure =1;
2545627f7eb2Smrg 	      break;
2546627f7eb2Smrg 	    case AB_OACC_DECLARE_CREATE:
2547627f7eb2Smrg 	      attr->oacc_declare_create = 1;
2548627f7eb2Smrg 	      break;
2549627f7eb2Smrg 	    case AB_OACC_DECLARE_COPYIN:
2550627f7eb2Smrg 	      attr->oacc_declare_copyin = 1;
2551627f7eb2Smrg 	      break;
2552627f7eb2Smrg 	    case AB_OACC_DECLARE_DEVICEPTR:
2553627f7eb2Smrg 	      attr->oacc_declare_deviceptr = 1;
2554627f7eb2Smrg 	      break;
2555627f7eb2Smrg 	    case AB_OACC_DECLARE_DEVICE_RESIDENT:
2556627f7eb2Smrg 	      attr->oacc_declare_device_resident = 1;
2557627f7eb2Smrg 	      break;
2558627f7eb2Smrg 	    case AB_OACC_DECLARE_LINK:
2559627f7eb2Smrg 	      attr->oacc_declare_link = 1;
2560627f7eb2Smrg 	      break;
2561627f7eb2Smrg 	    case AB_PDT_KIND:
2562627f7eb2Smrg 	      attr->pdt_kind = 1;
2563627f7eb2Smrg 	      break;
2564627f7eb2Smrg 	    case AB_PDT_LEN:
2565627f7eb2Smrg 	      attr->pdt_len = 1;
2566627f7eb2Smrg 	      break;
2567627f7eb2Smrg 	    case AB_PDT_TYPE:
2568627f7eb2Smrg 	      attr->pdt_type = 1;
2569627f7eb2Smrg 	      break;
2570627f7eb2Smrg 	    case AB_PDT_TEMPLATE:
2571627f7eb2Smrg 	      attr->pdt_template = 1;
2572627f7eb2Smrg 	      break;
2573627f7eb2Smrg 	    case AB_PDT_ARRAY:
2574627f7eb2Smrg 	      attr->pdt_array = 1;
2575627f7eb2Smrg 	      break;
2576627f7eb2Smrg 	    case AB_PDT_STRING:
2577627f7eb2Smrg 	      attr->pdt_string = 1;
2578627f7eb2Smrg 	      break;
2579627f7eb2Smrg 	    case AB_OACC_ROUTINE_LOP_GANG:
2580627f7eb2Smrg 	      verify_OACC_ROUTINE_LOP_NONE (attr->oacc_routine_lop);
2581627f7eb2Smrg 	      attr->oacc_routine_lop = OACC_ROUTINE_LOP_GANG;
2582627f7eb2Smrg 	      break;
2583627f7eb2Smrg 	    case AB_OACC_ROUTINE_LOP_WORKER:
2584627f7eb2Smrg 	      verify_OACC_ROUTINE_LOP_NONE (attr->oacc_routine_lop);
2585627f7eb2Smrg 	      attr->oacc_routine_lop = OACC_ROUTINE_LOP_WORKER;
2586627f7eb2Smrg 	      break;
2587627f7eb2Smrg 	    case AB_OACC_ROUTINE_LOP_VECTOR:
2588627f7eb2Smrg 	      verify_OACC_ROUTINE_LOP_NONE (attr->oacc_routine_lop);
2589627f7eb2Smrg 	      attr->oacc_routine_lop = OACC_ROUTINE_LOP_VECTOR;
2590627f7eb2Smrg 	      break;
2591627f7eb2Smrg 	    case AB_OACC_ROUTINE_LOP_SEQ:
2592627f7eb2Smrg 	      verify_OACC_ROUTINE_LOP_NONE (attr->oacc_routine_lop);
2593627f7eb2Smrg 	      attr->oacc_routine_lop = OACC_ROUTINE_LOP_SEQ;
2594627f7eb2Smrg 	      break;
2595627f7eb2Smrg 	    }
2596627f7eb2Smrg 	}
2597627f7eb2Smrg     }
2598627f7eb2Smrg }
2599627f7eb2Smrg 
2600627f7eb2Smrg 
2601627f7eb2Smrg static const mstring bt_types[] = {
2602627f7eb2Smrg     minit ("INTEGER", BT_INTEGER),
2603627f7eb2Smrg     minit ("REAL", BT_REAL),
2604627f7eb2Smrg     minit ("COMPLEX", BT_COMPLEX),
2605627f7eb2Smrg     minit ("LOGICAL", BT_LOGICAL),
2606627f7eb2Smrg     minit ("CHARACTER", BT_CHARACTER),
2607627f7eb2Smrg     minit ("UNION", BT_UNION),
2608627f7eb2Smrg     minit ("DERIVED", BT_DERIVED),
2609627f7eb2Smrg     minit ("CLASS", BT_CLASS),
2610627f7eb2Smrg     minit ("PROCEDURE", BT_PROCEDURE),
2611627f7eb2Smrg     minit ("UNKNOWN", BT_UNKNOWN),
2612627f7eb2Smrg     minit ("VOID", BT_VOID),
2613627f7eb2Smrg     minit ("ASSUMED", BT_ASSUMED),
2614627f7eb2Smrg     minit (NULL, -1)
2615627f7eb2Smrg };
2616627f7eb2Smrg 
2617627f7eb2Smrg 
2618627f7eb2Smrg static void
mio_charlen(gfc_charlen ** clp)2619627f7eb2Smrg mio_charlen (gfc_charlen **clp)
2620627f7eb2Smrg {
2621627f7eb2Smrg   gfc_charlen *cl;
2622627f7eb2Smrg 
2623627f7eb2Smrg   mio_lparen ();
2624627f7eb2Smrg 
2625627f7eb2Smrg   if (iomode == IO_OUTPUT)
2626627f7eb2Smrg     {
2627627f7eb2Smrg       cl = *clp;
2628627f7eb2Smrg       if (cl != NULL)
2629627f7eb2Smrg 	mio_expr (&cl->length);
2630627f7eb2Smrg     }
2631627f7eb2Smrg   else
2632627f7eb2Smrg     {
2633627f7eb2Smrg       if (peek_atom () != ATOM_RPAREN)
2634627f7eb2Smrg 	{
2635627f7eb2Smrg 	  cl = gfc_new_charlen (gfc_current_ns, NULL);
2636627f7eb2Smrg 	  mio_expr (&cl->length);
2637627f7eb2Smrg 	  *clp = cl;
2638627f7eb2Smrg 	}
2639627f7eb2Smrg     }
2640627f7eb2Smrg 
2641627f7eb2Smrg   mio_rparen ();
2642627f7eb2Smrg }
2643627f7eb2Smrg 
2644627f7eb2Smrg 
2645627f7eb2Smrg /* See if a name is a generated name.  */
2646627f7eb2Smrg 
2647627f7eb2Smrg static int
check_unique_name(const char * name)2648627f7eb2Smrg check_unique_name (const char *name)
2649627f7eb2Smrg {
2650627f7eb2Smrg   return *name == '@';
2651627f7eb2Smrg }
2652627f7eb2Smrg 
2653627f7eb2Smrg 
2654627f7eb2Smrg static void
mio_typespec(gfc_typespec * ts)2655627f7eb2Smrg mio_typespec (gfc_typespec *ts)
2656627f7eb2Smrg {
2657627f7eb2Smrg   mio_lparen ();
2658627f7eb2Smrg 
2659627f7eb2Smrg   ts->type = MIO_NAME (bt) (ts->type, bt_types);
2660627f7eb2Smrg 
2661627f7eb2Smrg   if (!gfc_bt_struct (ts->type) && ts->type != BT_CLASS)
2662627f7eb2Smrg     mio_integer (&ts->kind);
2663627f7eb2Smrg   else
2664627f7eb2Smrg     mio_symbol_ref (&ts->u.derived);
2665627f7eb2Smrg 
2666627f7eb2Smrg   mio_symbol_ref (&ts->interface);
2667627f7eb2Smrg 
2668627f7eb2Smrg   /* Add info for C interop and is_iso_c.  */
2669627f7eb2Smrg   mio_integer (&ts->is_c_interop);
2670627f7eb2Smrg   mio_integer (&ts->is_iso_c);
2671627f7eb2Smrg 
2672627f7eb2Smrg   /* If the typespec is for an identifier either from iso_c_binding, or
2673627f7eb2Smrg      a constant that was initialized to an identifier from it, use the
2674627f7eb2Smrg      f90_type.  Otherwise, use the ts->type, since it shouldn't matter.  */
2675627f7eb2Smrg   if (ts->is_iso_c)
2676627f7eb2Smrg     ts->f90_type = MIO_NAME (bt) (ts->f90_type, bt_types);
2677627f7eb2Smrg   else
2678627f7eb2Smrg     ts->f90_type = MIO_NAME (bt) (ts->type, bt_types);
2679627f7eb2Smrg 
2680627f7eb2Smrg   if (ts->type != BT_CHARACTER)
2681627f7eb2Smrg     {
2682627f7eb2Smrg       /* ts->u.cl is only valid for BT_CHARACTER.  */
2683627f7eb2Smrg       mio_lparen ();
2684627f7eb2Smrg       mio_rparen ();
2685627f7eb2Smrg     }
2686627f7eb2Smrg   else
2687627f7eb2Smrg     mio_charlen (&ts->u.cl);
2688627f7eb2Smrg 
2689627f7eb2Smrg   /* So as not to disturb the existing API, use an ATOM_NAME to
2690627f7eb2Smrg      transmit deferred characteristic for characters (F2003).  */
2691627f7eb2Smrg   if (iomode == IO_OUTPUT)
2692627f7eb2Smrg     {
2693627f7eb2Smrg       if (ts->type == BT_CHARACTER && ts->deferred)
2694627f7eb2Smrg 	write_atom (ATOM_NAME, "DEFERRED_CL");
2695627f7eb2Smrg     }
2696627f7eb2Smrg   else if (peek_atom () != ATOM_RPAREN)
2697627f7eb2Smrg     {
2698627f7eb2Smrg       if (parse_atom () != ATOM_NAME)
2699627f7eb2Smrg 	bad_module ("Expected string");
2700627f7eb2Smrg       ts->deferred = 1;
2701627f7eb2Smrg     }
2702627f7eb2Smrg 
2703627f7eb2Smrg   mio_rparen ();
2704627f7eb2Smrg }
2705627f7eb2Smrg 
2706627f7eb2Smrg 
2707627f7eb2Smrg static const mstring array_spec_types[] = {
2708627f7eb2Smrg     minit ("EXPLICIT", AS_EXPLICIT),
2709627f7eb2Smrg     minit ("ASSUMED_RANK", AS_ASSUMED_RANK),
2710627f7eb2Smrg     minit ("ASSUMED_SHAPE", AS_ASSUMED_SHAPE),
2711627f7eb2Smrg     minit ("DEFERRED", AS_DEFERRED),
2712627f7eb2Smrg     minit ("ASSUMED_SIZE", AS_ASSUMED_SIZE),
2713627f7eb2Smrg     minit (NULL, -1)
2714627f7eb2Smrg };
2715627f7eb2Smrg 
2716627f7eb2Smrg 
2717627f7eb2Smrg static void
mio_array_spec(gfc_array_spec ** asp)2718627f7eb2Smrg mio_array_spec (gfc_array_spec **asp)
2719627f7eb2Smrg {
2720627f7eb2Smrg   gfc_array_spec *as;
2721627f7eb2Smrg   int i;
2722627f7eb2Smrg 
2723627f7eb2Smrg   mio_lparen ();
2724627f7eb2Smrg 
2725627f7eb2Smrg   if (iomode == IO_OUTPUT)
2726627f7eb2Smrg     {
2727627f7eb2Smrg       int rank;
2728627f7eb2Smrg 
2729627f7eb2Smrg       if (*asp == NULL)
2730627f7eb2Smrg 	goto done;
2731627f7eb2Smrg       as = *asp;
2732627f7eb2Smrg 
2733627f7eb2Smrg       /* mio_integer expects nonnegative values.  */
2734627f7eb2Smrg       rank = as->rank > 0 ? as->rank : 0;
2735627f7eb2Smrg       mio_integer (&rank);
2736627f7eb2Smrg     }
2737627f7eb2Smrg   else
2738627f7eb2Smrg     {
2739627f7eb2Smrg       if (peek_atom () == ATOM_RPAREN)
2740627f7eb2Smrg 	{
2741627f7eb2Smrg 	  *asp = NULL;
2742627f7eb2Smrg 	  goto done;
2743627f7eb2Smrg 	}
2744627f7eb2Smrg 
2745627f7eb2Smrg       *asp = as = gfc_get_array_spec ();
2746627f7eb2Smrg       mio_integer (&as->rank);
2747627f7eb2Smrg     }
2748627f7eb2Smrg 
2749627f7eb2Smrg   mio_integer (&as->corank);
2750627f7eb2Smrg   as->type = MIO_NAME (array_type) (as->type, array_spec_types);
2751627f7eb2Smrg 
2752627f7eb2Smrg   if (iomode == IO_INPUT && as->type == AS_ASSUMED_RANK)
2753627f7eb2Smrg     as->rank = -1;
2754627f7eb2Smrg   if (iomode == IO_INPUT && as->corank)
2755627f7eb2Smrg     as->cotype = (as->type == AS_DEFERRED) ? AS_DEFERRED : AS_EXPLICIT;
2756627f7eb2Smrg 
2757627f7eb2Smrg   if (as->rank + as->corank > 0)
2758627f7eb2Smrg     for (i = 0; i < as->rank + as->corank; i++)
2759627f7eb2Smrg       {
2760627f7eb2Smrg 	mio_expr (&as->lower[i]);
2761627f7eb2Smrg 	mio_expr (&as->upper[i]);
2762627f7eb2Smrg       }
2763627f7eb2Smrg 
2764627f7eb2Smrg done:
2765627f7eb2Smrg   mio_rparen ();
2766627f7eb2Smrg }
2767627f7eb2Smrg 
2768627f7eb2Smrg 
2769627f7eb2Smrg /* Given a pointer to an array reference structure (which lives in a
2770627f7eb2Smrg    gfc_ref structure), find the corresponding array specification
2771627f7eb2Smrg    structure.  Storing the pointer in the ref structure doesn't quite
2772627f7eb2Smrg    work when loading from a module. Generating code for an array
2773627f7eb2Smrg    reference also needs more information than just the array spec.  */
2774627f7eb2Smrg 
2775627f7eb2Smrg static const mstring array_ref_types[] = {
2776627f7eb2Smrg     minit ("FULL", AR_FULL),
2777627f7eb2Smrg     minit ("ELEMENT", AR_ELEMENT),
2778627f7eb2Smrg     minit ("SECTION", AR_SECTION),
2779627f7eb2Smrg     minit (NULL, -1)
2780627f7eb2Smrg };
2781627f7eb2Smrg 
2782627f7eb2Smrg 
2783627f7eb2Smrg static void
mio_array_ref(gfc_array_ref * ar)2784627f7eb2Smrg mio_array_ref (gfc_array_ref *ar)
2785627f7eb2Smrg {
2786627f7eb2Smrg   int i;
2787627f7eb2Smrg 
2788627f7eb2Smrg   mio_lparen ();
2789627f7eb2Smrg   ar->type = MIO_NAME (ar_type) (ar->type, array_ref_types);
2790627f7eb2Smrg   mio_integer (&ar->dimen);
2791627f7eb2Smrg 
2792627f7eb2Smrg   switch (ar->type)
2793627f7eb2Smrg     {
2794627f7eb2Smrg     case AR_FULL:
2795627f7eb2Smrg       break;
2796627f7eb2Smrg 
2797627f7eb2Smrg     case AR_ELEMENT:
2798627f7eb2Smrg       for (i = 0; i < ar->dimen; i++)
2799627f7eb2Smrg 	mio_expr (&ar->start[i]);
2800627f7eb2Smrg 
2801627f7eb2Smrg       break;
2802627f7eb2Smrg 
2803627f7eb2Smrg     case AR_SECTION:
2804627f7eb2Smrg       for (i = 0; i < ar->dimen; i++)
2805627f7eb2Smrg 	{
2806627f7eb2Smrg 	  mio_expr (&ar->start[i]);
2807627f7eb2Smrg 	  mio_expr (&ar->end[i]);
2808627f7eb2Smrg 	  mio_expr (&ar->stride[i]);
2809627f7eb2Smrg 	}
2810627f7eb2Smrg 
2811627f7eb2Smrg       break;
2812627f7eb2Smrg 
2813627f7eb2Smrg     case AR_UNKNOWN:
2814627f7eb2Smrg       gfc_internal_error ("mio_array_ref(): Unknown array ref");
2815627f7eb2Smrg     }
2816627f7eb2Smrg 
2817627f7eb2Smrg   /* Unfortunately, ar->dimen_type is an anonymous enumerated type so
2818627f7eb2Smrg      we can't call mio_integer directly.  Instead loop over each element
2819627f7eb2Smrg      and cast it to/from an integer.  */
2820627f7eb2Smrg   if (iomode == IO_OUTPUT)
2821627f7eb2Smrg     {
2822627f7eb2Smrg       for (i = 0; i < ar->dimen; i++)
2823627f7eb2Smrg 	{
2824627f7eb2Smrg 	  HOST_WIDE_INT tmp = (HOST_WIDE_INT)ar->dimen_type[i];
2825627f7eb2Smrg 	  write_atom (ATOM_INTEGER, &tmp);
2826627f7eb2Smrg 	}
2827627f7eb2Smrg     }
2828627f7eb2Smrg   else
2829627f7eb2Smrg     {
2830627f7eb2Smrg       for (i = 0; i < ar->dimen; i++)
2831627f7eb2Smrg 	{
2832627f7eb2Smrg 	  require_atom (ATOM_INTEGER);
2833627f7eb2Smrg 	  ar->dimen_type[i] = (enum gfc_array_ref_dimen_type) atom_int;
2834627f7eb2Smrg 	}
2835627f7eb2Smrg     }
2836627f7eb2Smrg 
2837627f7eb2Smrg   if (iomode == IO_INPUT)
2838627f7eb2Smrg     {
2839627f7eb2Smrg       ar->where = gfc_current_locus;
2840627f7eb2Smrg 
2841627f7eb2Smrg       for (i = 0; i < ar->dimen; i++)
2842627f7eb2Smrg 	ar->c_where[i] = gfc_current_locus;
2843627f7eb2Smrg     }
2844627f7eb2Smrg 
2845627f7eb2Smrg   mio_rparen ();
2846627f7eb2Smrg }
2847627f7eb2Smrg 
2848627f7eb2Smrg 
2849627f7eb2Smrg /* Saves or restores a pointer.  The pointer is converted back and
2850627f7eb2Smrg    forth from an integer.  We return the pointer_info pointer so that
2851627f7eb2Smrg    the caller can take additional action based on the pointer type.  */
2852627f7eb2Smrg 
2853627f7eb2Smrg static pointer_info *
mio_pointer_ref(void * gp)2854627f7eb2Smrg mio_pointer_ref (void *gp)
2855627f7eb2Smrg {
2856627f7eb2Smrg   pointer_info *p;
2857627f7eb2Smrg 
2858627f7eb2Smrg   if (iomode == IO_OUTPUT)
2859627f7eb2Smrg     {
2860627f7eb2Smrg       p = get_pointer (*((char **) gp));
2861627f7eb2Smrg       HOST_WIDE_INT hwi = p->integer;
2862627f7eb2Smrg       write_atom (ATOM_INTEGER, &hwi);
2863627f7eb2Smrg     }
2864627f7eb2Smrg   else
2865627f7eb2Smrg     {
2866627f7eb2Smrg       require_atom (ATOM_INTEGER);
2867627f7eb2Smrg       p = add_fixup (atom_int, gp);
2868627f7eb2Smrg     }
2869627f7eb2Smrg 
2870627f7eb2Smrg   return p;
2871627f7eb2Smrg }
2872627f7eb2Smrg 
2873627f7eb2Smrg 
2874627f7eb2Smrg /* Save and load references to components that occur within
2875627f7eb2Smrg    expressions.  We have to describe these references by a number and
2876627f7eb2Smrg    by name.  The number is necessary for forward references during
2877627f7eb2Smrg    reading, and the name is necessary if the symbol already exists in
2878627f7eb2Smrg    the namespace and is not loaded again.  */
2879627f7eb2Smrg 
2880627f7eb2Smrg static void
mio_component_ref(gfc_component ** cp)2881627f7eb2Smrg mio_component_ref (gfc_component **cp)
2882627f7eb2Smrg {
2883627f7eb2Smrg   pointer_info *p;
2884627f7eb2Smrg 
2885627f7eb2Smrg   p = mio_pointer_ref (cp);
2886627f7eb2Smrg   if (p->type == P_UNKNOWN)
2887627f7eb2Smrg     p->type = P_COMPONENT;
2888627f7eb2Smrg }
2889627f7eb2Smrg 
2890627f7eb2Smrg 
2891627f7eb2Smrg static void mio_namespace_ref (gfc_namespace **nsp);
2892627f7eb2Smrg static void mio_formal_arglist (gfc_formal_arglist **formal);
2893627f7eb2Smrg static void mio_typebound_proc (gfc_typebound_proc** proc);
2894627f7eb2Smrg static void mio_actual_arglist (gfc_actual_arglist **ap, bool pdt);
2895627f7eb2Smrg 
2896627f7eb2Smrg static void
mio_component(gfc_component * c,int vtype)2897627f7eb2Smrg mio_component (gfc_component *c, int vtype)
2898627f7eb2Smrg {
2899627f7eb2Smrg   pointer_info *p;
2900627f7eb2Smrg 
2901627f7eb2Smrg   mio_lparen ();
2902627f7eb2Smrg 
2903627f7eb2Smrg   if (iomode == IO_OUTPUT)
2904627f7eb2Smrg     {
2905627f7eb2Smrg       p = get_pointer (c);
2906627f7eb2Smrg       mio_hwi (&p->integer);
2907627f7eb2Smrg     }
2908627f7eb2Smrg   else
2909627f7eb2Smrg     {
2910627f7eb2Smrg       HOST_WIDE_INT n;
2911627f7eb2Smrg       mio_hwi (&n);
2912627f7eb2Smrg       p = get_integer (n);
2913627f7eb2Smrg       associate_integer_pointer (p, c);
2914627f7eb2Smrg     }
2915627f7eb2Smrg 
2916627f7eb2Smrg   if (p->type == P_UNKNOWN)
2917627f7eb2Smrg     p->type = P_COMPONENT;
2918627f7eb2Smrg 
2919627f7eb2Smrg   mio_pool_string (&c->name);
2920627f7eb2Smrg   mio_typespec (&c->ts);
2921627f7eb2Smrg   mio_array_spec (&c->as);
2922627f7eb2Smrg 
2923627f7eb2Smrg   /* PDT templates store the expression for the kind of a component here.  */
2924627f7eb2Smrg   mio_expr (&c->kind_expr);
2925627f7eb2Smrg 
2926627f7eb2Smrg   /* PDT types store the component specification list here. */
2927627f7eb2Smrg   mio_actual_arglist (&c->param_list, true);
2928627f7eb2Smrg 
2929627f7eb2Smrg   mio_symbol_attribute (&c->attr);
2930627f7eb2Smrg   if (c->ts.type == BT_CLASS)
2931627f7eb2Smrg     c->attr.class_ok = 1;
2932627f7eb2Smrg   c->attr.access = MIO_NAME (gfc_access) (c->attr.access, access_types);
2933627f7eb2Smrg 
2934627f7eb2Smrg   if (!vtype || strcmp (c->name, "_final") == 0
2935627f7eb2Smrg       || strcmp (c->name, "_hash") == 0)
2936627f7eb2Smrg     mio_expr (&c->initializer);
2937627f7eb2Smrg 
2938627f7eb2Smrg   if (c->attr.proc_pointer)
2939627f7eb2Smrg     mio_typebound_proc (&c->tb);
2940627f7eb2Smrg 
2941627f7eb2Smrg   c->loc = gfc_current_locus;
2942627f7eb2Smrg 
2943627f7eb2Smrg   mio_rparen ();
2944627f7eb2Smrg }
2945627f7eb2Smrg 
2946627f7eb2Smrg 
2947627f7eb2Smrg static void
mio_component_list(gfc_component ** cp,int vtype)2948627f7eb2Smrg mio_component_list (gfc_component **cp, int vtype)
2949627f7eb2Smrg {
2950627f7eb2Smrg   gfc_component *c, *tail;
2951627f7eb2Smrg 
2952627f7eb2Smrg   mio_lparen ();
2953627f7eb2Smrg 
2954627f7eb2Smrg   if (iomode == IO_OUTPUT)
2955627f7eb2Smrg     {
2956627f7eb2Smrg       for (c = *cp; c; c = c->next)
2957627f7eb2Smrg 	mio_component (c, vtype);
2958627f7eb2Smrg     }
2959627f7eb2Smrg   else
2960627f7eb2Smrg     {
2961627f7eb2Smrg       *cp = NULL;
2962627f7eb2Smrg       tail = NULL;
2963627f7eb2Smrg 
2964627f7eb2Smrg       for (;;)
2965627f7eb2Smrg 	{
2966627f7eb2Smrg 	  if (peek_atom () == ATOM_RPAREN)
2967627f7eb2Smrg 	    break;
2968627f7eb2Smrg 
2969627f7eb2Smrg 	  c = gfc_get_component ();
2970627f7eb2Smrg 	  mio_component (c, vtype);
2971627f7eb2Smrg 
2972627f7eb2Smrg 	  if (tail == NULL)
2973627f7eb2Smrg 	    *cp = c;
2974627f7eb2Smrg 	  else
2975627f7eb2Smrg 	    tail->next = c;
2976627f7eb2Smrg 
2977627f7eb2Smrg 	  tail = c;
2978627f7eb2Smrg 	}
2979627f7eb2Smrg     }
2980627f7eb2Smrg 
2981627f7eb2Smrg   mio_rparen ();
2982627f7eb2Smrg }
2983627f7eb2Smrg 
2984627f7eb2Smrg 
2985627f7eb2Smrg static void
mio_actual_arg(gfc_actual_arglist * a,bool pdt)2986627f7eb2Smrg mio_actual_arg (gfc_actual_arglist *a, bool pdt)
2987627f7eb2Smrg {
2988627f7eb2Smrg   mio_lparen ();
2989627f7eb2Smrg   mio_pool_string (&a->name);
2990627f7eb2Smrg   mio_expr (&a->expr);
2991627f7eb2Smrg   if (pdt)
2992627f7eb2Smrg     mio_integer ((int *)&a->spec_type);
2993627f7eb2Smrg   mio_rparen ();
2994627f7eb2Smrg }
2995627f7eb2Smrg 
2996627f7eb2Smrg 
2997627f7eb2Smrg static void
mio_actual_arglist(gfc_actual_arglist ** ap,bool pdt)2998627f7eb2Smrg mio_actual_arglist (gfc_actual_arglist **ap, bool pdt)
2999627f7eb2Smrg {
3000627f7eb2Smrg   gfc_actual_arglist *a, *tail;
3001627f7eb2Smrg 
3002627f7eb2Smrg   mio_lparen ();
3003627f7eb2Smrg 
3004627f7eb2Smrg   if (iomode == IO_OUTPUT)
3005627f7eb2Smrg     {
3006627f7eb2Smrg       for (a = *ap; a; a = a->next)
3007627f7eb2Smrg 	mio_actual_arg (a, pdt);
3008627f7eb2Smrg 
3009627f7eb2Smrg     }
3010627f7eb2Smrg   else
3011627f7eb2Smrg     {
3012627f7eb2Smrg       tail = NULL;
3013627f7eb2Smrg 
3014627f7eb2Smrg       for (;;)
3015627f7eb2Smrg 	{
3016627f7eb2Smrg 	  if (peek_atom () != ATOM_LPAREN)
3017627f7eb2Smrg 	    break;
3018627f7eb2Smrg 
3019627f7eb2Smrg 	  a = gfc_get_actual_arglist ();
3020627f7eb2Smrg 
3021627f7eb2Smrg 	  if (tail == NULL)
3022627f7eb2Smrg 	    *ap = a;
3023627f7eb2Smrg 	  else
3024627f7eb2Smrg 	    tail->next = a;
3025627f7eb2Smrg 
3026627f7eb2Smrg 	  tail = a;
3027627f7eb2Smrg 	  mio_actual_arg (a, pdt);
3028627f7eb2Smrg 	}
3029627f7eb2Smrg     }
3030627f7eb2Smrg 
3031627f7eb2Smrg   mio_rparen ();
3032627f7eb2Smrg }
3033627f7eb2Smrg 
3034627f7eb2Smrg 
3035627f7eb2Smrg /* Read and write formal argument lists.  */
3036627f7eb2Smrg 
3037627f7eb2Smrg static void
mio_formal_arglist(gfc_formal_arglist ** formal)3038627f7eb2Smrg mio_formal_arglist (gfc_formal_arglist **formal)
3039627f7eb2Smrg {
3040627f7eb2Smrg   gfc_formal_arglist *f, *tail;
3041627f7eb2Smrg 
3042627f7eb2Smrg   mio_lparen ();
3043627f7eb2Smrg 
3044627f7eb2Smrg   if (iomode == IO_OUTPUT)
3045627f7eb2Smrg     {
3046627f7eb2Smrg       for (f = *formal; f; f = f->next)
3047627f7eb2Smrg 	mio_symbol_ref (&f->sym);
3048627f7eb2Smrg     }
3049627f7eb2Smrg   else
3050627f7eb2Smrg     {
3051627f7eb2Smrg       *formal = tail = NULL;
3052627f7eb2Smrg 
3053627f7eb2Smrg       while (peek_atom () != ATOM_RPAREN)
3054627f7eb2Smrg 	{
3055627f7eb2Smrg 	  f = gfc_get_formal_arglist ();
3056627f7eb2Smrg 	  mio_symbol_ref (&f->sym);
3057627f7eb2Smrg 
3058627f7eb2Smrg 	  if (*formal == NULL)
3059627f7eb2Smrg 	    *formal = f;
3060627f7eb2Smrg 	  else
3061627f7eb2Smrg 	    tail->next = f;
3062627f7eb2Smrg 
3063627f7eb2Smrg 	  tail = f;
3064627f7eb2Smrg 	}
3065627f7eb2Smrg     }
3066627f7eb2Smrg 
3067627f7eb2Smrg   mio_rparen ();
3068627f7eb2Smrg }
3069627f7eb2Smrg 
3070627f7eb2Smrg 
3071627f7eb2Smrg /* Save or restore a reference to a symbol node.  */
3072627f7eb2Smrg 
3073627f7eb2Smrg pointer_info *
mio_symbol_ref(gfc_symbol ** symp)3074627f7eb2Smrg mio_symbol_ref (gfc_symbol **symp)
3075627f7eb2Smrg {
3076627f7eb2Smrg   pointer_info *p;
3077627f7eb2Smrg 
3078627f7eb2Smrg   p = mio_pointer_ref (symp);
3079627f7eb2Smrg   if (p->type == P_UNKNOWN)
3080627f7eb2Smrg     p->type = P_SYMBOL;
3081627f7eb2Smrg 
3082627f7eb2Smrg   if (iomode == IO_OUTPUT)
3083627f7eb2Smrg     {
3084627f7eb2Smrg       if (p->u.wsym.state == UNREFERENCED)
3085627f7eb2Smrg 	p->u.wsym.state = NEEDS_WRITE;
3086627f7eb2Smrg     }
3087627f7eb2Smrg   else
3088627f7eb2Smrg     {
3089627f7eb2Smrg       if (p->u.rsym.state == UNUSED)
3090627f7eb2Smrg 	p->u.rsym.state = NEEDED;
3091627f7eb2Smrg     }
3092627f7eb2Smrg   return p;
3093627f7eb2Smrg }
3094627f7eb2Smrg 
3095627f7eb2Smrg 
3096627f7eb2Smrg /* Save or restore a reference to a symtree node.  */
3097627f7eb2Smrg 
3098627f7eb2Smrg static void
mio_symtree_ref(gfc_symtree ** stp)3099627f7eb2Smrg mio_symtree_ref (gfc_symtree **stp)
3100627f7eb2Smrg {
3101627f7eb2Smrg   pointer_info *p;
3102627f7eb2Smrg   fixup_t *f;
3103627f7eb2Smrg 
3104627f7eb2Smrg   if (iomode == IO_OUTPUT)
3105627f7eb2Smrg     mio_symbol_ref (&(*stp)->n.sym);
3106627f7eb2Smrg   else
3107627f7eb2Smrg     {
3108627f7eb2Smrg       require_atom (ATOM_INTEGER);
3109627f7eb2Smrg       p = get_integer (atom_int);
3110627f7eb2Smrg 
3111627f7eb2Smrg       /* An unused equivalence member; make a symbol and a symtree
3112627f7eb2Smrg 	 for it.  */
3113627f7eb2Smrg       if (in_load_equiv && p->u.rsym.symtree == NULL)
3114627f7eb2Smrg 	{
3115627f7eb2Smrg 	  /* Since this is not used, it must have a unique name.  */
3116627f7eb2Smrg 	  p->u.rsym.symtree = gfc_get_unique_symtree (gfc_current_ns);
3117627f7eb2Smrg 
3118627f7eb2Smrg 	  /* Make the symbol.  */
3119627f7eb2Smrg 	  if (p->u.rsym.sym == NULL)
3120627f7eb2Smrg 	    {
3121627f7eb2Smrg 	      p->u.rsym.sym = gfc_new_symbol (p->u.rsym.true_name,
3122627f7eb2Smrg 					      gfc_current_ns);
3123627f7eb2Smrg 	      p->u.rsym.sym->module = gfc_get_string ("%s", p->u.rsym.module);
3124627f7eb2Smrg 	    }
3125627f7eb2Smrg 
3126627f7eb2Smrg 	  p->u.rsym.symtree->n.sym = p->u.rsym.sym;
3127627f7eb2Smrg 	  p->u.rsym.symtree->n.sym->refs++;
3128627f7eb2Smrg 	  p->u.rsym.referenced = 1;
3129627f7eb2Smrg 
3130627f7eb2Smrg 	  /* If the symbol is PRIVATE and in COMMON, load_commons will
3131627f7eb2Smrg 	     generate a fixup symbol, which must be associated.  */
3132627f7eb2Smrg 	  if (p->fixup)
3133627f7eb2Smrg 	    resolve_fixups (p->fixup, p->u.rsym.sym);
3134627f7eb2Smrg 	  p->fixup = NULL;
3135627f7eb2Smrg 	}
3136627f7eb2Smrg 
3137627f7eb2Smrg       if (p->type == P_UNKNOWN)
3138627f7eb2Smrg 	p->type = P_SYMBOL;
3139627f7eb2Smrg 
3140627f7eb2Smrg       if (p->u.rsym.state == UNUSED)
3141627f7eb2Smrg 	p->u.rsym.state = NEEDED;
3142627f7eb2Smrg 
3143627f7eb2Smrg       if (p->u.rsym.symtree != NULL)
3144627f7eb2Smrg 	{
3145627f7eb2Smrg 	  *stp = p->u.rsym.symtree;
3146627f7eb2Smrg 	}
3147627f7eb2Smrg       else
3148627f7eb2Smrg 	{
3149627f7eb2Smrg 	  f = XCNEW (fixup_t);
3150627f7eb2Smrg 
3151627f7eb2Smrg 	  f->next = p->u.rsym.stfixup;
3152627f7eb2Smrg 	  p->u.rsym.stfixup = f;
3153627f7eb2Smrg 
3154627f7eb2Smrg 	  f->pointer = (void **) stp;
3155627f7eb2Smrg 	}
3156627f7eb2Smrg     }
3157627f7eb2Smrg }
3158627f7eb2Smrg 
3159627f7eb2Smrg 
3160627f7eb2Smrg static void
mio_iterator(gfc_iterator ** ip)3161627f7eb2Smrg mio_iterator (gfc_iterator **ip)
3162627f7eb2Smrg {
3163627f7eb2Smrg   gfc_iterator *iter;
3164627f7eb2Smrg 
3165627f7eb2Smrg   mio_lparen ();
3166627f7eb2Smrg 
3167627f7eb2Smrg   if (iomode == IO_OUTPUT)
3168627f7eb2Smrg     {
3169627f7eb2Smrg       if (*ip == NULL)
3170627f7eb2Smrg 	goto done;
3171627f7eb2Smrg     }
3172627f7eb2Smrg   else
3173627f7eb2Smrg     {
3174627f7eb2Smrg       if (peek_atom () == ATOM_RPAREN)
3175627f7eb2Smrg 	{
3176627f7eb2Smrg 	  *ip = NULL;
3177627f7eb2Smrg 	  goto done;
3178627f7eb2Smrg 	}
3179627f7eb2Smrg 
3180627f7eb2Smrg       *ip = gfc_get_iterator ();
3181627f7eb2Smrg     }
3182627f7eb2Smrg 
3183627f7eb2Smrg   iter = *ip;
3184627f7eb2Smrg 
3185627f7eb2Smrg   mio_expr (&iter->var);
3186627f7eb2Smrg   mio_expr (&iter->start);
3187627f7eb2Smrg   mio_expr (&iter->end);
3188627f7eb2Smrg   mio_expr (&iter->step);
3189627f7eb2Smrg 
3190627f7eb2Smrg done:
3191627f7eb2Smrg   mio_rparen ();
3192627f7eb2Smrg }
3193627f7eb2Smrg 
3194627f7eb2Smrg 
3195627f7eb2Smrg static void
mio_constructor(gfc_constructor_base * cp)3196627f7eb2Smrg mio_constructor (gfc_constructor_base *cp)
3197627f7eb2Smrg {
3198627f7eb2Smrg   gfc_constructor *c;
3199627f7eb2Smrg 
3200627f7eb2Smrg   mio_lparen ();
3201627f7eb2Smrg 
3202627f7eb2Smrg   if (iomode == IO_OUTPUT)
3203627f7eb2Smrg     {
3204627f7eb2Smrg       for (c = gfc_constructor_first (*cp); c; c = gfc_constructor_next (c))
3205627f7eb2Smrg 	{
3206627f7eb2Smrg 	  mio_lparen ();
3207627f7eb2Smrg 	  mio_expr (&c->expr);
3208627f7eb2Smrg 	  mio_iterator (&c->iterator);
3209627f7eb2Smrg 	  mio_rparen ();
3210627f7eb2Smrg 	}
3211627f7eb2Smrg     }
3212627f7eb2Smrg   else
3213627f7eb2Smrg     {
3214627f7eb2Smrg       while (peek_atom () != ATOM_RPAREN)
3215627f7eb2Smrg 	{
3216627f7eb2Smrg 	  c = gfc_constructor_append_expr (cp, NULL, NULL);
3217627f7eb2Smrg 
3218627f7eb2Smrg 	  mio_lparen ();
3219627f7eb2Smrg 	  mio_expr (&c->expr);
3220627f7eb2Smrg 	  mio_iterator (&c->iterator);
3221627f7eb2Smrg 	  mio_rparen ();
3222627f7eb2Smrg 	}
3223627f7eb2Smrg     }
3224627f7eb2Smrg 
3225627f7eb2Smrg   mio_rparen ();
3226627f7eb2Smrg }
3227627f7eb2Smrg 
3228627f7eb2Smrg 
3229627f7eb2Smrg static const mstring ref_types[] = {
3230627f7eb2Smrg     minit ("ARRAY", REF_ARRAY),
3231627f7eb2Smrg     minit ("COMPONENT", REF_COMPONENT),
3232627f7eb2Smrg     minit ("SUBSTRING", REF_SUBSTRING),
3233627f7eb2Smrg     minit ("INQUIRY", REF_INQUIRY),
3234627f7eb2Smrg     minit (NULL, -1)
3235627f7eb2Smrg };
3236627f7eb2Smrg 
3237627f7eb2Smrg static const mstring inquiry_types[] = {
3238627f7eb2Smrg     minit ("RE", INQUIRY_RE),
3239627f7eb2Smrg     minit ("IM", INQUIRY_IM),
3240627f7eb2Smrg     minit ("KIND", INQUIRY_KIND),
3241627f7eb2Smrg     minit ("LEN", INQUIRY_LEN),
3242627f7eb2Smrg     minit (NULL, -1)
3243627f7eb2Smrg };
3244627f7eb2Smrg 
3245627f7eb2Smrg 
3246627f7eb2Smrg static void
mio_ref(gfc_ref ** rp)3247627f7eb2Smrg mio_ref (gfc_ref **rp)
3248627f7eb2Smrg {
3249627f7eb2Smrg   gfc_ref *r;
3250627f7eb2Smrg 
3251627f7eb2Smrg   mio_lparen ();
3252627f7eb2Smrg 
3253627f7eb2Smrg   r = *rp;
3254627f7eb2Smrg   r->type = MIO_NAME (ref_type) (r->type, ref_types);
3255627f7eb2Smrg 
3256627f7eb2Smrg   switch (r->type)
3257627f7eb2Smrg     {
3258627f7eb2Smrg     case REF_ARRAY:
3259627f7eb2Smrg       mio_array_ref (&r->u.ar);
3260627f7eb2Smrg       break;
3261627f7eb2Smrg 
3262627f7eb2Smrg     case REF_COMPONENT:
3263627f7eb2Smrg       mio_symbol_ref (&r->u.c.sym);
3264627f7eb2Smrg       mio_component_ref (&r->u.c.component);
3265627f7eb2Smrg       break;
3266627f7eb2Smrg 
3267627f7eb2Smrg     case REF_SUBSTRING:
3268627f7eb2Smrg       mio_expr (&r->u.ss.start);
3269627f7eb2Smrg       mio_expr (&r->u.ss.end);
3270627f7eb2Smrg       mio_charlen (&r->u.ss.length);
3271627f7eb2Smrg       break;
3272627f7eb2Smrg 
3273627f7eb2Smrg     case REF_INQUIRY:
3274627f7eb2Smrg       r->u.i = MIO_NAME (inquiry_type) (r->u.i, inquiry_types);
3275627f7eb2Smrg       break;
3276627f7eb2Smrg     }
3277627f7eb2Smrg 
3278627f7eb2Smrg   mio_rparen ();
3279627f7eb2Smrg }
3280627f7eb2Smrg 
3281627f7eb2Smrg 
3282627f7eb2Smrg static void
mio_ref_list(gfc_ref ** rp)3283627f7eb2Smrg mio_ref_list (gfc_ref **rp)
3284627f7eb2Smrg {
3285627f7eb2Smrg   gfc_ref *ref, *head, *tail;
3286627f7eb2Smrg 
3287627f7eb2Smrg   mio_lparen ();
3288627f7eb2Smrg 
3289627f7eb2Smrg   if (iomode == IO_OUTPUT)
3290627f7eb2Smrg     {
3291627f7eb2Smrg       for (ref = *rp; ref; ref = ref->next)
3292627f7eb2Smrg 	mio_ref (&ref);
3293627f7eb2Smrg     }
3294627f7eb2Smrg   else
3295627f7eb2Smrg     {
3296627f7eb2Smrg       head = tail = NULL;
3297627f7eb2Smrg 
3298627f7eb2Smrg       while (peek_atom () != ATOM_RPAREN)
3299627f7eb2Smrg 	{
3300627f7eb2Smrg 	  if (head == NULL)
3301627f7eb2Smrg 	    head = tail = gfc_get_ref ();
3302627f7eb2Smrg 	  else
3303627f7eb2Smrg 	    {
3304627f7eb2Smrg 	      tail->next = gfc_get_ref ();
3305627f7eb2Smrg 	      tail = tail->next;
3306627f7eb2Smrg 	    }
3307627f7eb2Smrg 
3308627f7eb2Smrg 	  mio_ref (&tail);
3309627f7eb2Smrg 	}
3310627f7eb2Smrg 
3311627f7eb2Smrg       *rp = head;
3312627f7eb2Smrg     }
3313627f7eb2Smrg 
3314627f7eb2Smrg   mio_rparen ();
3315627f7eb2Smrg }
3316627f7eb2Smrg 
3317627f7eb2Smrg 
3318627f7eb2Smrg /* Read and write an integer value.  */
3319627f7eb2Smrg 
3320627f7eb2Smrg static void
mio_gmp_integer(mpz_t * integer)3321627f7eb2Smrg mio_gmp_integer (mpz_t *integer)
3322627f7eb2Smrg {
3323627f7eb2Smrg   char *p;
3324627f7eb2Smrg 
3325627f7eb2Smrg   if (iomode == IO_INPUT)
3326627f7eb2Smrg     {
3327627f7eb2Smrg       if (parse_atom () != ATOM_STRING)
3328627f7eb2Smrg 	bad_module ("Expected integer string");
3329627f7eb2Smrg 
3330627f7eb2Smrg       mpz_init (*integer);
3331627f7eb2Smrg       if (mpz_set_str (*integer, atom_string, 10))
3332627f7eb2Smrg 	bad_module ("Error converting integer");
3333627f7eb2Smrg 
3334627f7eb2Smrg       free (atom_string);
3335627f7eb2Smrg     }
3336627f7eb2Smrg   else
3337627f7eb2Smrg     {
3338627f7eb2Smrg       p = mpz_get_str (NULL, 10, *integer);
3339627f7eb2Smrg       write_atom (ATOM_STRING, p);
3340627f7eb2Smrg       free (p);
3341627f7eb2Smrg     }
3342627f7eb2Smrg }
3343627f7eb2Smrg 
3344627f7eb2Smrg 
3345627f7eb2Smrg static void
mio_gmp_real(mpfr_t * real)3346627f7eb2Smrg mio_gmp_real (mpfr_t *real)
3347627f7eb2Smrg {
3348*4c3eb207Smrg   mpfr_exp_t exponent;
3349627f7eb2Smrg   char *p;
3350627f7eb2Smrg 
3351627f7eb2Smrg   if (iomode == IO_INPUT)
3352627f7eb2Smrg     {
3353627f7eb2Smrg       if (parse_atom () != ATOM_STRING)
3354627f7eb2Smrg 	bad_module ("Expected real string");
3355627f7eb2Smrg 
3356627f7eb2Smrg       mpfr_init (*real);
3357627f7eb2Smrg       mpfr_set_str (*real, atom_string, 16, GFC_RND_MODE);
3358627f7eb2Smrg       free (atom_string);
3359627f7eb2Smrg     }
3360627f7eb2Smrg   else
3361627f7eb2Smrg     {
3362627f7eb2Smrg       p = mpfr_get_str (NULL, &exponent, 16, 0, *real, GFC_RND_MODE);
3363627f7eb2Smrg 
3364627f7eb2Smrg       if (mpfr_nan_p (*real) || mpfr_inf_p (*real))
3365627f7eb2Smrg 	{
3366627f7eb2Smrg 	  write_atom (ATOM_STRING, p);
3367627f7eb2Smrg 	  free (p);
3368627f7eb2Smrg 	  return;
3369627f7eb2Smrg 	}
3370627f7eb2Smrg 
3371627f7eb2Smrg       atom_string = XCNEWVEC (char, strlen (p) + 20);
3372627f7eb2Smrg 
3373627f7eb2Smrg       sprintf (atom_string, "0.%s@%ld", p, exponent);
3374627f7eb2Smrg 
3375627f7eb2Smrg       /* Fix negative numbers.  */
3376627f7eb2Smrg       if (atom_string[2] == '-')
3377627f7eb2Smrg 	{
3378627f7eb2Smrg 	  atom_string[0] = '-';
3379627f7eb2Smrg 	  atom_string[1] = '0';
3380627f7eb2Smrg 	  atom_string[2] = '.';
3381627f7eb2Smrg 	}
3382627f7eb2Smrg 
3383627f7eb2Smrg       write_atom (ATOM_STRING, atom_string);
3384627f7eb2Smrg 
3385627f7eb2Smrg       free (atom_string);
3386627f7eb2Smrg       free (p);
3387627f7eb2Smrg     }
3388627f7eb2Smrg }
3389627f7eb2Smrg 
3390627f7eb2Smrg 
3391627f7eb2Smrg /* Save and restore the shape of an array constructor.  */
3392627f7eb2Smrg 
3393627f7eb2Smrg static void
mio_shape(mpz_t ** pshape,int rank)3394627f7eb2Smrg mio_shape (mpz_t **pshape, int rank)
3395627f7eb2Smrg {
3396627f7eb2Smrg   mpz_t *shape;
3397627f7eb2Smrg   atom_type t;
3398627f7eb2Smrg   int n;
3399627f7eb2Smrg 
3400627f7eb2Smrg   /* A NULL shape is represented by ().  */
3401627f7eb2Smrg   mio_lparen ();
3402627f7eb2Smrg 
3403627f7eb2Smrg   if (iomode == IO_OUTPUT)
3404627f7eb2Smrg     {
3405627f7eb2Smrg       shape = *pshape;
3406627f7eb2Smrg       if (!shape)
3407627f7eb2Smrg 	{
3408627f7eb2Smrg 	  mio_rparen ();
3409627f7eb2Smrg 	  return;
3410627f7eb2Smrg 	}
3411627f7eb2Smrg     }
3412627f7eb2Smrg   else
3413627f7eb2Smrg     {
3414627f7eb2Smrg       t = peek_atom ();
3415627f7eb2Smrg       if (t == ATOM_RPAREN)
3416627f7eb2Smrg 	{
3417627f7eb2Smrg 	  *pshape = NULL;
3418627f7eb2Smrg 	  mio_rparen ();
3419627f7eb2Smrg 	  return;
3420627f7eb2Smrg 	}
3421627f7eb2Smrg 
3422627f7eb2Smrg       shape = gfc_get_shape (rank);
3423627f7eb2Smrg       *pshape = shape;
3424627f7eb2Smrg     }
3425627f7eb2Smrg 
3426627f7eb2Smrg   for (n = 0; n < rank; n++)
3427627f7eb2Smrg     mio_gmp_integer (&shape[n]);
3428627f7eb2Smrg 
3429627f7eb2Smrg   mio_rparen ();
3430627f7eb2Smrg }
3431627f7eb2Smrg 
3432627f7eb2Smrg 
3433627f7eb2Smrg static const mstring expr_types[] = {
3434627f7eb2Smrg     minit ("OP", EXPR_OP),
3435627f7eb2Smrg     minit ("FUNCTION", EXPR_FUNCTION),
3436627f7eb2Smrg     minit ("CONSTANT", EXPR_CONSTANT),
3437627f7eb2Smrg     minit ("VARIABLE", EXPR_VARIABLE),
3438627f7eb2Smrg     minit ("SUBSTRING", EXPR_SUBSTRING),
3439627f7eb2Smrg     minit ("STRUCTURE", EXPR_STRUCTURE),
3440627f7eb2Smrg     minit ("ARRAY", EXPR_ARRAY),
3441627f7eb2Smrg     minit ("NULL", EXPR_NULL),
3442627f7eb2Smrg     minit ("COMPCALL", EXPR_COMPCALL),
3443627f7eb2Smrg     minit (NULL, -1)
3444627f7eb2Smrg };
3445627f7eb2Smrg 
3446627f7eb2Smrg /* INTRINSIC_ASSIGN is missing because it is used as an index for
3447627f7eb2Smrg    generic operators, not in expressions.  INTRINSIC_USER is also
3448627f7eb2Smrg    replaced by the correct function name by the time we see it.  */
3449627f7eb2Smrg 
3450627f7eb2Smrg static const mstring intrinsics[] =
3451627f7eb2Smrg {
3452627f7eb2Smrg     minit ("UPLUS", INTRINSIC_UPLUS),
3453627f7eb2Smrg     minit ("UMINUS", INTRINSIC_UMINUS),
3454627f7eb2Smrg     minit ("PLUS", INTRINSIC_PLUS),
3455627f7eb2Smrg     minit ("MINUS", INTRINSIC_MINUS),
3456627f7eb2Smrg     minit ("TIMES", INTRINSIC_TIMES),
3457627f7eb2Smrg     minit ("DIVIDE", INTRINSIC_DIVIDE),
3458627f7eb2Smrg     minit ("POWER", INTRINSIC_POWER),
3459627f7eb2Smrg     minit ("CONCAT", INTRINSIC_CONCAT),
3460627f7eb2Smrg     minit ("AND", INTRINSIC_AND),
3461627f7eb2Smrg     minit ("OR", INTRINSIC_OR),
3462627f7eb2Smrg     minit ("EQV", INTRINSIC_EQV),
3463627f7eb2Smrg     minit ("NEQV", INTRINSIC_NEQV),
3464627f7eb2Smrg     minit ("EQ_SIGN", INTRINSIC_EQ),
3465627f7eb2Smrg     minit ("EQ", INTRINSIC_EQ_OS),
3466627f7eb2Smrg     minit ("NE_SIGN", INTRINSIC_NE),
3467627f7eb2Smrg     minit ("NE", INTRINSIC_NE_OS),
3468627f7eb2Smrg     minit ("GT_SIGN", INTRINSIC_GT),
3469627f7eb2Smrg     minit ("GT", INTRINSIC_GT_OS),
3470627f7eb2Smrg     minit ("GE_SIGN", INTRINSIC_GE),
3471627f7eb2Smrg     minit ("GE", INTRINSIC_GE_OS),
3472627f7eb2Smrg     minit ("LT_SIGN", INTRINSIC_LT),
3473627f7eb2Smrg     minit ("LT", INTRINSIC_LT_OS),
3474627f7eb2Smrg     minit ("LE_SIGN", INTRINSIC_LE),
3475627f7eb2Smrg     minit ("LE", INTRINSIC_LE_OS),
3476627f7eb2Smrg     minit ("NOT", INTRINSIC_NOT),
3477627f7eb2Smrg     minit ("PARENTHESES", INTRINSIC_PARENTHESES),
3478627f7eb2Smrg     minit ("USER", INTRINSIC_USER),
3479627f7eb2Smrg     minit (NULL, -1)
3480627f7eb2Smrg };
3481627f7eb2Smrg 
3482627f7eb2Smrg 
3483627f7eb2Smrg /* Remedy a couple of situations where the gfc_expr's can be defective.  */
3484627f7eb2Smrg 
3485627f7eb2Smrg static void
fix_mio_expr(gfc_expr * e)3486627f7eb2Smrg fix_mio_expr (gfc_expr *e)
3487627f7eb2Smrg {
3488627f7eb2Smrg   gfc_symtree *ns_st = NULL;
3489627f7eb2Smrg   const char *fname;
3490627f7eb2Smrg 
3491627f7eb2Smrg   if (iomode != IO_OUTPUT)
3492627f7eb2Smrg     return;
3493627f7eb2Smrg 
3494627f7eb2Smrg   if (e->symtree)
3495627f7eb2Smrg     {
3496627f7eb2Smrg       /* If this is a symtree for a symbol that came from a contained module
3497627f7eb2Smrg 	 namespace, it has a unique name and we should look in the current
3498627f7eb2Smrg 	 namespace to see if the required, non-contained symbol is available
3499627f7eb2Smrg 	 yet. If so, the latter should be written.  */
3500627f7eb2Smrg       if (e->symtree->n.sym && check_unique_name (e->symtree->name))
3501627f7eb2Smrg 	{
3502627f7eb2Smrg           const char *name = e->symtree->n.sym->name;
3503627f7eb2Smrg 	  if (gfc_fl_struct (e->symtree->n.sym->attr.flavor))
3504627f7eb2Smrg 	    name = gfc_dt_upper_string (name);
3505627f7eb2Smrg 	  ns_st = gfc_find_symtree (gfc_current_ns->sym_root, name);
3506627f7eb2Smrg 	}
3507627f7eb2Smrg 
3508627f7eb2Smrg       /* On the other hand, if the existing symbol is the module name or the
3509627f7eb2Smrg 	 new symbol is a dummy argument, do not do the promotion.  */
3510627f7eb2Smrg       if (ns_st && ns_st->n.sym
3511627f7eb2Smrg 	  && ns_st->n.sym->attr.flavor != FL_MODULE
3512627f7eb2Smrg 	  && !e->symtree->n.sym->attr.dummy)
3513627f7eb2Smrg 	e->symtree = ns_st;
3514627f7eb2Smrg     }
3515627f7eb2Smrg   else if (e->expr_type == EXPR_FUNCTION
3516627f7eb2Smrg 	   && (e->value.function.name || e->value.function.isym))
3517627f7eb2Smrg     {
3518627f7eb2Smrg       gfc_symbol *sym;
3519627f7eb2Smrg 
3520627f7eb2Smrg       /* In some circumstances, a function used in an initialization
3521627f7eb2Smrg 	 expression, in one use associated module, can fail to be
3522627f7eb2Smrg 	 coupled to its symtree when used in a specification
3523627f7eb2Smrg 	 expression in another module.  */
3524627f7eb2Smrg       fname = e->value.function.esym ? e->value.function.esym->name
3525627f7eb2Smrg 				     : e->value.function.isym->name;
3526627f7eb2Smrg       e->symtree = gfc_find_symtree (gfc_current_ns->sym_root, fname);
3527627f7eb2Smrg 
3528627f7eb2Smrg       if (e->symtree)
3529627f7eb2Smrg 	return;
3530627f7eb2Smrg 
3531627f7eb2Smrg       /* This is probably a reference to a private procedure from another
3532627f7eb2Smrg 	 module.  To prevent a segfault, make a generic with no specific
3533627f7eb2Smrg 	 instances.  If this module is used, without the required
3534627f7eb2Smrg 	 specific coming from somewhere, the appropriate error message
3535627f7eb2Smrg 	 is issued.  */
3536627f7eb2Smrg       gfc_get_symbol (fname, gfc_current_ns, &sym);
3537627f7eb2Smrg       sym->attr.flavor = FL_PROCEDURE;
3538627f7eb2Smrg       sym->attr.generic = 1;
3539627f7eb2Smrg       e->symtree = gfc_find_symtree (gfc_current_ns->sym_root, fname);
3540627f7eb2Smrg       gfc_commit_symbol (sym);
3541627f7eb2Smrg     }
3542627f7eb2Smrg }
3543627f7eb2Smrg 
3544627f7eb2Smrg 
3545627f7eb2Smrg /* Read and write expressions.  The form "()" is allowed to indicate a
3546627f7eb2Smrg    NULL expression.  */
3547627f7eb2Smrg 
3548627f7eb2Smrg static void
mio_expr(gfc_expr ** ep)3549627f7eb2Smrg mio_expr (gfc_expr **ep)
3550627f7eb2Smrg {
3551627f7eb2Smrg   HOST_WIDE_INT hwi;
3552627f7eb2Smrg   gfc_expr *e;
3553627f7eb2Smrg   atom_type t;
3554627f7eb2Smrg   int flag;
3555627f7eb2Smrg 
3556627f7eb2Smrg   mio_lparen ();
3557627f7eb2Smrg 
3558627f7eb2Smrg   if (iomode == IO_OUTPUT)
3559627f7eb2Smrg     {
3560627f7eb2Smrg       if (*ep == NULL)
3561627f7eb2Smrg 	{
3562627f7eb2Smrg 	  mio_rparen ();
3563627f7eb2Smrg 	  return;
3564627f7eb2Smrg 	}
3565627f7eb2Smrg 
3566627f7eb2Smrg       e = *ep;
3567627f7eb2Smrg       MIO_NAME (expr_t) (e->expr_type, expr_types);
3568627f7eb2Smrg     }
3569627f7eb2Smrg   else
3570627f7eb2Smrg     {
3571627f7eb2Smrg       t = parse_atom ();
3572627f7eb2Smrg       if (t == ATOM_RPAREN)
3573627f7eb2Smrg 	{
3574627f7eb2Smrg 	  *ep = NULL;
3575627f7eb2Smrg 	  return;
3576627f7eb2Smrg 	}
3577627f7eb2Smrg 
3578627f7eb2Smrg       if (t != ATOM_NAME)
3579627f7eb2Smrg 	bad_module ("Expected expression type");
3580627f7eb2Smrg 
3581627f7eb2Smrg       e = *ep = gfc_get_expr ();
3582627f7eb2Smrg       e->where = gfc_current_locus;
3583627f7eb2Smrg       e->expr_type = (expr_t) find_enum (expr_types);
3584627f7eb2Smrg     }
3585627f7eb2Smrg 
3586627f7eb2Smrg   mio_typespec (&e->ts);
3587627f7eb2Smrg   mio_integer (&e->rank);
3588627f7eb2Smrg 
3589627f7eb2Smrg   fix_mio_expr (e);
3590627f7eb2Smrg 
3591627f7eb2Smrg   switch (e->expr_type)
3592627f7eb2Smrg     {
3593627f7eb2Smrg     case EXPR_OP:
3594627f7eb2Smrg       e->value.op.op
3595627f7eb2Smrg 	= MIO_NAME (gfc_intrinsic_op) (e->value.op.op, intrinsics);
3596627f7eb2Smrg 
3597627f7eb2Smrg       switch (e->value.op.op)
3598627f7eb2Smrg 	{
3599627f7eb2Smrg 	case INTRINSIC_UPLUS:
3600627f7eb2Smrg 	case INTRINSIC_UMINUS:
3601627f7eb2Smrg 	case INTRINSIC_NOT:
3602627f7eb2Smrg 	case INTRINSIC_PARENTHESES:
3603627f7eb2Smrg 	  mio_expr (&e->value.op.op1);
3604627f7eb2Smrg 	  break;
3605627f7eb2Smrg 
3606627f7eb2Smrg 	case INTRINSIC_PLUS:
3607627f7eb2Smrg 	case INTRINSIC_MINUS:
3608627f7eb2Smrg 	case INTRINSIC_TIMES:
3609627f7eb2Smrg 	case INTRINSIC_DIVIDE:
3610627f7eb2Smrg 	case INTRINSIC_POWER:
3611627f7eb2Smrg 	case INTRINSIC_CONCAT:
3612627f7eb2Smrg 	case INTRINSIC_AND:
3613627f7eb2Smrg 	case INTRINSIC_OR:
3614627f7eb2Smrg 	case INTRINSIC_EQV:
3615627f7eb2Smrg 	case INTRINSIC_NEQV:
3616627f7eb2Smrg 	case INTRINSIC_EQ:
3617627f7eb2Smrg 	case INTRINSIC_EQ_OS:
3618627f7eb2Smrg 	case INTRINSIC_NE:
3619627f7eb2Smrg 	case INTRINSIC_NE_OS:
3620627f7eb2Smrg 	case INTRINSIC_GT:
3621627f7eb2Smrg 	case INTRINSIC_GT_OS:
3622627f7eb2Smrg 	case INTRINSIC_GE:
3623627f7eb2Smrg 	case INTRINSIC_GE_OS:
3624627f7eb2Smrg 	case INTRINSIC_LT:
3625627f7eb2Smrg 	case INTRINSIC_LT_OS:
3626627f7eb2Smrg 	case INTRINSIC_LE:
3627627f7eb2Smrg 	case INTRINSIC_LE_OS:
3628627f7eb2Smrg 	  mio_expr (&e->value.op.op1);
3629627f7eb2Smrg 	  mio_expr (&e->value.op.op2);
3630627f7eb2Smrg 	  break;
3631627f7eb2Smrg 
3632627f7eb2Smrg 	case INTRINSIC_USER:
3633627f7eb2Smrg 	  /* INTRINSIC_USER should not appear in resolved expressions,
3634627f7eb2Smrg 	     though for UDRs we need to stream unresolved ones.  */
3635627f7eb2Smrg 	  if (iomode == IO_OUTPUT)
3636627f7eb2Smrg 	    write_atom (ATOM_STRING, e->value.op.uop->name);
3637627f7eb2Smrg 	  else
3638627f7eb2Smrg 	    {
3639627f7eb2Smrg 	      char *name = read_string ();
3640627f7eb2Smrg 	      const char *uop_name = find_use_name (name, true);
3641627f7eb2Smrg 	      if (uop_name == NULL)
3642627f7eb2Smrg 		{
3643627f7eb2Smrg 		  size_t len = strlen (name);
3644627f7eb2Smrg 		  char *name2 = XCNEWVEC (char, len + 2);
3645627f7eb2Smrg 		  memcpy (name2, name, len);
3646627f7eb2Smrg 		  name2[len] = ' ';
3647627f7eb2Smrg 		  name2[len + 1] = '\0';
3648627f7eb2Smrg 		  free (name);
3649627f7eb2Smrg 		  uop_name = name = name2;
3650627f7eb2Smrg 		}
3651627f7eb2Smrg 	      e->value.op.uop = gfc_get_uop (uop_name);
3652627f7eb2Smrg 	      free (name);
3653627f7eb2Smrg 	    }
3654627f7eb2Smrg 	  mio_expr (&e->value.op.op1);
3655627f7eb2Smrg 	  mio_expr (&e->value.op.op2);
3656627f7eb2Smrg 	  break;
3657627f7eb2Smrg 
3658627f7eb2Smrg 	default:
3659627f7eb2Smrg 	  bad_module ("Bad operator");
3660627f7eb2Smrg 	}
3661627f7eb2Smrg 
3662627f7eb2Smrg       break;
3663627f7eb2Smrg 
3664627f7eb2Smrg     case EXPR_FUNCTION:
3665627f7eb2Smrg       mio_symtree_ref (&e->symtree);
3666627f7eb2Smrg       mio_actual_arglist (&e->value.function.actual, false);
3667627f7eb2Smrg 
3668627f7eb2Smrg       if (iomode == IO_OUTPUT)
3669627f7eb2Smrg 	{
3670627f7eb2Smrg 	  e->value.function.name
3671627f7eb2Smrg 	    = mio_allocated_string (e->value.function.name);
3672627f7eb2Smrg 	  if (e->value.function.esym)
3673627f7eb2Smrg 	    flag = 1;
3674627f7eb2Smrg 	  else if (e->ref)
3675627f7eb2Smrg 	    flag = 2;
3676627f7eb2Smrg 	  else if (e->value.function.isym == NULL)
3677627f7eb2Smrg 	    flag = 3;
3678627f7eb2Smrg 	  else
3679627f7eb2Smrg 	    flag = 0;
3680627f7eb2Smrg 	  mio_integer (&flag);
3681627f7eb2Smrg 	  switch (flag)
3682627f7eb2Smrg 	    {
3683627f7eb2Smrg 	    case 1:
3684627f7eb2Smrg 	      mio_symbol_ref (&e->value.function.esym);
3685627f7eb2Smrg 	      break;
3686627f7eb2Smrg 	    case 2:
3687627f7eb2Smrg 	      mio_ref_list (&e->ref);
3688627f7eb2Smrg 	      break;
3689627f7eb2Smrg 	    case 3:
3690627f7eb2Smrg 	      break;
3691627f7eb2Smrg 	    default:
3692627f7eb2Smrg 	      write_atom (ATOM_STRING, e->value.function.isym->name);
3693627f7eb2Smrg 	    }
3694627f7eb2Smrg 	}
3695627f7eb2Smrg       else
3696627f7eb2Smrg 	{
3697627f7eb2Smrg 	  require_atom (ATOM_STRING);
3698627f7eb2Smrg 	  if (atom_string[0] == '\0')
3699627f7eb2Smrg 	    e->value.function.name = NULL;
3700627f7eb2Smrg 	  else
3701627f7eb2Smrg 	    e->value.function.name = gfc_get_string ("%s", atom_string);
3702627f7eb2Smrg 	  free (atom_string);
3703627f7eb2Smrg 
3704627f7eb2Smrg 	  mio_integer (&flag);
3705627f7eb2Smrg 	  switch (flag)
3706627f7eb2Smrg 	    {
3707627f7eb2Smrg 	    case 1:
3708627f7eb2Smrg 	      mio_symbol_ref (&e->value.function.esym);
3709627f7eb2Smrg 	      break;
3710627f7eb2Smrg 	    case 2:
3711627f7eb2Smrg 	      mio_ref_list (&e->ref);
3712627f7eb2Smrg 	      break;
3713627f7eb2Smrg 	    case 3:
3714627f7eb2Smrg 	      break;
3715627f7eb2Smrg 	    default:
3716627f7eb2Smrg 	      require_atom (ATOM_STRING);
3717627f7eb2Smrg 	      e->value.function.isym = gfc_find_function (atom_string);
3718627f7eb2Smrg 	      free (atom_string);
3719627f7eb2Smrg 	    }
3720627f7eb2Smrg 	}
3721627f7eb2Smrg 
3722627f7eb2Smrg       break;
3723627f7eb2Smrg 
3724627f7eb2Smrg     case EXPR_VARIABLE:
3725627f7eb2Smrg       mio_symtree_ref (&e->symtree);
3726627f7eb2Smrg       mio_ref_list (&e->ref);
3727627f7eb2Smrg       break;
3728627f7eb2Smrg 
3729627f7eb2Smrg     case EXPR_SUBSTRING:
3730627f7eb2Smrg       e->value.character.string
3731627f7eb2Smrg 	= CONST_CAST (gfc_char_t *,
3732627f7eb2Smrg 		      mio_allocated_wide_string (e->value.character.string,
3733627f7eb2Smrg 						 e->value.character.length));
3734627f7eb2Smrg       mio_ref_list (&e->ref);
3735627f7eb2Smrg       break;
3736627f7eb2Smrg 
3737627f7eb2Smrg     case EXPR_STRUCTURE:
3738627f7eb2Smrg     case EXPR_ARRAY:
3739627f7eb2Smrg       mio_constructor (&e->value.constructor);
3740627f7eb2Smrg       mio_shape (&e->shape, e->rank);
3741627f7eb2Smrg       break;
3742627f7eb2Smrg 
3743627f7eb2Smrg     case EXPR_CONSTANT:
3744627f7eb2Smrg       switch (e->ts.type)
3745627f7eb2Smrg 	{
3746627f7eb2Smrg 	case BT_INTEGER:
3747627f7eb2Smrg 	  mio_gmp_integer (&e->value.integer);
3748627f7eb2Smrg 	  break;
3749627f7eb2Smrg 
3750627f7eb2Smrg 	case BT_REAL:
3751627f7eb2Smrg 	  gfc_set_model_kind (e->ts.kind);
3752627f7eb2Smrg 	  mio_gmp_real (&e->value.real);
3753627f7eb2Smrg 	  break;
3754627f7eb2Smrg 
3755627f7eb2Smrg 	case BT_COMPLEX:
3756627f7eb2Smrg 	  gfc_set_model_kind (e->ts.kind);
3757627f7eb2Smrg 	  mio_gmp_real (&mpc_realref (e->value.complex));
3758627f7eb2Smrg 	  mio_gmp_real (&mpc_imagref (e->value.complex));
3759627f7eb2Smrg 	  break;
3760627f7eb2Smrg 
3761627f7eb2Smrg 	case BT_LOGICAL:
3762627f7eb2Smrg 	  mio_integer (&e->value.logical);
3763627f7eb2Smrg 	  break;
3764627f7eb2Smrg 
3765627f7eb2Smrg 	case BT_CHARACTER:
3766627f7eb2Smrg 	  hwi = e->value.character.length;
3767627f7eb2Smrg 	  mio_hwi (&hwi);
3768627f7eb2Smrg 	  e->value.character.length = hwi;
3769627f7eb2Smrg 	  e->value.character.string
3770627f7eb2Smrg 	    = CONST_CAST (gfc_char_t *,
3771627f7eb2Smrg 			  mio_allocated_wide_string (e->value.character.string,
3772627f7eb2Smrg 						     e->value.character.length));
3773627f7eb2Smrg 	  break;
3774627f7eb2Smrg 
3775627f7eb2Smrg 	default:
3776627f7eb2Smrg 	  bad_module ("Bad type in constant expression");
3777627f7eb2Smrg 	}
3778627f7eb2Smrg 
3779627f7eb2Smrg       break;
3780627f7eb2Smrg 
3781627f7eb2Smrg     case EXPR_NULL:
3782627f7eb2Smrg       break;
3783627f7eb2Smrg 
3784627f7eb2Smrg     case EXPR_COMPCALL:
3785627f7eb2Smrg     case EXPR_PPC:
3786627f7eb2Smrg     case EXPR_UNKNOWN:
3787627f7eb2Smrg       gcc_unreachable ();
3788627f7eb2Smrg       break;
3789627f7eb2Smrg     }
3790627f7eb2Smrg 
3791627f7eb2Smrg   /* PDT types store the expression specification list here. */
3792627f7eb2Smrg   mio_actual_arglist (&e->param_list, true);
3793627f7eb2Smrg 
3794627f7eb2Smrg   mio_rparen ();
3795627f7eb2Smrg }
3796627f7eb2Smrg 
3797627f7eb2Smrg 
3798627f7eb2Smrg /* Read and write namelists.  */
3799627f7eb2Smrg 
3800627f7eb2Smrg static void
mio_namelist(gfc_symbol * sym)3801627f7eb2Smrg mio_namelist (gfc_symbol *sym)
3802627f7eb2Smrg {
3803627f7eb2Smrg   gfc_namelist *n, *m;
3804627f7eb2Smrg 
3805627f7eb2Smrg   mio_lparen ();
3806627f7eb2Smrg 
3807627f7eb2Smrg   if (iomode == IO_OUTPUT)
3808627f7eb2Smrg     {
3809627f7eb2Smrg       for (n = sym->namelist; n; n = n->next)
3810627f7eb2Smrg 	mio_symbol_ref (&n->sym);
3811627f7eb2Smrg     }
3812627f7eb2Smrg   else
3813627f7eb2Smrg     {
3814627f7eb2Smrg       m = NULL;
3815627f7eb2Smrg       while (peek_atom () != ATOM_RPAREN)
3816627f7eb2Smrg 	{
3817627f7eb2Smrg 	  n = gfc_get_namelist ();
3818627f7eb2Smrg 	  mio_symbol_ref (&n->sym);
3819627f7eb2Smrg 
3820627f7eb2Smrg 	  if (sym->namelist == NULL)
3821627f7eb2Smrg 	    sym->namelist = n;
3822627f7eb2Smrg 	  else
3823627f7eb2Smrg 	    m->next = n;
3824627f7eb2Smrg 
3825627f7eb2Smrg 	  m = n;
3826627f7eb2Smrg 	}
3827627f7eb2Smrg       sym->namelist_tail = m;
3828627f7eb2Smrg     }
3829627f7eb2Smrg 
3830627f7eb2Smrg   mio_rparen ();
3831627f7eb2Smrg }
3832627f7eb2Smrg 
3833627f7eb2Smrg 
3834627f7eb2Smrg /* Save/restore lists of gfc_interface structures.  When loading an
3835627f7eb2Smrg    interface, we are really appending to the existing list of
3836627f7eb2Smrg    interfaces.  Checking for duplicate and ambiguous interfaces has to
3837627f7eb2Smrg    be done later when all symbols have been loaded.  */
3838627f7eb2Smrg 
3839627f7eb2Smrg pointer_info *
mio_interface_rest(gfc_interface ** ip)3840627f7eb2Smrg mio_interface_rest (gfc_interface **ip)
3841627f7eb2Smrg {
3842627f7eb2Smrg   gfc_interface *tail, *p;
3843627f7eb2Smrg   pointer_info *pi = NULL;
3844627f7eb2Smrg 
3845627f7eb2Smrg   if (iomode == IO_OUTPUT)
3846627f7eb2Smrg     {
3847627f7eb2Smrg       if (ip != NULL)
3848627f7eb2Smrg 	for (p = *ip; p; p = p->next)
3849627f7eb2Smrg 	  mio_symbol_ref (&p->sym);
3850627f7eb2Smrg     }
3851627f7eb2Smrg   else
3852627f7eb2Smrg     {
3853627f7eb2Smrg       if (*ip == NULL)
3854627f7eb2Smrg 	tail = NULL;
3855627f7eb2Smrg       else
3856627f7eb2Smrg 	{
3857627f7eb2Smrg 	  tail = *ip;
3858627f7eb2Smrg 	  while (tail->next)
3859627f7eb2Smrg 	    tail = tail->next;
3860627f7eb2Smrg 	}
3861627f7eb2Smrg 
3862627f7eb2Smrg       for (;;)
3863627f7eb2Smrg 	{
3864627f7eb2Smrg 	  if (peek_atom () == ATOM_RPAREN)
3865627f7eb2Smrg 	    break;
3866627f7eb2Smrg 
3867627f7eb2Smrg 	  p = gfc_get_interface ();
3868627f7eb2Smrg 	  p->where = gfc_current_locus;
3869627f7eb2Smrg 	  pi = mio_symbol_ref (&p->sym);
3870627f7eb2Smrg 
3871627f7eb2Smrg 	  if (tail == NULL)
3872627f7eb2Smrg 	    *ip = p;
3873627f7eb2Smrg 	  else
3874627f7eb2Smrg 	    tail->next = p;
3875627f7eb2Smrg 
3876627f7eb2Smrg 	  tail = p;
3877627f7eb2Smrg 	}
3878627f7eb2Smrg     }
3879627f7eb2Smrg 
3880627f7eb2Smrg   mio_rparen ();
3881627f7eb2Smrg   return pi;
3882627f7eb2Smrg }
3883627f7eb2Smrg 
3884627f7eb2Smrg 
3885627f7eb2Smrg /* Save/restore a nameless operator interface.  */
3886627f7eb2Smrg 
3887627f7eb2Smrg static void
mio_interface(gfc_interface ** ip)3888627f7eb2Smrg mio_interface (gfc_interface **ip)
3889627f7eb2Smrg {
3890627f7eb2Smrg   mio_lparen ();
3891627f7eb2Smrg   mio_interface_rest (ip);
3892627f7eb2Smrg }
3893627f7eb2Smrg 
3894627f7eb2Smrg 
3895627f7eb2Smrg /* Save/restore a named operator interface.  */
3896627f7eb2Smrg 
3897627f7eb2Smrg static void
mio_symbol_interface(const char ** name,const char ** module,gfc_interface ** ip)3898627f7eb2Smrg mio_symbol_interface (const char **name, const char **module,
3899627f7eb2Smrg 		      gfc_interface **ip)
3900627f7eb2Smrg {
3901627f7eb2Smrg   mio_lparen ();
3902627f7eb2Smrg   mio_pool_string (name);
3903627f7eb2Smrg   mio_pool_string (module);
3904627f7eb2Smrg   mio_interface_rest (ip);
3905627f7eb2Smrg }
3906627f7eb2Smrg 
3907627f7eb2Smrg 
3908627f7eb2Smrg static void
mio_namespace_ref(gfc_namespace ** nsp)3909627f7eb2Smrg mio_namespace_ref (gfc_namespace **nsp)
3910627f7eb2Smrg {
3911627f7eb2Smrg   gfc_namespace *ns;
3912627f7eb2Smrg   pointer_info *p;
3913627f7eb2Smrg 
3914627f7eb2Smrg   p = mio_pointer_ref (nsp);
3915627f7eb2Smrg 
3916627f7eb2Smrg   if (p->type == P_UNKNOWN)
3917627f7eb2Smrg     p->type = P_NAMESPACE;
3918627f7eb2Smrg 
3919627f7eb2Smrg   if (iomode == IO_INPUT && p->integer != 0)
3920627f7eb2Smrg     {
3921627f7eb2Smrg       ns = (gfc_namespace *) p->u.pointer;
3922627f7eb2Smrg       if (ns == NULL)
3923627f7eb2Smrg 	{
3924627f7eb2Smrg 	  ns = gfc_get_namespace (NULL, 0);
3925627f7eb2Smrg 	  associate_integer_pointer (p, ns);
3926627f7eb2Smrg 	}
3927627f7eb2Smrg       else
3928627f7eb2Smrg 	ns->refs++;
3929627f7eb2Smrg     }
3930627f7eb2Smrg }
3931627f7eb2Smrg 
3932627f7eb2Smrg 
3933627f7eb2Smrg /* Save/restore the f2k_derived namespace of a derived-type symbol.  */
3934627f7eb2Smrg 
3935627f7eb2Smrg static gfc_namespace* current_f2k_derived;
3936627f7eb2Smrg 
3937627f7eb2Smrg static void
mio_typebound_proc(gfc_typebound_proc ** proc)3938627f7eb2Smrg mio_typebound_proc (gfc_typebound_proc** proc)
3939627f7eb2Smrg {
3940627f7eb2Smrg   int flag;
3941627f7eb2Smrg   int overriding_flag;
3942627f7eb2Smrg 
3943627f7eb2Smrg   if (iomode == IO_INPUT)
3944627f7eb2Smrg     {
3945627f7eb2Smrg       *proc = gfc_get_typebound_proc (NULL);
3946627f7eb2Smrg       (*proc)->where = gfc_current_locus;
3947627f7eb2Smrg     }
3948627f7eb2Smrg   gcc_assert (*proc);
3949627f7eb2Smrg 
3950627f7eb2Smrg   mio_lparen ();
3951627f7eb2Smrg 
3952627f7eb2Smrg   (*proc)->access = MIO_NAME (gfc_access) ((*proc)->access, access_types);
3953627f7eb2Smrg 
3954627f7eb2Smrg   /* IO the NON_OVERRIDABLE/DEFERRED combination.  */
3955627f7eb2Smrg   gcc_assert (!((*proc)->deferred && (*proc)->non_overridable));
3956627f7eb2Smrg   overriding_flag = ((*proc)->deferred << 1) | (*proc)->non_overridable;
3957627f7eb2Smrg   overriding_flag = mio_name (overriding_flag, binding_overriding);
3958627f7eb2Smrg   (*proc)->deferred = ((overriding_flag & 2) != 0);
3959627f7eb2Smrg   (*proc)->non_overridable = ((overriding_flag & 1) != 0);
3960627f7eb2Smrg   gcc_assert (!((*proc)->deferred && (*proc)->non_overridable));
3961627f7eb2Smrg 
3962627f7eb2Smrg   (*proc)->nopass = mio_name ((*proc)->nopass, binding_passing);
3963627f7eb2Smrg   (*proc)->is_generic = mio_name ((*proc)->is_generic, binding_generic);
3964627f7eb2Smrg   (*proc)->ppc = mio_name((*proc)->ppc, binding_ppc);
3965627f7eb2Smrg 
3966627f7eb2Smrg   mio_pool_string (&((*proc)->pass_arg));
3967627f7eb2Smrg 
3968627f7eb2Smrg   flag = (int) (*proc)->pass_arg_num;
3969627f7eb2Smrg   mio_integer (&flag);
3970627f7eb2Smrg   (*proc)->pass_arg_num = (unsigned) flag;
3971627f7eb2Smrg 
3972627f7eb2Smrg   if ((*proc)->is_generic)
3973627f7eb2Smrg     {
3974627f7eb2Smrg       gfc_tbp_generic* g;
3975627f7eb2Smrg       int iop;
3976627f7eb2Smrg 
3977627f7eb2Smrg       mio_lparen ();
3978627f7eb2Smrg 
3979627f7eb2Smrg       if (iomode == IO_OUTPUT)
3980627f7eb2Smrg 	for (g = (*proc)->u.generic; g; g = g->next)
3981627f7eb2Smrg 	  {
3982627f7eb2Smrg 	    iop = (int) g->is_operator;
3983627f7eb2Smrg 	    mio_integer (&iop);
3984627f7eb2Smrg 	    mio_allocated_string (g->specific_st->name);
3985627f7eb2Smrg 	  }
3986627f7eb2Smrg       else
3987627f7eb2Smrg 	{
3988627f7eb2Smrg 	  (*proc)->u.generic = NULL;
3989627f7eb2Smrg 	  while (peek_atom () != ATOM_RPAREN)
3990627f7eb2Smrg 	    {
3991627f7eb2Smrg 	      gfc_symtree** sym_root;
3992627f7eb2Smrg 
3993627f7eb2Smrg 	      g = gfc_get_tbp_generic ();
3994627f7eb2Smrg 	      g->specific = NULL;
3995627f7eb2Smrg 
3996627f7eb2Smrg 	      mio_integer (&iop);
3997627f7eb2Smrg 	      g->is_operator = (bool) iop;
3998627f7eb2Smrg 
3999627f7eb2Smrg 	      require_atom (ATOM_STRING);
4000627f7eb2Smrg 	      sym_root = &current_f2k_derived->tb_sym_root;
4001627f7eb2Smrg 	      g->specific_st = gfc_get_tbp_symtree (sym_root, atom_string);
4002627f7eb2Smrg 	      free (atom_string);
4003627f7eb2Smrg 
4004627f7eb2Smrg 	      g->next = (*proc)->u.generic;
4005627f7eb2Smrg 	      (*proc)->u.generic = g;
4006627f7eb2Smrg 	    }
4007627f7eb2Smrg 	}
4008627f7eb2Smrg 
4009627f7eb2Smrg       mio_rparen ();
4010627f7eb2Smrg     }
4011627f7eb2Smrg   else if (!(*proc)->ppc)
4012627f7eb2Smrg     mio_symtree_ref (&(*proc)->u.specific);
4013627f7eb2Smrg 
4014627f7eb2Smrg   mio_rparen ();
4015627f7eb2Smrg }
4016627f7eb2Smrg 
4017627f7eb2Smrg /* Walker-callback function for this purpose.  */
4018627f7eb2Smrg static void
mio_typebound_symtree(gfc_symtree * st)4019627f7eb2Smrg mio_typebound_symtree (gfc_symtree* st)
4020627f7eb2Smrg {
4021627f7eb2Smrg   if (iomode == IO_OUTPUT && !st->n.tb)
4022627f7eb2Smrg     return;
4023627f7eb2Smrg 
4024627f7eb2Smrg   if (iomode == IO_OUTPUT)
4025627f7eb2Smrg     {
4026627f7eb2Smrg       mio_lparen ();
4027627f7eb2Smrg       mio_allocated_string (st->name);
4028627f7eb2Smrg     }
4029627f7eb2Smrg   /* For IO_INPUT, the above is done in mio_f2k_derived.  */
4030627f7eb2Smrg 
4031627f7eb2Smrg   mio_typebound_proc (&st->n.tb);
4032627f7eb2Smrg   mio_rparen ();
4033627f7eb2Smrg }
4034627f7eb2Smrg 
4035627f7eb2Smrg /* IO a full symtree (in all depth).  */
4036627f7eb2Smrg static void
mio_full_typebound_tree(gfc_symtree ** root)4037627f7eb2Smrg mio_full_typebound_tree (gfc_symtree** root)
4038627f7eb2Smrg {
4039627f7eb2Smrg   mio_lparen ();
4040627f7eb2Smrg 
4041627f7eb2Smrg   if (iomode == IO_OUTPUT)
4042627f7eb2Smrg     gfc_traverse_symtree (*root, &mio_typebound_symtree);
4043627f7eb2Smrg   else
4044627f7eb2Smrg     {
4045627f7eb2Smrg       while (peek_atom () == ATOM_LPAREN)
4046627f7eb2Smrg 	{
4047627f7eb2Smrg 	  gfc_symtree* st;
4048627f7eb2Smrg 
4049627f7eb2Smrg 	  mio_lparen ();
4050627f7eb2Smrg 
4051627f7eb2Smrg 	  require_atom (ATOM_STRING);
4052627f7eb2Smrg 	  st = gfc_get_tbp_symtree (root, atom_string);
4053627f7eb2Smrg 	  free (atom_string);
4054627f7eb2Smrg 
4055627f7eb2Smrg 	  mio_typebound_symtree (st);
4056627f7eb2Smrg 	}
4057627f7eb2Smrg     }
4058627f7eb2Smrg 
4059627f7eb2Smrg   mio_rparen ();
4060627f7eb2Smrg }
4061627f7eb2Smrg 
4062627f7eb2Smrg static void
mio_finalizer(gfc_finalizer ** f)4063627f7eb2Smrg mio_finalizer (gfc_finalizer **f)
4064627f7eb2Smrg {
4065627f7eb2Smrg   if (iomode == IO_OUTPUT)
4066627f7eb2Smrg     {
4067627f7eb2Smrg       gcc_assert (*f);
4068627f7eb2Smrg       gcc_assert ((*f)->proc_tree); /* Should already be resolved.  */
4069627f7eb2Smrg       mio_symtree_ref (&(*f)->proc_tree);
4070627f7eb2Smrg     }
4071627f7eb2Smrg   else
4072627f7eb2Smrg     {
4073627f7eb2Smrg       *f = gfc_get_finalizer ();
4074627f7eb2Smrg       (*f)->where = gfc_current_locus; /* Value should not matter.  */
4075627f7eb2Smrg       (*f)->next = NULL;
4076627f7eb2Smrg 
4077627f7eb2Smrg       mio_symtree_ref (&(*f)->proc_tree);
4078627f7eb2Smrg       (*f)->proc_sym = NULL;
4079627f7eb2Smrg     }
4080627f7eb2Smrg }
4081627f7eb2Smrg 
4082627f7eb2Smrg static void
mio_f2k_derived(gfc_namespace * f2k)4083627f7eb2Smrg mio_f2k_derived (gfc_namespace *f2k)
4084627f7eb2Smrg {
4085627f7eb2Smrg   current_f2k_derived = f2k;
4086627f7eb2Smrg 
4087627f7eb2Smrg   /* Handle the list of finalizer procedures.  */
4088627f7eb2Smrg   mio_lparen ();
4089627f7eb2Smrg   if (iomode == IO_OUTPUT)
4090627f7eb2Smrg     {
4091627f7eb2Smrg       gfc_finalizer *f;
4092627f7eb2Smrg       for (f = f2k->finalizers; f; f = f->next)
4093627f7eb2Smrg 	mio_finalizer (&f);
4094627f7eb2Smrg     }
4095627f7eb2Smrg   else
4096627f7eb2Smrg     {
4097627f7eb2Smrg       f2k->finalizers = NULL;
4098627f7eb2Smrg       while (peek_atom () != ATOM_RPAREN)
4099627f7eb2Smrg 	{
4100627f7eb2Smrg 	  gfc_finalizer *cur = NULL;
4101627f7eb2Smrg 	  mio_finalizer (&cur);
4102627f7eb2Smrg 	  cur->next = f2k->finalizers;
4103627f7eb2Smrg 	  f2k->finalizers = cur;
4104627f7eb2Smrg 	}
4105627f7eb2Smrg     }
4106627f7eb2Smrg   mio_rparen ();
4107627f7eb2Smrg 
4108627f7eb2Smrg   /* Handle type-bound procedures.  */
4109627f7eb2Smrg   mio_full_typebound_tree (&f2k->tb_sym_root);
4110627f7eb2Smrg 
4111627f7eb2Smrg   /* Type-bound user operators.  */
4112627f7eb2Smrg   mio_full_typebound_tree (&f2k->tb_uop_root);
4113627f7eb2Smrg 
4114627f7eb2Smrg   /* Type-bound intrinsic operators.  */
4115627f7eb2Smrg   mio_lparen ();
4116627f7eb2Smrg   if (iomode == IO_OUTPUT)
4117627f7eb2Smrg     {
4118627f7eb2Smrg       int op;
4119627f7eb2Smrg       for (op = GFC_INTRINSIC_BEGIN; op != GFC_INTRINSIC_END; ++op)
4120627f7eb2Smrg 	{
4121627f7eb2Smrg 	  gfc_intrinsic_op realop;
4122627f7eb2Smrg 
4123627f7eb2Smrg 	  if (op == INTRINSIC_USER || !f2k->tb_op[op])
4124627f7eb2Smrg 	    continue;
4125627f7eb2Smrg 
4126627f7eb2Smrg 	  mio_lparen ();
4127627f7eb2Smrg 	  realop = (gfc_intrinsic_op) op;
4128627f7eb2Smrg 	  mio_intrinsic_op (&realop);
4129627f7eb2Smrg 	  mio_typebound_proc (&f2k->tb_op[op]);
4130627f7eb2Smrg 	  mio_rparen ();
4131627f7eb2Smrg 	}
4132627f7eb2Smrg     }
4133627f7eb2Smrg   else
4134627f7eb2Smrg     while (peek_atom () != ATOM_RPAREN)
4135627f7eb2Smrg       {
4136627f7eb2Smrg 	gfc_intrinsic_op op = GFC_INTRINSIC_BEGIN; /* Silence GCC.  */
4137627f7eb2Smrg 
4138627f7eb2Smrg 	mio_lparen ();
4139627f7eb2Smrg 	mio_intrinsic_op (&op);
4140627f7eb2Smrg 	mio_typebound_proc (&f2k->tb_op[op]);
4141627f7eb2Smrg 	mio_rparen ();
4142627f7eb2Smrg       }
4143627f7eb2Smrg   mio_rparen ();
4144627f7eb2Smrg }
4145627f7eb2Smrg 
4146627f7eb2Smrg static void
mio_full_f2k_derived(gfc_symbol * sym)4147627f7eb2Smrg mio_full_f2k_derived (gfc_symbol *sym)
4148627f7eb2Smrg {
4149627f7eb2Smrg   mio_lparen ();
4150627f7eb2Smrg 
4151627f7eb2Smrg   if (iomode == IO_OUTPUT)
4152627f7eb2Smrg     {
4153627f7eb2Smrg       if (sym->f2k_derived)
4154627f7eb2Smrg 	mio_f2k_derived (sym->f2k_derived);
4155627f7eb2Smrg     }
4156627f7eb2Smrg   else
4157627f7eb2Smrg     {
4158627f7eb2Smrg       if (peek_atom () != ATOM_RPAREN)
4159627f7eb2Smrg 	{
4160627f7eb2Smrg 	  gfc_namespace *ns;
4161627f7eb2Smrg 
4162627f7eb2Smrg 	  sym->f2k_derived = gfc_get_namespace (NULL, 0);
4163627f7eb2Smrg 
4164627f7eb2Smrg 	  /* PDT templates make use of the mechanisms for formal args
4165627f7eb2Smrg 	     and so the parameter symbols are stored in the formal
4166627f7eb2Smrg 	     namespace.  Transfer the sym_root to f2k_derived and then
4167627f7eb2Smrg 	     free the formal namespace since it is uneeded.  */
4168627f7eb2Smrg 	  if (sym->attr.pdt_template && sym->formal && sym->formal->sym)
4169627f7eb2Smrg 	    {
4170627f7eb2Smrg 	      ns = sym->formal->sym->ns;
4171627f7eb2Smrg 	      sym->f2k_derived->sym_root = ns->sym_root;
4172627f7eb2Smrg 	      ns->sym_root = NULL;
4173627f7eb2Smrg 	      ns->refs++;
4174627f7eb2Smrg 	      gfc_free_namespace (ns);
4175627f7eb2Smrg 	      ns = NULL;
4176627f7eb2Smrg 	    }
4177627f7eb2Smrg 
4178627f7eb2Smrg 	  mio_f2k_derived (sym->f2k_derived);
4179627f7eb2Smrg 	}
4180627f7eb2Smrg       else
4181627f7eb2Smrg 	gcc_assert (!sym->f2k_derived);
4182627f7eb2Smrg     }
4183627f7eb2Smrg 
4184627f7eb2Smrg   mio_rparen ();
4185627f7eb2Smrg }
4186627f7eb2Smrg 
4187627f7eb2Smrg static const mstring omp_declare_simd_clauses[] =
4188627f7eb2Smrg {
4189627f7eb2Smrg     minit ("INBRANCH", 0),
4190627f7eb2Smrg     minit ("NOTINBRANCH", 1),
4191627f7eb2Smrg     minit ("SIMDLEN", 2),
4192627f7eb2Smrg     minit ("UNIFORM", 3),
4193627f7eb2Smrg     minit ("LINEAR", 4),
4194627f7eb2Smrg     minit ("ALIGNED", 5),
4195627f7eb2Smrg     minit ("LINEAR_REF", 33),
4196627f7eb2Smrg     minit ("LINEAR_VAL", 34),
4197627f7eb2Smrg     minit ("LINEAR_UVAL", 35),
4198627f7eb2Smrg     minit (NULL, -1)
4199627f7eb2Smrg };
4200627f7eb2Smrg 
4201627f7eb2Smrg /* Handle !$omp declare simd.  */
4202627f7eb2Smrg 
4203627f7eb2Smrg static void
mio_omp_declare_simd(gfc_namespace * ns,gfc_omp_declare_simd ** odsp)4204627f7eb2Smrg mio_omp_declare_simd (gfc_namespace *ns, gfc_omp_declare_simd **odsp)
4205627f7eb2Smrg {
4206627f7eb2Smrg   if (iomode == IO_OUTPUT)
4207627f7eb2Smrg     {
4208627f7eb2Smrg       if (*odsp == NULL)
4209627f7eb2Smrg 	return;
4210627f7eb2Smrg     }
4211627f7eb2Smrg   else if (peek_atom () != ATOM_LPAREN)
4212627f7eb2Smrg     return;
4213627f7eb2Smrg 
4214627f7eb2Smrg   gfc_omp_declare_simd *ods = *odsp;
4215627f7eb2Smrg 
4216627f7eb2Smrg   mio_lparen ();
4217627f7eb2Smrg   if (iomode == IO_OUTPUT)
4218627f7eb2Smrg     {
4219627f7eb2Smrg       write_atom (ATOM_NAME, "OMP_DECLARE_SIMD");
4220627f7eb2Smrg       if (ods->clauses)
4221627f7eb2Smrg 	{
4222627f7eb2Smrg 	  gfc_omp_namelist *n;
4223627f7eb2Smrg 
4224627f7eb2Smrg 	  if (ods->clauses->inbranch)
4225627f7eb2Smrg 	    mio_name (0, omp_declare_simd_clauses);
4226627f7eb2Smrg 	  if (ods->clauses->notinbranch)
4227627f7eb2Smrg 	    mio_name (1, omp_declare_simd_clauses);
4228627f7eb2Smrg 	  if (ods->clauses->simdlen_expr)
4229627f7eb2Smrg 	    {
4230627f7eb2Smrg 	      mio_name (2, omp_declare_simd_clauses);
4231627f7eb2Smrg 	      mio_expr (&ods->clauses->simdlen_expr);
4232627f7eb2Smrg 	    }
4233627f7eb2Smrg 	  for (n = ods->clauses->lists[OMP_LIST_UNIFORM]; n; n = n->next)
4234627f7eb2Smrg 	    {
4235627f7eb2Smrg 	      mio_name (3, omp_declare_simd_clauses);
4236627f7eb2Smrg 	      mio_symbol_ref (&n->sym);
4237627f7eb2Smrg 	    }
4238627f7eb2Smrg 	  for (n = ods->clauses->lists[OMP_LIST_LINEAR]; n; n = n->next)
4239627f7eb2Smrg 	    {
4240627f7eb2Smrg 	      if (n->u.linear_op == OMP_LINEAR_DEFAULT)
4241627f7eb2Smrg 		mio_name (4, omp_declare_simd_clauses);
4242627f7eb2Smrg 	      else
4243627f7eb2Smrg 		mio_name (32 + n->u.linear_op, omp_declare_simd_clauses);
4244627f7eb2Smrg 	      mio_symbol_ref (&n->sym);
4245627f7eb2Smrg 	      mio_expr (&n->expr);
4246627f7eb2Smrg 	    }
4247627f7eb2Smrg 	  for (n = ods->clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
4248627f7eb2Smrg 	    {
4249627f7eb2Smrg 	      mio_name (5, omp_declare_simd_clauses);
4250627f7eb2Smrg 	      mio_symbol_ref (&n->sym);
4251627f7eb2Smrg 	      mio_expr (&n->expr);
4252627f7eb2Smrg 	    }
4253627f7eb2Smrg 	}
4254627f7eb2Smrg     }
4255627f7eb2Smrg   else
4256627f7eb2Smrg     {
4257627f7eb2Smrg       gfc_omp_namelist **ptrs[3] = { NULL, NULL, NULL };
4258627f7eb2Smrg 
4259627f7eb2Smrg       require_atom (ATOM_NAME);
4260627f7eb2Smrg       *odsp = ods = gfc_get_omp_declare_simd ();
4261627f7eb2Smrg       ods->where = gfc_current_locus;
4262627f7eb2Smrg       ods->proc_name = ns->proc_name;
4263627f7eb2Smrg       if (peek_atom () == ATOM_NAME)
4264627f7eb2Smrg 	{
4265627f7eb2Smrg 	  ods->clauses = gfc_get_omp_clauses ();
4266627f7eb2Smrg 	  ptrs[0] = &ods->clauses->lists[OMP_LIST_UNIFORM];
4267627f7eb2Smrg 	  ptrs[1] = &ods->clauses->lists[OMP_LIST_LINEAR];
4268627f7eb2Smrg 	  ptrs[2] = &ods->clauses->lists[OMP_LIST_ALIGNED];
4269627f7eb2Smrg 	}
4270627f7eb2Smrg       while (peek_atom () == ATOM_NAME)
4271627f7eb2Smrg 	{
4272627f7eb2Smrg 	  gfc_omp_namelist *n;
4273627f7eb2Smrg 	  int t = mio_name (0, omp_declare_simd_clauses);
4274627f7eb2Smrg 
4275627f7eb2Smrg 	  switch (t)
4276627f7eb2Smrg 	    {
4277627f7eb2Smrg 	    case 0: ods->clauses->inbranch = true; break;
4278627f7eb2Smrg 	    case 1: ods->clauses->notinbranch = true; break;
4279627f7eb2Smrg 	    case 2: mio_expr (&ods->clauses->simdlen_expr); break;
4280627f7eb2Smrg 	    case 3:
4281627f7eb2Smrg 	    case 4:
4282627f7eb2Smrg 	    case 5:
4283627f7eb2Smrg 	      *ptrs[t - 3] = n = gfc_get_omp_namelist ();
4284627f7eb2Smrg 	    finish_namelist:
4285627f7eb2Smrg 	      n->where = gfc_current_locus;
4286627f7eb2Smrg 	      ptrs[t - 3] = &n->next;
4287627f7eb2Smrg 	      mio_symbol_ref (&n->sym);
4288627f7eb2Smrg 	      if (t != 3)
4289627f7eb2Smrg 		mio_expr (&n->expr);
4290627f7eb2Smrg 	      break;
4291627f7eb2Smrg 	    case 33:
4292627f7eb2Smrg 	    case 34:
4293627f7eb2Smrg 	    case 35:
4294627f7eb2Smrg 	      *ptrs[1] = n = gfc_get_omp_namelist ();
4295627f7eb2Smrg 	      n->u.linear_op = (enum gfc_omp_linear_op) (t - 32);
4296627f7eb2Smrg 	      t = 4;
4297627f7eb2Smrg 	      goto finish_namelist;
4298627f7eb2Smrg 	    }
4299627f7eb2Smrg 	}
4300627f7eb2Smrg     }
4301627f7eb2Smrg 
4302627f7eb2Smrg   mio_omp_declare_simd (ns, &ods->next);
4303627f7eb2Smrg 
4304627f7eb2Smrg   mio_rparen ();
4305627f7eb2Smrg }
4306627f7eb2Smrg 
4307627f7eb2Smrg 
4308627f7eb2Smrg static const mstring omp_declare_reduction_stmt[] =
4309627f7eb2Smrg {
4310627f7eb2Smrg     minit ("ASSIGN", 0),
4311627f7eb2Smrg     minit ("CALL", 1),
4312627f7eb2Smrg     minit (NULL, -1)
4313627f7eb2Smrg };
4314627f7eb2Smrg 
4315627f7eb2Smrg 
4316627f7eb2Smrg static void
mio_omp_udr_expr(gfc_omp_udr * udr,gfc_symbol ** sym1,gfc_symbol ** sym2,gfc_namespace * ns,bool is_initializer)4317627f7eb2Smrg mio_omp_udr_expr (gfc_omp_udr *udr, gfc_symbol **sym1, gfc_symbol **sym2,
4318627f7eb2Smrg 		  gfc_namespace *ns, bool is_initializer)
4319627f7eb2Smrg {
4320627f7eb2Smrg   if (iomode == IO_OUTPUT)
4321627f7eb2Smrg     {
4322627f7eb2Smrg       if ((*sym1)->module == NULL)
4323627f7eb2Smrg 	{
4324627f7eb2Smrg 	  (*sym1)->module = module_name;
4325627f7eb2Smrg 	  (*sym2)->module = module_name;
4326627f7eb2Smrg 	}
4327627f7eb2Smrg       mio_symbol_ref (sym1);
4328627f7eb2Smrg       mio_symbol_ref (sym2);
4329627f7eb2Smrg       if (ns->code->op == EXEC_ASSIGN)
4330627f7eb2Smrg 	{
4331627f7eb2Smrg 	  mio_name (0, omp_declare_reduction_stmt);
4332627f7eb2Smrg 	  mio_expr (&ns->code->expr1);
4333627f7eb2Smrg 	  mio_expr (&ns->code->expr2);
4334627f7eb2Smrg 	}
4335627f7eb2Smrg       else
4336627f7eb2Smrg 	{
4337627f7eb2Smrg 	  int flag;
4338627f7eb2Smrg 	  mio_name (1, omp_declare_reduction_stmt);
4339627f7eb2Smrg 	  mio_symtree_ref (&ns->code->symtree);
4340627f7eb2Smrg 	  mio_actual_arglist (&ns->code->ext.actual, false);
4341627f7eb2Smrg 
4342627f7eb2Smrg 	  flag = ns->code->resolved_isym != NULL;
4343627f7eb2Smrg 	  mio_integer (&flag);
4344627f7eb2Smrg 	  if (flag)
4345627f7eb2Smrg 	    write_atom (ATOM_STRING, ns->code->resolved_isym->name);
4346627f7eb2Smrg 	  else
4347627f7eb2Smrg 	    mio_symbol_ref (&ns->code->resolved_sym);
4348627f7eb2Smrg 	}
4349627f7eb2Smrg     }
4350627f7eb2Smrg   else
4351627f7eb2Smrg     {
4352627f7eb2Smrg       pointer_info *p1 = mio_symbol_ref (sym1);
4353627f7eb2Smrg       pointer_info *p2 = mio_symbol_ref (sym2);
4354627f7eb2Smrg       gfc_symbol *sym;
4355627f7eb2Smrg       gcc_assert (p1->u.rsym.ns == p2->u.rsym.ns);
4356627f7eb2Smrg       gcc_assert (p1->u.rsym.sym == NULL);
4357627f7eb2Smrg       /* Add hidden symbols to the symtree.  */
4358627f7eb2Smrg       pointer_info *q = get_integer (p1->u.rsym.ns);
4359627f7eb2Smrg       q->u.pointer = (void *) ns;
4360627f7eb2Smrg       sym = gfc_new_symbol (is_initializer ? "omp_priv" : "omp_out", ns);
4361627f7eb2Smrg       sym->ts = udr->ts;
4362627f7eb2Smrg       sym->module = gfc_get_string ("%s", p1->u.rsym.module);
4363627f7eb2Smrg       associate_integer_pointer (p1, sym);
4364627f7eb2Smrg       sym->attr.omp_udr_artificial_var = 1;
4365627f7eb2Smrg       gcc_assert (p2->u.rsym.sym == NULL);
4366627f7eb2Smrg       sym = gfc_new_symbol (is_initializer ? "omp_orig" : "omp_in", ns);
4367627f7eb2Smrg       sym->ts = udr->ts;
4368627f7eb2Smrg       sym->module = gfc_get_string ("%s", p2->u.rsym.module);
4369627f7eb2Smrg       associate_integer_pointer (p2, sym);
4370627f7eb2Smrg       sym->attr.omp_udr_artificial_var = 1;
4371627f7eb2Smrg       if (mio_name (0, omp_declare_reduction_stmt) == 0)
4372627f7eb2Smrg 	{
4373627f7eb2Smrg 	  ns->code = gfc_get_code (EXEC_ASSIGN);
4374627f7eb2Smrg 	  mio_expr (&ns->code->expr1);
4375627f7eb2Smrg 	  mio_expr (&ns->code->expr2);
4376627f7eb2Smrg 	}
4377627f7eb2Smrg       else
4378627f7eb2Smrg 	{
4379627f7eb2Smrg 	  int flag;
4380627f7eb2Smrg 	  ns->code = gfc_get_code (EXEC_CALL);
4381627f7eb2Smrg 	  mio_symtree_ref (&ns->code->symtree);
4382627f7eb2Smrg 	  mio_actual_arglist (&ns->code->ext.actual, false);
4383627f7eb2Smrg 
4384627f7eb2Smrg 	  mio_integer (&flag);
4385627f7eb2Smrg 	  if (flag)
4386627f7eb2Smrg 	    {
4387627f7eb2Smrg 	      require_atom (ATOM_STRING);
4388627f7eb2Smrg 	      ns->code->resolved_isym = gfc_find_subroutine (atom_string);
4389627f7eb2Smrg 	      free (atom_string);
4390627f7eb2Smrg 	    }
4391627f7eb2Smrg 	  else
4392627f7eb2Smrg 	    mio_symbol_ref (&ns->code->resolved_sym);
4393627f7eb2Smrg 	}
4394627f7eb2Smrg       ns->code->loc = gfc_current_locus;
4395627f7eb2Smrg       ns->omp_udr_ns = 1;
4396627f7eb2Smrg     }
4397627f7eb2Smrg }
4398627f7eb2Smrg 
4399627f7eb2Smrg 
4400627f7eb2Smrg /* Unlike most other routines, the address of the symbol node is already
4401627f7eb2Smrg    fixed on input and the name/module has already been filled in.
4402627f7eb2Smrg    If you update the symbol format here, don't forget to update read_module
4403627f7eb2Smrg    as well (look for "seek to the symbol's component list").   */
4404627f7eb2Smrg 
4405627f7eb2Smrg static void
mio_symbol(gfc_symbol * sym)4406627f7eb2Smrg mio_symbol (gfc_symbol *sym)
4407627f7eb2Smrg {
4408627f7eb2Smrg   int intmod = INTMOD_NONE;
4409627f7eb2Smrg 
4410627f7eb2Smrg   mio_lparen ();
4411627f7eb2Smrg 
4412627f7eb2Smrg   mio_symbol_attribute (&sym->attr);
4413627f7eb2Smrg 
4414*4c3eb207Smrg   if (sym->attr.pdt_type)
4415*4c3eb207Smrg     sym->name = gfc_dt_upper_string (sym->name);
4416*4c3eb207Smrg 
4417627f7eb2Smrg   /* Note that components are always saved, even if they are supposed
4418627f7eb2Smrg      to be private.  Component access is checked during searching.  */
4419627f7eb2Smrg   mio_component_list (&sym->components, sym->attr.vtype);
4420627f7eb2Smrg   if (sym->components != NULL)
4421627f7eb2Smrg     sym->component_access
4422627f7eb2Smrg       = MIO_NAME (gfc_access) (sym->component_access, access_types);
4423627f7eb2Smrg 
4424627f7eb2Smrg   mio_typespec (&sym->ts);
4425627f7eb2Smrg   if (sym->ts.type == BT_CLASS)
4426627f7eb2Smrg     sym->attr.class_ok = 1;
4427627f7eb2Smrg 
4428627f7eb2Smrg   if (iomode == IO_OUTPUT)
4429627f7eb2Smrg     mio_namespace_ref (&sym->formal_ns);
4430627f7eb2Smrg   else
4431627f7eb2Smrg     {
4432627f7eb2Smrg       mio_namespace_ref (&sym->formal_ns);
4433627f7eb2Smrg       if (sym->formal_ns)
4434627f7eb2Smrg 	sym->formal_ns->proc_name = sym;
4435627f7eb2Smrg     }
4436627f7eb2Smrg 
4437627f7eb2Smrg   /* Save/restore common block links.  */
4438627f7eb2Smrg   mio_symbol_ref (&sym->common_next);
4439627f7eb2Smrg 
4440627f7eb2Smrg   mio_formal_arglist (&sym->formal);
4441627f7eb2Smrg 
4442627f7eb2Smrg   if (sym->attr.flavor == FL_PARAMETER)
4443627f7eb2Smrg     mio_expr (&sym->value);
4444627f7eb2Smrg 
4445627f7eb2Smrg   mio_array_spec (&sym->as);
4446627f7eb2Smrg 
4447627f7eb2Smrg   mio_symbol_ref (&sym->result);
4448627f7eb2Smrg 
4449627f7eb2Smrg   if (sym->attr.cray_pointee)
4450627f7eb2Smrg     mio_symbol_ref (&sym->cp_pointer);
4451627f7eb2Smrg 
4452627f7eb2Smrg   /* Load/save the f2k_derived namespace of a derived-type symbol.  */
4453627f7eb2Smrg   mio_full_f2k_derived (sym);
4454627f7eb2Smrg 
4455627f7eb2Smrg   /* PDT types store the symbol specification list here. */
4456627f7eb2Smrg   mio_actual_arglist (&sym->param_list, true);
4457627f7eb2Smrg 
4458627f7eb2Smrg   mio_namelist (sym);
4459627f7eb2Smrg 
4460627f7eb2Smrg   /* Add the fields that say whether this is from an intrinsic module,
4461627f7eb2Smrg      and if so, what symbol it is within the module.  */
4462627f7eb2Smrg /*   mio_integer (&(sym->from_intmod)); */
4463627f7eb2Smrg   if (iomode == IO_OUTPUT)
4464627f7eb2Smrg     {
4465627f7eb2Smrg       intmod = sym->from_intmod;
4466627f7eb2Smrg       mio_integer (&intmod);
4467627f7eb2Smrg     }
4468627f7eb2Smrg   else
4469627f7eb2Smrg     {
4470627f7eb2Smrg       mio_integer (&intmod);
4471627f7eb2Smrg       if (current_intmod)
4472627f7eb2Smrg 	sym->from_intmod = current_intmod;
4473627f7eb2Smrg       else
4474627f7eb2Smrg 	sym->from_intmod = (intmod_id) intmod;
4475627f7eb2Smrg     }
4476627f7eb2Smrg 
4477627f7eb2Smrg   mio_integer (&(sym->intmod_sym_id));
4478627f7eb2Smrg 
4479627f7eb2Smrg   if (gfc_fl_struct (sym->attr.flavor))
4480627f7eb2Smrg     mio_integer (&(sym->hash_value));
4481627f7eb2Smrg 
4482627f7eb2Smrg   if (sym->formal_ns
4483627f7eb2Smrg       && sym->formal_ns->proc_name == sym
4484627f7eb2Smrg       && sym->formal_ns->entries == NULL)
4485627f7eb2Smrg     mio_omp_declare_simd (sym->formal_ns, &sym->formal_ns->omp_declare_simd);
4486627f7eb2Smrg 
4487627f7eb2Smrg   mio_rparen ();
4488627f7eb2Smrg }
4489627f7eb2Smrg 
4490627f7eb2Smrg 
4491627f7eb2Smrg /************************* Top level subroutines *************************/
4492627f7eb2Smrg 
4493627f7eb2Smrg /* A recursive function to look for a specific symbol by name and by
4494627f7eb2Smrg    module.  Whilst several symtrees might point to one symbol, its
4495627f7eb2Smrg    is sufficient for the purposes here than one exist.  Note that
4496627f7eb2Smrg    generic interfaces are distinguished as are symbols that have been
4497627f7eb2Smrg    renamed in another module.  */
4498627f7eb2Smrg static gfc_symtree *
find_symbol(gfc_symtree * st,const char * name,const char * module,int generic)4499627f7eb2Smrg find_symbol (gfc_symtree *st, const char *name,
4500627f7eb2Smrg 	     const char *module, int generic)
4501627f7eb2Smrg {
4502627f7eb2Smrg   int c;
4503627f7eb2Smrg   gfc_symtree *retval, *s;
4504627f7eb2Smrg 
4505627f7eb2Smrg   if (st == NULL || st->n.sym == NULL)
4506627f7eb2Smrg     return NULL;
4507627f7eb2Smrg 
4508627f7eb2Smrg   c = strcmp (name, st->n.sym->name);
4509627f7eb2Smrg   if (c == 0 && st->n.sym->module
4510627f7eb2Smrg 	     && strcmp (module, st->n.sym->module) == 0
4511627f7eb2Smrg 	     && !check_unique_name (st->name))
4512627f7eb2Smrg     {
4513627f7eb2Smrg       s = gfc_find_symtree (gfc_current_ns->sym_root, name);
4514627f7eb2Smrg 
4515627f7eb2Smrg       /* Detect symbols that are renamed by use association in another
4516627f7eb2Smrg 	 module by the absence of a symtree and null attr.use_rename,
4517627f7eb2Smrg 	 since the latter is not transmitted in the module file.  */
4518627f7eb2Smrg       if (((!generic && !st->n.sym->attr.generic)
4519627f7eb2Smrg 		|| (generic && st->n.sym->attr.generic))
4520627f7eb2Smrg 	    && !(s == NULL && !st->n.sym->attr.use_rename))
4521627f7eb2Smrg 	return st;
4522627f7eb2Smrg     }
4523627f7eb2Smrg 
4524627f7eb2Smrg   retval = find_symbol (st->left, name, module, generic);
4525627f7eb2Smrg 
4526627f7eb2Smrg   if (retval == NULL)
4527627f7eb2Smrg     retval = find_symbol (st->right, name, module, generic);
4528627f7eb2Smrg 
4529627f7eb2Smrg   return retval;
4530627f7eb2Smrg }
4531627f7eb2Smrg 
4532627f7eb2Smrg 
4533627f7eb2Smrg /* Skip a list between balanced left and right parens.
4534627f7eb2Smrg    By setting NEST_LEVEL one assumes that a number of NEST_LEVEL opening parens
4535627f7eb2Smrg    have been already parsed by hand, and the remaining of the content is to be
4536627f7eb2Smrg    skipped here.  The default value is 0 (balanced parens).  */
4537627f7eb2Smrg 
4538627f7eb2Smrg static void
4539627f7eb2Smrg skip_list (int nest_level = 0)
4540627f7eb2Smrg {
4541627f7eb2Smrg   int level;
4542627f7eb2Smrg 
4543627f7eb2Smrg   level = nest_level;
4544627f7eb2Smrg   do
4545627f7eb2Smrg     {
4546627f7eb2Smrg       switch (parse_atom ())
4547627f7eb2Smrg 	{
4548627f7eb2Smrg 	case ATOM_LPAREN:
4549627f7eb2Smrg 	  level++;
4550627f7eb2Smrg 	  break;
4551627f7eb2Smrg 
4552627f7eb2Smrg 	case ATOM_RPAREN:
4553627f7eb2Smrg 	  level--;
4554627f7eb2Smrg 	  break;
4555627f7eb2Smrg 
4556627f7eb2Smrg 	case ATOM_STRING:
4557627f7eb2Smrg 	  free (atom_string);
4558627f7eb2Smrg 	  break;
4559627f7eb2Smrg 
4560627f7eb2Smrg 	case ATOM_NAME:
4561627f7eb2Smrg 	case ATOM_INTEGER:
4562627f7eb2Smrg 	  break;
4563627f7eb2Smrg 	}
4564627f7eb2Smrg     }
4565627f7eb2Smrg   while (level > 0);
4566627f7eb2Smrg }
4567627f7eb2Smrg 
4568627f7eb2Smrg 
4569627f7eb2Smrg /* Load operator interfaces from the module.  Interfaces are unusual
4570627f7eb2Smrg    in that they attach themselves to existing symbols.  */
4571627f7eb2Smrg 
4572627f7eb2Smrg static void
load_operator_interfaces(void)4573627f7eb2Smrg load_operator_interfaces (void)
4574627f7eb2Smrg {
4575627f7eb2Smrg   const char *p;
4576*4c3eb207Smrg   /* "module" must be large enough for the case of submodules in which the name
4577*4c3eb207Smrg      has the form module.submodule */
4578*4c3eb207Smrg   char name[GFC_MAX_SYMBOL_LEN + 1], module[2 * GFC_MAX_SYMBOL_LEN + 2];
4579627f7eb2Smrg   gfc_user_op *uop;
4580627f7eb2Smrg   pointer_info *pi = NULL;
4581627f7eb2Smrg   int n, i;
4582627f7eb2Smrg 
4583627f7eb2Smrg   mio_lparen ();
4584627f7eb2Smrg 
4585627f7eb2Smrg   while (peek_atom () != ATOM_RPAREN)
4586627f7eb2Smrg     {
4587627f7eb2Smrg       mio_lparen ();
4588627f7eb2Smrg 
4589627f7eb2Smrg       mio_internal_string (name);
4590627f7eb2Smrg       mio_internal_string (module);
4591627f7eb2Smrg 
4592627f7eb2Smrg       n = number_use_names (name, true);
4593627f7eb2Smrg       n = n ? n : 1;
4594627f7eb2Smrg 
4595627f7eb2Smrg       for (i = 1; i <= n; i++)
4596627f7eb2Smrg 	{
4597627f7eb2Smrg 	  /* Decide if we need to load this one or not.  */
4598627f7eb2Smrg 	  p = find_use_name_n (name, &i, true);
4599627f7eb2Smrg 
4600627f7eb2Smrg 	  if (p == NULL)
4601627f7eb2Smrg 	    {
4602627f7eb2Smrg 	      while (parse_atom () != ATOM_RPAREN);
4603627f7eb2Smrg 	      continue;
4604627f7eb2Smrg 	    }
4605627f7eb2Smrg 
4606627f7eb2Smrg 	  if (i == 1)
4607627f7eb2Smrg 	    {
4608627f7eb2Smrg 	      uop = gfc_get_uop (p);
4609627f7eb2Smrg 	      pi = mio_interface_rest (&uop->op);
4610627f7eb2Smrg 	    }
4611627f7eb2Smrg 	  else
4612627f7eb2Smrg 	    {
4613627f7eb2Smrg 	      if (gfc_find_uop (p, NULL))
4614627f7eb2Smrg 		continue;
4615627f7eb2Smrg 	      uop = gfc_get_uop (p);
4616627f7eb2Smrg 	      uop->op = gfc_get_interface ();
4617627f7eb2Smrg 	      uop->op->where = gfc_current_locus;
4618627f7eb2Smrg 	      add_fixup (pi->integer, &uop->op->sym);
4619627f7eb2Smrg 	    }
4620627f7eb2Smrg 	}
4621627f7eb2Smrg     }
4622627f7eb2Smrg 
4623627f7eb2Smrg   mio_rparen ();
4624627f7eb2Smrg }
4625627f7eb2Smrg 
4626627f7eb2Smrg 
4627627f7eb2Smrg /* Load interfaces from the module.  Interfaces are unusual in that
4628627f7eb2Smrg    they attach themselves to existing symbols.  */
4629627f7eb2Smrg 
4630627f7eb2Smrg static void
load_generic_interfaces(void)4631627f7eb2Smrg load_generic_interfaces (void)
4632627f7eb2Smrg {
4633627f7eb2Smrg   const char *p;
4634*4c3eb207Smrg   /* "module" must be large enough for the case of submodules in which the name
4635*4c3eb207Smrg      has the form module.submodule */
4636*4c3eb207Smrg   char name[GFC_MAX_SYMBOL_LEN + 1], module[2 * GFC_MAX_SYMBOL_LEN + 2];
4637627f7eb2Smrg   gfc_symbol *sym;
4638627f7eb2Smrg   gfc_interface *generic = NULL, *gen = NULL;
4639627f7eb2Smrg   int n, i, renamed;
4640627f7eb2Smrg   bool ambiguous_set = false;
4641627f7eb2Smrg 
4642627f7eb2Smrg   mio_lparen ();
4643627f7eb2Smrg 
4644627f7eb2Smrg   while (peek_atom () != ATOM_RPAREN)
4645627f7eb2Smrg     {
4646627f7eb2Smrg       mio_lparen ();
4647627f7eb2Smrg 
4648627f7eb2Smrg       mio_internal_string (name);
4649627f7eb2Smrg       mio_internal_string (module);
4650627f7eb2Smrg 
4651627f7eb2Smrg       n = number_use_names (name, false);
4652627f7eb2Smrg       renamed = n ? 1 : 0;
4653627f7eb2Smrg       n = n ? n : 1;
4654627f7eb2Smrg 
4655627f7eb2Smrg       for (i = 1; i <= n; i++)
4656627f7eb2Smrg 	{
4657627f7eb2Smrg 	  gfc_symtree *st;
4658627f7eb2Smrg 	  /* Decide if we need to load this one or not.  */
4659627f7eb2Smrg 	  p = find_use_name_n (name, &i, false);
4660627f7eb2Smrg 
4661627f7eb2Smrg 	  if (!p || gfc_find_symbol (p, NULL, 0, &sym))
4662627f7eb2Smrg 	    {
4663627f7eb2Smrg 	      /* Skip the specific names for these cases.  */
4664627f7eb2Smrg 	      while (i == 1 && parse_atom () != ATOM_RPAREN);
4665627f7eb2Smrg 
4666627f7eb2Smrg 	      continue;
4667627f7eb2Smrg 	    }
4668627f7eb2Smrg 
4669627f7eb2Smrg 	  st = find_symbol (gfc_current_ns->sym_root,
4670627f7eb2Smrg 			    name, module_name, 1);
4671627f7eb2Smrg 
4672627f7eb2Smrg 	  /* If the symbol exists already and is being USEd without being
4673627f7eb2Smrg 	     in an ONLY clause, do not load a new symtree(11.3.2).  */
4674627f7eb2Smrg 	  if (!only_flag && st)
4675627f7eb2Smrg 	    sym = st->n.sym;
4676627f7eb2Smrg 
4677627f7eb2Smrg 	  if (!sym)
4678627f7eb2Smrg 	    {
4679627f7eb2Smrg 	      if (st)
4680627f7eb2Smrg 		{
4681627f7eb2Smrg 		  sym = st->n.sym;
4682627f7eb2Smrg 		  if (strcmp (st->name, p) != 0)
4683627f7eb2Smrg 		    {
4684627f7eb2Smrg 	              st = gfc_new_symtree (&gfc_current_ns->sym_root, p);
4685627f7eb2Smrg 		      st->n.sym = sym;
4686627f7eb2Smrg 		      sym->refs++;
4687627f7eb2Smrg 		    }
4688627f7eb2Smrg 		}
4689627f7eb2Smrg 
4690627f7eb2Smrg 	      /* Since we haven't found a valid generic interface, we had
4691627f7eb2Smrg 		 better make one.  */
4692627f7eb2Smrg 	      if (!sym)
4693627f7eb2Smrg 		{
4694627f7eb2Smrg 		  gfc_get_symbol (p, NULL, &sym);
4695627f7eb2Smrg 		  sym->name = gfc_get_string ("%s", name);
4696627f7eb2Smrg 		  sym->module = module_name;
4697627f7eb2Smrg 		  sym->attr.flavor = FL_PROCEDURE;
4698627f7eb2Smrg 		  sym->attr.generic = 1;
4699627f7eb2Smrg 		  sym->attr.use_assoc = 1;
4700627f7eb2Smrg 		}
4701627f7eb2Smrg 	    }
4702627f7eb2Smrg 	  else
4703627f7eb2Smrg 	    {
4704627f7eb2Smrg 	      /* Unless sym is a generic interface, this reference
4705627f7eb2Smrg 		 is ambiguous.  */
4706627f7eb2Smrg 	      if (st == NULL)
4707627f7eb2Smrg 	        st = gfc_find_symtree (gfc_current_ns->sym_root, p);
4708627f7eb2Smrg 
4709627f7eb2Smrg 	      sym = st->n.sym;
4710627f7eb2Smrg 
4711627f7eb2Smrg 	      if (st && !sym->attr.generic
4712627f7eb2Smrg 		     && !st->ambiguous
4713627f7eb2Smrg 		     && sym->module
4714627f7eb2Smrg 		     && strcmp (module, sym->module))
4715627f7eb2Smrg 		{
4716627f7eb2Smrg 		  ambiguous_set = true;
4717627f7eb2Smrg 		  st->ambiguous = 1;
4718627f7eb2Smrg 		}
4719627f7eb2Smrg 	    }
4720627f7eb2Smrg 
4721627f7eb2Smrg 	  sym->attr.use_only = only_flag;
4722627f7eb2Smrg 	  sym->attr.use_rename = renamed;
4723627f7eb2Smrg 
4724627f7eb2Smrg 	  if (i == 1)
4725627f7eb2Smrg 	    {
4726627f7eb2Smrg 	      mio_interface_rest (&sym->generic);
4727627f7eb2Smrg 	      generic = sym->generic;
4728627f7eb2Smrg 	    }
4729627f7eb2Smrg 	  else if (!sym->generic)
4730627f7eb2Smrg 	    {
4731627f7eb2Smrg 	      sym->generic = generic;
4732627f7eb2Smrg 	      sym->attr.generic_copy = 1;
4733627f7eb2Smrg 	    }
4734627f7eb2Smrg 
4735627f7eb2Smrg 	  /* If a procedure that is not generic has generic interfaces
4736627f7eb2Smrg 	     that include itself, it is generic! We need to take care
4737627f7eb2Smrg 	     to retain symbols ambiguous that were already so.  */
4738627f7eb2Smrg 	  if (sym->attr.use_assoc
4739627f7eb2Smrg 		&& !sym->attr.generic
4740627f7eb2Smrg 		&& sym->attr.flavor == FL_PROCEDURE)
4741627f7eb2Smrg 	    {
4742627f7eb2Smrg 	      for (gen = generic; gen; gen = gen->next)
4743627f7eb2Smrg 		{
4744627f7eb2Smrg 		  if (gen->sym == sym)
4745627f7eb2Smrg 		    {
4746627f7eb2Smrg 		      sym->attr.generic = 1;
4747627f7eb2Smrg 		      if (ambiguous_set)
4748627f7eb2Smrg 		        st->ambiguous = 0;
4749627f7eb2Smrg 		      break;
4750627f7eb2Smrg 		    }
4751627f7eb2Smrg 		}
4752627f7eb2Smrg 	    }
4753627f7eb2Smrg 
4754627f7eb2Smrg 	}
4755627f7eb2Smrg     }
4756627f7eb2Smrg 
4757627f7eb2Smrg   mio_rparen ();
4758627f7eb2Smrg }
4759627f7eb2Smrg 
4760627f7eb2Smrg 
4761627f7eb2Smrg /* Load common blocks.  */
4762627f7eb2Smrg 
4763627f7eb2Smrg static void
load_commons(void)4764627f7eb2Smrg load_commons (void)
4765627f7eb2Smrg {
4766627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
4767627f7eb2Smrg   gfc_common_head *p;
4768627f7eb2Smrg 
4769627f7eb2Smrg   mio_lparen ();
4770627f7eb2Smrg 
4771627f7eb2Smrg   while (peek_atom () != ATOM_RPAREN)
4772627f7eb2Smrg     {
4773*4c3eb207Smrg       int flags = 0;
4774627f7eb2Smrg       char* label;
4775627f7eb2Smrg       mio_lparen ();
4776627f7eb2Smrg       mio_internal_string (name);
4777627f7eb2Smrg 
4778627f7eb2Smrg       p = gfc_get_common (name, 1);
4779627f7eb2Smrg 
4780627f7eb2Smrg       mio_symbol_ref (&p->head);
4781627f7eb2Smrg       mio_integer (&flags);
4782627f7eb2Smrg       if (flags & 1)
4783627f7eb2Smrg 	p->saved = 1;
4784627f7eb2Smrg       if (flags & 2)
4785627f7eb2Smrg 	p->threadprivate = 1;
4786627f7eb2Smrg       p->use_assoc = 1;
4787627f7eb2Smrg 
4788627f7eb2Smrg       /* Get whether this was a bind(c) common or not.  */
4789627f7eb2Smrg       mio_integer (&p->is_bind_c);
4790627f7eb2Smrg       /* Get the binding label.  */
4791627f7eb2Smrg       label = read_string ();
4792627f7eb2Smrg       if (strlen (label))
4793627f7eb2Smrg 	p->binding_label = IDENTIFIER_POINTER (get_identifier (label));
4794627f7eb2Smrg       XDELETEVEC (label);
4795627f7eb2Smrg 
4796627f7eb2Smrg       mio_rparen ();
4797627f7eb2Smrg     }
4798627f7eb2Smrg 
4799627f7eb2Smrg   mio_rparen ();
4800627f7eb2Smrg }
4801627f7eb2Smrg 
4802627f7eb2Smrg 
4803627f7eb2Smrg /* Load equivalences.  The flag in_load_equiv informs mio_expr_ref of this
4804627f7eb2Smrg    so that unused variables are not loaded and so that the expression can
4805627f7eb2Smrg    be safely freed.  */
4806627f7eb2Smrg 
4807627f7eb2Smrg static void
load_equiv(void)4808627f7eb2Smrg load_equiv (void)
4809627f7eb2Smrg {
4810627f7eb2Smrg   gfc_equiv *head, *tail, *end, *eq, *equiv;
4811627f7eb2Smrg   bool duplicate;
4812627f7eb2Smrg 
4813627f7eb2Smrg   mio_lparen ();
4814627f7eb2Smrg   in_load_equiv = true;
4815627f7eb2Smrg 
4816627f7eb2Smrg   end = gfc_current_ns->equiv;
4817627f7eb2Smrg   while (end != NULL && end->next != NULL)
4818627f7eb2Smrg     end = end->next;
4819627f7eb2Smrg 
4820627f7eb2Smrg   while (peek_atom () != ATOM_RPAREN) {
4821627f7eb2Smrg     mio_lparen ();
4822627f7eb2Smrg     head = tail = NULL;
4823627f7eb2Smrg 
4824627f7eb2Smrg     while(peek_atom () != ATOM_RPAREN)
4825627f7eb2Smrg       {
4826627f7eb2Smrg 	if (head == NULL)
4827627f7eb2Smrg 	  head = tail = gfc_get_equiv ();
4828627f7eb2Smrg 	else
4829627f7eb2Smrg 	  {
4830627f7eb2Smrg 	    tail->eq = gfc_get_equiv ();
4831627f7eb2Smrg 	    tail = tail->eq;
4832627f7eb2Smrg 	  }
4833627f7eb2Smrg 
4834627f7eb2Smrg 	mio_pool_string (&tail->module);
4835627f7eb2Smrg 	mio_expr (&tail->expr);
4836627f7eb2Smrg       }
4837627f7eb2Smrg 
4838627f7eb2Smrg     /* Check for duplicate equivalences being loaded from different modules */
4839627f7eb2Smrg     duplicate = false;
4840627f7eb2Smrg     for (equiv = gfc_current_ns->equiv; equiv; equiv = equiv->next)
4841627f7eb2Smrg       {
4842627f7eb2Smrg 	if (equiv->module && head->module
4843627f7eb2Smrg 	    && strcmp (equiv->module, head->module) == 0)
4844627f7eb2Smrg 	  {
4845627f7eb2Smrg 	    duplicate = true;
4846627f7eb2Smrg 	    break;
4847627f7eb2Smrg 	  }
4848627f7eb2Smrg       }
4849627f7eb2Smrg 
4850627f7eb2Smrg     if (duplicate)
4851627f7eb2Smrg       {
4852627f7eb2Smrg 	for (eq = head; eq; eq = head)
4853627f7eb2Smrg 	  {
4854627f7eb2Smrg 	    head = eq->eq;
4855627f7eb2Smrg 	    gfc_free_expr (eq->expr);
4856627f7eb2Smrg 	    free (eq);
4857627f7eb2Smrg 	  }
4858627f7eb2Smrg       }
4859627f7eb2Smrg 
4860627f7eb2Smrg     if (end == NULL)
4861627f7eb2Smrg       gfc_current_ns->equiv = head;
4862627f7eb2Smrg     else
4863627f7eb2Smrg       end->next = head;
4864627f7eb2Smrg 
4865627f7eb2Smrg     if (head != NULL)
4866627f7eb2Smrg       end = head;
4867627f7eb2Smrg 
4868627f7eb2Smrg     mio_rparen ();
4869627f7eb2Smrg   }
4870627f7eb2Smrg 
4871627f7eb2Smrg   mio_rparen ();
4872627f7eb2Smrg   in_load_equiv = false;
4873627f7eb2Smrg }
4874627f7eb2Smrg 
4875627f7eb2Smrg 
4876627f7eb2Smrg /* This function loads OpenMP user defined reductions.  */
4877627f7eb2Smrg static void
load_omp_udrs(void)4878627f7eb2Smrg load_omp_udrs (void)
4879627f7eb2Smrg {
4880627f7eb2Smrg   mio_lparen ();
4881627f7eb2Smrg   while (peek_atom () != ATOM_RPAREN)
4882627f7eb2Smrg     {
4883627f7eb2Smrg       const char *name = NULL, *newname;
4884627f7eb2Smrg       char *altname;
4885627f7eb2Smrg       gfc_typespec ts;
4886627f7eb2Smrg       gfc_symtree *st;
4887627f7eb2Smrg       gfc_omp_reduction_op rop = OMP_REDUCTION_USER;
4888627f7eb2Smrg 
4889627f7eb2Smrg       mio_lparen ();
4890627f7eb2Smrg       mio_pool_string (&name);
4891627f7eb2Smrg       gfc_clear_ts (&ts);
4892627f7eb2Smrg       mio_typespec (&ts);
4893627f7eb2Smrg       if (gfc_str_startswith (name, "operator "))
4894627f7eb2Smrg 	{
4895627f7eb2Smrg 	  const char *p = name + sizeof ("operator ") - 1;
4896627f7eb2Smrg 	  if (strcmp (p, "+") == 0)
4897627f7eb2Smrg 	    rop = OMP_REDUCTION_PLUS;
4898627f7eb2Smrg 	  else if (strcmp (p, "*") == 0)
4899627f7eb2Smrg 	    rop = OMP_REDUCTION_TIMES;
4900627f7eb2Smrg 	  else if (strcmp (p, "-") == 0)
4901627f7eb2Smrg 	    rop = OMP_REDUCTION_MINUS;
4902627f7eb2Smrg 	  else if (strcmp (p, ".and.") == 0)
4903627f7eb2Smrg 	    rop = OMP_REDUCTION_AND;
4904627f7eb2Smrg 	  else if (strcmp (p, ".or.") == 0)
4905627f7eb2Smrg 	    rop = OMP_REDUCTION_OR;
4906627f7eb2Smrg 	  else if (strcmp (p, ".eqv.") == 0)
4907627f7eb2Smrg 	    rop = OMP_REDUCTION_EQV;
4908627f7eb2Smrg 	  else if (strcmp (p, ".neqv.") == 0)
4909627f7eb2Smrg 	    rop = OMP_REDUCTION_NEQV;
4910627f7eb2Smrg 	}
4911627f7eb2Smrg       altname = NULL;
4912627f7eb2Smrg       if (rop == OMP_REDUCTION_USER && name[0] == '.')
4913627f7eb2Smrg 	{
4914627f7eb2Smrg 	  size_t len = strlen (name + 1);
4915627f7eb2Smrg 	  altname = XALLOCAVEC (char, len);
4916627f7eb2Smrg 	  gcc_assert (name[len] == '.');
4917627f7eb2Smrg 	  memcpy (altname, name + 1, len - 1);
4918627f7eb2Smrg 	  altname[len - 1] = '\0';
4919627f7eb2Smrg 	}
4920627f7eb2Smrg       newname = name;
4921627f7eb2Smrg       if (rop == OMP_REDUCTION_USER)
4922627f7eb2Smrg 	newname = find_use_name (altname ? altname : name, !!altname);
4923627f7eb2Smrg       else if (only_flag && find_use_operator ((gfc_intrinsic_op) rop) == NULL)
4924627f7eb2Smrg 	newname = NULL;
4925627f7eb2Smrg       if (newname == NULL)
4926627f7eb2Smrg 	{
4927627f7eb2Smrg 	  skip_list (1);
4928627f7eb2Smrg 	  continue;
4929627f7eb2Smrg 	}
4930627f7eb2Smrg       if (altname && newname != altname)
4931627f7eb2Smrg 	{
4932627f7eb2Smrg 	  size_t len = strlen (newname);
4933627f7eb2Smrg 	  altname = XALLOCAVEC (char, len + 3);
4934627f7eb2Smrg 	  altname[0] = '.';
4935627f7eb2Smrg 	  memcpy (altname + 1, newname, len);
4936627f7eb2Smrg 	  altname[len + 1] = '.';
4937627f7eb2Smrg 	  altname[len + 2] = '\0';
4938627f7eb2Smrg 	  name = gfc_get_string ("%s", altname);
4939627f7eb2Smrg 	}
4940627f7eb2Smrg       st = gfc_find_symtree (gfc_current_ns->omp_udr_root, name);
4941627f7eb2Smrg       gfc_omp_udr *udr = gfc_omp_udr_find (st, &ts);
4942627f7eb2Smrg       if (udr)
4943627f7eb2Smrg 	{
4944627f7eb2Smrg 	  require_atom (ATOM_INTEGER);
4945627f7eb2Smrg 	  pointer_info *p = get_integer (atom_int);
4946627f7eb2Smrg 	  if (strcmp (p->u.rsym.module, udr->omp_out->module))
4947627f7eb2Smrg 	    {
4948627f7eb2Smrg 	      gfc_error ("Ambiguous !$OMP DECLARE REDUCTION from "
4949627f7eb2Smrg 			 "module %s at %L",
4950627f7eb2Smrg 			 p->u.rsym.module, &gfc_current_locus);
4951627f7eb2Smrg 	      gfc_error ("Previous !$OMP DECLARE REDUCTION from module "
4952627f7eb2Smrg 			 "%s at %L",
4953627f7eb2Smrg 			 udr->omp_out->module, &udr->where);
4954627f7eb2Smrg 	    }
4955627f7eb2Smrg 	  skip_list (1);
4956627f7eb2Smrg 	  continue;
4957627f7eb2Smrg 	}
4958627f7eb2Smrg       udr = gfc_get_omp_udr ();
4959627f7eb2Smrg       udr->name = name;
4960627f7eb2Smrg       udr->rop = rop;
4961627f7eb2Smrg       udr->ts = ts;
4962627f7eb2Smrg       udr->where = gfc_current_locus;
4963627f7eb2Smrg       udr->combiner_ns = gfc_get_namespace (gfc_current_ns, 1);
4964627f7eb2Smrg       udr->combiner_ns->proc_name = gfc_current_ns->proc_name;
4965627f7eb2Smrg       mio_omp_udr_expr (udr, &udr->omp_out, &udr->omp_in, udr->combiner_ns,
4966627f7eb2Smrg 			false);
4967627f7eb2Smrg       if (peek_atom () != ATOM_RPAREN)
4968627f7eb2Smrg 	{
4969627f7eb2Smrg 	  udr->initializer_ns = gfc_get_namespace (gfc_current_ns, 1);
4970627f7eb2Smrg 	  udr->initializer_ns->proc_name = gfc_current_ns->proc_name;
4971627f7eb2Smrg 	  mio_omp_udr_expr (udr, &udr->omp_priv, &udr->omp_orig,
4972627f7eb2Smrg 			    udr->initializer_ns, true);
4973627f7eb2Smrg 	}
4974627f7eb2Smrg       if (st)
4975627f7eb2Smrg 	{
4976627f7eb2Smrg 	  udr->next = st->n.omp_udr;
4977627f7eb2Smrg 	  st->n.omp_udr = udr;
4978627f7eb2Smrg 	}
4979627f7eb2Smrg       else
4980627f7eb2Smrg 	{
4981627f7eb2Smrg 	  st = gfc_new_symtree (&gfc_current_ns->omp_udr_root, name);
4982627f7eb2Smrg 	  st->n.omp_udr = udr;
4983627f7eb2Smrg 	}
4984627f7eb2Smrg       mio_rparen ();
4985627f7eb2Smrg     }
4986627f7eb2Smrg   mio_rparen ();
4987627f7eb2Smrg }
4988627f7eb2Smrg 
4989627f7eb2Smrg 
4990627f7eb2Smrg /* Recursive function to traverse the pointer_info tree and load a
4991627f7eb2Smrg    needed symbol.  We return nonzero if we load a symbol and stop the
4992627f7eb2Smrg    traversal, because the act of loading can alter the tree.  */
4993627f7eb2Smrg 
4994627f7eb2Smrg static int
load_needed(pointer_info * p)4995627f7eb2Smrg load_needed (pointer_info *p)
4996627f7eb2Smrg {
4997627f7eb2Smrg   gfc_namespace *ns;
4998627f7eb2Smrg   pointer_info *q;
4999627f7eb2Smrg   gfc_symbol *sym;
5000627f7eb2Smrg   int rv;
5001627f7eb2Smrg 
5002627f7eb2Smrg   rv = 0;
5003627f7eb2Smrg   if (p == NULL)
5004627f7eb2Smrg     return rv;
5005627f7eb2Smrg 
5006627f7eb2Smrg   rv |= load_needed (p->left);
5007627f7eb2Smrg   rv |= load_needed (p->right);
5008627f7eb2Smrg 
5009627f7eb2Smrg   if (p->type != P_SYMBOL || p->u.rsym.state != NEEDED)
5010627f7eb2Smrg     return rv;
5011627f7eb2Smrg 
5012627f7eb2Smrg   p->u.rsym.state = USED;
5013627f7eb2Smrg 
5014627f7eb2Smrg   set_module_locus (&p->u.rsym.where);
5015627f7eb2Smrg 
5016627f7eb2Smrg   sym = p->u.rsym.sym;
5017627f7eb2Smrg   if (sym == NULL)
5018627f7eb2Smrg     {
5019627f7eb2Smrg       q = get_integer (p->u.rsym.ns);
5020627f7eb2Smrg 
5021627f7eb2Smrg       ns = (gfc_namespace *) q->u.pointer;
5022627f7eb2Smrg       if (ns == NULL)
5023627f7eb2Smrg 	{
5024627f7eb2Smrg 	  /* Create an interface namespace if necessary.  These are
5025627f7eb2Smrg 	     the namespaces that hold the formal parameters of module
5026627f7eb2Smrg 	     procedures.  */
5027627f7eb2Smrg 
5028627f7eb2Smrg 	  ns = gfc_get_namespace (NULL, 0);
5029627f7eb2Smrg 	  associate_integer_pointer (q, ns);
5030627f7eb2Smrg 	}
5031627f7eb2Smrg 
5032627f7eb2Smrg       /* Use the module sym as 'proc_name' so that gfc_get_symbol_decl
5033627f7eb2Smrg 	 doesn't go pear-shaped if the symbol is used.  */
5034627f7eb2Smrg       if (!ns->proc_name)
5035627f7eb2Smrg 	gfc_find_symbol (p->u.rsym.module, gfc_current_ns,
5036627f7eb2Smrg 				 1, &ns->proc_name);
5037627f7eb2Smrg 
5038627f7eb2Smrg       sym = gfc_new_symbol (p->u.rsym.true_name, ns);
5039627f7eb2Smrg       sym->name = gfc_dt_lower_string (p->u.rsym.true_name);
5040627f7eb2Smrg       sym->module = gfc_get_string ("%s", p->u.rsym.module);
5041627f7eb2Smrg       if (p->u.rsym.binding_label)
5042627f7eb2Smrg 	sym->binding_label = IDENTIFIER_POINTER (get_identifier
5043627f7eb2Smrg 						 (p->u.rsym.binding_label));
5044627f7eb2Smrg 
5045627f7eb2Smrg       associate_integer_pointer (p, sym);
5046627f7eb2Smrg     }
5047627f7eb2Smrg 
5048627f7eb2Smrg   mio_symbol (sym);
5049627f7eb2Smrg   sym->attr.use_assoc = 1;
5050627f7eb2Smrg 
5051627f7eb2Smrg   /* Unliked derived types, a STRUCTURE may share names with other symbols.
5052*4c3eb207Smrg      We greedily converted the symbol name to lowercase before we knew its
5053627f7eb2Smrg      type, so now we must fix it. */
5054627f7eb2Smrg   if (sym->attr.flavor == FL_STRUCT)
5055627f7eb2Smrg     sym->name = gfc_dt_upper_string (sym->name);
5056627f7eb2Smrg 
5057627f7eb2Smrg   /* Mark as only or rename for later diagnosis for explicitly imported
5058627f7eb2Smrg      but not used warnings; don't mark internal symbols such as __vtab,
5059627f7eb2Smrg      __def_init etc. Only mark them if they have been explicitly loaded.  */
5060627f7eb2Smrg 
5061627f7eb2Smrg   if (only_flag && sym->name[0] != '_' && sym->name[1] != '_')
5062627f7eb2Smrg     {
5063627f7eb2Smrg       gfc_use_rename *u;
5064627f7eb2Smrg 
5065627f7eb2Smrg       /* Search the use/rename list for the variable; if the variable is
5066627f7eb2Smrg 	 found, mark it.  */
5067627f7eb2Smrg       for (u = gfc_rename_list; u; u = u->next)
5068627f7eb2Smrg 	{
5069627f7eb2Smrg 	  if (strcmp (u->use_name, sym->name) == 0)
5070627f7eb2Smrg 	    {
5071627f7eb2Smrg 	      sym->attr.use_only = 1;
5072627f7eb2Smrg 	      break;
5073627f7eb2Smrg 	    }
5074627f7eb2Smrg 	}
5075627f7eb2Smrg     }
5076627f7eb2Smrg 
5077627f7eb2Smrg   if (p->u.rsym.renamed)
5078627f7eb2Smrg     sym->attr.use_rename = 1;
5079627f7eb2Smrg 
5080627f7eb2Smrg   return 1;
5081627f7eb2Smrg }
5082627f7eb2Smrg 
5083627f7eb2Smrg 
5084627f7eb2Smrg /* Recursive function for cleaning up things after a module has been read.  */
5085627f7eb2Smrg 
5086627f7eb2Smrg static void
read_cleanup(pointer_info * p)5087627f7eb2Smrg read_cleanup (pointer_info *p)
5088627f7eb2Smrg {
5089627f7eb2Smrg   gfc_symtree *st;
5090627f7eb2Smrg   pointer_info *q;
5091627f7eb2Smrg 
5092627f7eb2Smrg   if (p == NULL)
5093627f7eb2Smrg     return;
5094627f7eb2Smrg 
5095627f7eb2Smrg   read_cleanup (p->left);
5096627f7eb2Smrg   read_cleanup (p->right);
5097627f7eb2Smrg 
5098627f7eb2Smrg   if (p->type == P_SYMBOL && p->u.rsym.state == USED && !p->u.rsym.referenced)
5099627f7eb2Smrg     {
5100627f7eb2Smrg       gfc_namespace *ns;
5101627f7eb2Smrg       /* Add hidden symbols to the symtree.  */
5102627f7eb2Smrg       q = get_integer (p->u.rsym.ns);
5103627f7eb2Smrg       ns = (gfc_namespace *) q->u.pointer;
5104627f7eb2Smrg 
5105627f7eb2Smrg       if (!p->u.rsym.sym->attr.vtype
5106627f7eb2Smrg 	    && !p->u.rsym.sym->attr.vtab)
5107627f7eb2Smrg 	st = gfc_get_unique_symtree (ns);
5108627f7eb2Smrg       else
5109627f7eb2Smrg 	{
5110627f7eb2Smrg 	  /* There is no reason to use 'unique_symtrees' for vtabs or
5111627f7eb2Smrg 	     vtypes - their name is fine for a symtree and reduces the
5112627f7eb2Smrg 	     namespace pollution.  */
5113627f7eb2Smrg 	  st = gfc_find_symtree (ns->sym_root, p->u.rsym.sym->name);
5114627f7eb2Smrg 	  if (!st)
5115627f7eb2Smrg 	    st = gfc_new_symtree (&ns->sym_root, p->u.rsym.sym->name);
5116627f7eb2Smrg 	}
5117627f7eb2Smrg 
5118627f7eb2Smrg       st->n.sym = p->u.rsym.sym;
5119627f7eb2Smrg       st->n.sym->refs++;
5120627f7eb2Smrg 
5121627f7eb2Smrg       /* Fixup any symtree references.  */
5122627f7eb2Smrg       p->u.rsym.symtree = st;
5123627f7eb2Smrg       resolve_fixups (p->u.rsym.stfixup, st);
5124627f7eb2Smrg       p->u.rsym.stfixup = NULL;
5125627f7eb2Smrg     }
5126627f7eb2Smrg 
5127627f7eb2Smrg   /* Free unused symbols.  */
5128627f7eb2Smrg   if (p->type == P_SYMBOL && p->u.rsym.state == UNUSED)
5129627f7eb2Smrg     gfc_free_symbol (p->u.rsym.sym);
5130627f7eb2Smrg }
5131627f7eb2Smrg 
5132627f7eb2Smrg 
5133627f7eb2Smrg /* It is not quite enough to check for ambiguity in the symbols by
5134627f7eb2Smrg    the loaded symbol and the new symbol not being identical.  */
5135627f7eb2Smrg static bool
check_for_ambiguous(gfc_symtree * st,pointer_info * info)5136627f7eb2Smrg check_for_ambiguous (gfc_symtree *st, pointer_info *info)
5137627f7eb2Smrg {
5138627f7eb2Smrg   gfc_symbol *rsym;
5139627f7eb2Smrg   module_locus locus;
5140627f7eb2Smrg   symbol_attribute attr;
5141627f7eb2Smrg   gfc_symbol *st_sym;
5142627f7eb2Smrg 
5143627f7eb2Smrg   if (gfc_current_ns->proc_name && st->name == gfc_current_ns->proc_name->name)
5144627f7eb2Smrg     {
5145627f7eb2Smrg       gfc_error ("%qs of module %qs, imported at %C, is also the name of the "
5146627f7eb2Smrg 		 "current program unit", st->name, module_name);
5147627f7eb2Smrg       return true;
5148627f7eb2Smrg     }
5149627f7eb2Smrg 
5150627f7eb2Smrg   st_sym = st->n.sym;
5151627f7eb2Smrg   rsym = info->u.rsym.sym;
5152627f7eb2Smrg   if (st_sym == rsym)
5153627f7eb2Smrg     return false;
5154627f7eb2Smrg 
5155627f7eb2Smrg   if (st_sym->attr.vtab || st_sym->attr.vtype)
5156627f7eb2Smrg     return false;
5157627f7eb2Smrg 
5158627f7eb2Smrg   /* If the existing symbol is generic from a different module and
5159627f7eb2Smrg      the new symbol is generic there can be no ambiguity.  */
5160627f7eb2Smrg   if (st_sym->attr.generic
5161627f7eb2Smrg 	&& st_sym->module
5162627f7eb2Smrg 	&& st_sym->module != module_name)
5163627f7eb2Smrg     {
5164627f7eb2Smrg       /* The new symbol's attributes have not yet been read.  Since
5165627f7eb2Smrg 	 we need attr.generic, read it directly.  */
5166627f7eb2Smrg       get_module_locus (&locus);
5167627f7eb2Smrg       set_module_locus (&info->u.rsym.where);
5168627f7eb2Smrg       mio_lparen ();
5169627f7eb2Smrg       attr.generic = 0;
5170627f7eb2Smrg       mio_symbol_attribute (&attr);
5171627f7eb2Smrg       set_module_locus (&locus);
5172627f7eb2Smrg       if (attr.generic)
5173627f7eb2Smrg 	return false;
5174627f7eb2Smrg     }
5175627f7eb2Smrg 
5176627f7eb2Smrg   return true;
5177627f7eb2Smrg }
5178627f7eb2Smrg 
5179627f7eb2Smrg 
5180627f7eb2Smrg /* Read a module file.  */
5181627f7eb2Smrg 
5182627f7eb2Smrg static void
read_module(void)5183627f7eb2Smrg read_module (void)
5184627f7eb2Smrg {
5185627f7eb2Smrg   module_locus operator_interfaces, user_operators, omp_udrs;
5186627f7eb2Smrg   const char *p;
5187627f7eb2Smrg   char name[GFC_MAX_SYMBOL_LEN + 1];
5188627f7eb2Smrg   int i;
5189627f7eb2Smrg   /* Workaround -Wmaybe-uninitialized false positive during
5190627f7eb2Smrg      profiledbootstrap by initializing them.  */
5191627f7eb2Smrg   int ambiguous = 0, j, nuse, symbol = 0;
5192627f7eb2Smrg   pointer_info *info, *q;
5193627f7eb2Smrg   gfc_use_rename *u = NULL;
5194627f7eb2Smrg   gfc_symtree *st;
5195627f7eb2Smrg   gfc_symbol *sym;
5196627f7eb2Smrg 
5197627f7eb2Smrg   get_module_locus (&operator_interfaces);	/* Skip these for now.  */
5198627f7eb2Smrg   skip_list ();
5199627f7eb2Smrg 
5200627f7eb2Smrg   get_module_locus (&user_operators);
5201627f7eb2Smrg   skip_list ();
5202627f7eb2Smrg   skip_list ();
5203627f7eb2Smrg 
5204627f7eb2Smrg   /* Skip commons and equivalences for now.  */
5205627f7eb2Smrg   skip_list ();
5206627f7eb2Smrg   skip_list ();
5207627f7eb2Smrg 
5208627f7eb2Smrg   /* Skip OpenMP UDRs.  */
5209627f7eb2Smrg   get_module_locus (&omp_udrs);
5210627f7eb2Smrg   skip_list ();
5211627f7eb2Smrg 
5212627f7eb2Smrg   mio_lparen ();
5213627f7eb2Smrg 
5214627f7eb2Smrg   /* Create the fixup nodes for all the symbols.  */
5215627f7eb2Smrg 
5216627f7eb2Smrg   while (peek_atom () != ATOM_RPAREN)
5217627f7eb2Smrg     {
5218627f7eb2Smrg       char* bind_label;
5219627f7eb2Smrg       require_atom (ATOM_INTEGER);
5220627f7eb2Smrg       info = get_integer (atom_int);
5221627f7eb2Smrg 
5222627f7eb2Smrg       info->type = P_SYMBOL;
5223627f7eb2Smrg       info->u.rsym.state = UNUSED;
5224627f7eb2Smrg 
5225627f7eb2Smrg       info->u.rsym.true_name = read_string ();
5226627f7eb2Smrg       info->u.rsym.module = read_string ();
5227627f7eb2Smrg       bind_label = read_string ();
5228627f7eb2Smrg       if (strlen (bind_label))
5229627f7eb2Smrg 	info->u.rsym.binding_label = bind_label;
5230627f7eb2Smrg       else
5231627f7eb2Smrg 	XDELETEVEC (bind_label);
5232627f7eb2Smrg 
5233627f7eb2Smrg       require_atom (ATOM_INTEGER);
5234627f7eb2Smrg       info->u.rsym.ns = atom_int;
5235627f7eb2Smrg 
5236627f7eb2Smrg       get_module_locus (&info->u.rsym.where);
5237627f7eb2Smrg 
5238627f7eb2Smrg       /* See if the symbol has already been loaded by a previous module.
5239627f7eb2Smrg 	 If so, we reference the existing symbol and prevent it from
5240627f7eb2Smrg 	 being loaded again.  This should not happen if the symbol being
5241627f7eb2Smrg 	 read is an index for an assumed shape dummy array (ns != 1).  */
5242627f7eb2Smrg 
5243627f7eb2Smrg       sym = find_true_name (info->u.rsym.true_name, info->u.rsym.module);
5244627f7eb2Smrg 
5245627f7eb2Smrg       if (sym == NULL
5246627f7eb2Smrg 	  || (sym->attr.flavor == FL_VARIABLE && info->u.rsym.ns !=1))
5247627f7eb2Smrg 	{
5248627f7eb2Smrg 	  skip_list ();
5249627f7eb2Smrg 	  continue;
5250627f7eb2Smrg 	}
5251627f7eb2Smrg 
5252627f7eb2Smrg       info->u.rsym.state = USED;
5253627f7eb2Smrg       info->u.rsym.sym = sym;
5254627f7eb2Smrg       /* The current symbol has already been loaded, so we can avoid loading
5255627f7eb2Smrg 	 it again.  However, if it is a derived type, some of its components
5256627f7eb2Smrg 	 can be used in expressions in the module.  To avoid the module loading
5257627f7eb2Smrg 	 failing, we need to associate the module's component pointer indexes
5258627f7eb2Smrg 	 with the existing symbol's component pointers.  */
5259627f7eb2Smrg       if (gfc_fl_struct (sym->attr.flavor))
5260627f7eb2Smrg 	{
5261627f7eb2Smrg 	  gfc_component *c;
5262627f7eb2Smrg 
5263627f7eb2Smrg 	  /* First seek to the symbol's component list.  */
5264627f7eb2Smrg 	  mio_lparen (); /* symbol opening.  */
5265627f7eb2Smrg 	  skip_list (); /* skip symbol attribute.  */
5266627f7eb2Smrg 
5267627f7eb2Smrg 	  mio_lparen (); /* component list opening.  */
5268627f7eb2Smrg 	  for (c = sym->components; c; c = c->next)
5269627f7eb2Smrg 	    {
5270627f7eb2Smrg 	      pointer_info *p;
5271*4c3eb207Smrg 	      const char *comp_name = NULL;
5272*4c3eb207Smrg 	      int n = 0;
5273627f7eb2Smrg 
5274627f7eb2Smrg 	      mio_lparen (); /* component opening.  */
5275627f7eb2Smrg 	      mio_integer (&n);
5276627f7eb2Smrg 	      p = get_integer (n);
5277627f7eb2Smrg 	      if (p->u.pointer == NULL)
5278627f7eb2Smrg 		associate_integer_pointer (p, c);
5279627f7eb2Smrg 	      mio_pool_string (&comp_name);
5280627f7eb2Smrg 	      if (comp_name != c->name)
5281627f7eb2Smrg 		{
5282627f7eb2Smrg 		  gfc_fatal_error ("Mismatch in components of derived type "
5283627f7eb2Smrg 				   "%qs from %qs at %C: expecting %qs, "
5284627f7eb2Smrg 				   "but got %qs", sym->name, sym->module,
5285627f7eb2Smrg 				   c->name, comp_name);
5286627f7eb2Smrg 		}
5287627f7eb2Smrg 	      skip_list (1); /* component end.  */
5288627f7eb2Smrg 	    }
5289627f7eb2Smrg 	  mio_rparen (); /* component list closing.  */
5290627f7eb2Smrg 
5291627f7eb2Smrg 	  skip_list (1); /* symbol end.  */
5292627f7eb2Smrg 	}
5293627f7eb2Smrg       else
5294627f7eb2Smrg 	skip_list ();
5295627f7eb2Smrg 
5296627f7eb2Smrg       /* Some symbols do not have a namespace (eg. formal arguments),
5297627f7eb2Smrg 	 so the automatic "unique symtree" mechanism must be suppressed
5298627f7eb2Smrg 	 by marking them as referenced.  */
5299627f7eb2Smrg       q = get_integer (info->u.rsym.ns);
5300627f7eb2Smrg       if (q->u.pointer == NULL)
5301627f7eb2Smrg 	{
5302627f7eb2Smrg 	  info->u.rsym.referenced = 1;
5303627f7eb2Smrg 	  continue;
5304627f7eb2Smrg 	}
5305627f7eb2Smrg     }
5306627f7eb2Smrg 
5307627f7eb2Smrg   mio_rparen ();
5308627f7eb2Smrg 
5309627f7eb2Smrg   /* Parse the symtree lists.  This lets us mark which symbols need to
5310627f7eb2Smrg      be loaded.  Renaming is also done at this point by replacing the
5311627f7eb2Smrg      symtree name.  */
5312627f7eb2Smrg 
5313627f7eb2Smrg   mio_lparen ();
5314627f7eb2Smrg 
5315627f7eb2Smrg   while (peek_atom () != ATOM_RPAREN)
5316627f7eb2Smrg     {
5317627f7eb2Smrg       mio_internal_string (name);
5318627f7eb2Smrg       mio_integer (&ambiguous);
5319627f7eb2Smrg       mio_integer (&symbol);
5320627f7eb2Smrg 
5321627f7eb2Smrg       info = get_integer (symbol);
5322627f7eb2Smrg 
5323627f7eb2Smrg       /* See how many use names there are.  If none, go through the start
5324627f7eb2Smrg 	 of the loop at least once.  */
5325627f7eb2Smrg       nuse = number_use_names (name, false);
5326627f7eb2Smrg       info->u.rsym.renamed = nuse ? 1 : 0;
5327627f7eb2Smrg 
5328627f7eb2Smrg       if (nuse == 0)
5329627f7eb2Smrg 	nuse = 1;
5330627f7eb2Smrg 
5331627f7eb2Smrg       for (j = 1; j <= nuse; j++)
5332627f7eb2Smrg 	{
5333627f7eb2Smrg 	  /* Get the jth local name for this symbol.  */
5334627f7eb2Smrg 	  p = find_use_name_n (name, &j, false);
5335627f7eb2Smrg 
5336627f7eb2Smrg 	  if (p == NULL && strcmp (name, module_name) == 0)
5337627f7eb2Smrg 	    p = name;
5338627f7eb2Smrg 
5339627f7eb2Smrg 	  /* Exception: Always import vtabs & vtypes.  */
5340627f7eb2Smrg 	  if (p == NULL && name[0] == '_'
5341627f7eb2Smrg 	      && (gfc_str_startswith (name, "__vtab_")
5342627f7eb2Smrg 		  || gfc_str_startswith (name, "__vtype_")))
5343627f7eb2Smrg 	    p = name;
5344627f7eb2Smrg 
5345627f7eb2Smrg 	  /* Skip symtree nodes not in an ONLY clause, unless there
5346627f7eb2Smrg 	     is an existing symtree loaded from another USE statement.  */
5347627f7eb2Smrg 	  if (p == NULL)
5348627f7eb2Smrg 	    {
5349627f7eb2Smrg 	      st = gfc_find_symtree (gfc_current_ns->sym_root, name);
5350627f7eb2Smrg 	      if (st != NULL
5351627f7eb2Smrg 		  && strcmp (st->n.sym->name, info->u.rsym.true_name) == 0
5352627f7eb2Smrg 		  && st->n.sym->module != NULL
5353627f7eb2Smrg 		  && strcmp (st->n.sym->module, info->u.rsym.module) == 0)
5354627f7eb2Smrg 		{
5355627f7eb2Smrg 		  info->u.rsym.symtree = st;
5356627f7eb2Smrg 		  info->u.rsym.sym = st->n.sym;
5357627f7eb2Smrg 		}
5358627f7eb2Smrg 	      continue;
5359627f7eb2Smrg 	    }
5360627f7eb2Smrg 
5361627f7eb2Smrg 	  /* If a symbol of the same name and module exists already,
5362627f7eb2Smrg 	     this symbol, which is not in an ONLY clause, must not be
5363627f7eb2Smrg 	     added to the namespace(11.3.2).  Note that find_symbol
5364627f7eb2Smrg 	     only returns the first occurrence that it finds.  */
5365627f7eb2Smrg 	  if (!only_flag && !info->u.rsym.renamed
5366627f7eb2Smrg 		&& strcmp (name, module_name) != 0
5367627f7eb2Smrg 		&& find_symbol (gfc_current_ns->sym_root, name,
5368627f7eb2Smrg 				module_name, 0))
5369627f7eb2Smrg 	    continue;
5370627f7eb2Smrg 
5371627f7eb2Smrg 	  st = gfc_find_symtree (gfc_current_ns->sym_root, p);
5372627f7eb2Smrg 
5373627f7eb2Smrg 	  if (st != NULL
5374627f7eb2Smrg 	      && !(st->n.sym && st->n.sym->attr.used_in_submodule))
5375627f7eb2Smrg 	    {
5376627f7eb2Smrg 	      /* Check for ambiguous symbols.  */
5377627f7eb2Smrg 	      if (check_for_ambiguous (st, info))
5378627f7eb2Smrg 		st->ambiguous = 1;
5379627f7eb2Smrg 	      else
5380627f7eb2Smrg 		info->u.rsym.symtree = st;
5381627f7eb2Smrg 	    }
5382627f7eb2Smrg 	  else
5383627f7eb2Smrg 	    {
5384627f7eb2Smrg 	      if (st)
5385627f7eb2Smrg 		{
5386627f7eb2Smrg 		  /* This symbol is host associated from a module in a
5387627f7eb2Smrg 		     submodule.  Hide it with a unique symtree.  */
5388627f7eb2Smrg 		  gfc_symtree *s = gfc_get_unique_symtree (gfc_current_ns);
5389627f7eb2Smrg 		  s->n.sym = st->n.sym;
5390627f7eb2Smrg 		  st->n.sym = NULL;
5391627f7eb2Smrg 		}
5392627f7eb2Smrg 	      else
5393627f7eb2Smrg 		{
5394627f7eb2Smrg 		  /* Create a symtree node in the current namespace for this
5395627f7eb2Smrg 		     symbol.  */
5396627f7eb2Smrg 		  st = check_unique_name (p)
5397627f7eb2Smrg 		       ? gfc_get_unique_symtree (gfc_current_ns)
5398627f7eb2Smrg 		       : gfc_new_symtree (&gfc_current_ns->sym_root, p);
5399627f7eb2Smrg 		  st->ambiguous = ambiguous;
5400627f7eb2Smrg 		}
5401627f7eb2Smrg 
5402627f7eb2Smrg 	      sym = info->u.rsym.sym;
5403627f7eb2Smrg 
5404627f7eb2Smrg 	      /* Create a symbol node if it doesn't already exist.  */
5405627f7eb2Smrg 	      if (sym == NULL)
5406627f7eb2Smrg 		{
5407627f7eb2Smrg 		  info->u.rsym.sym = gfc_new_symbol (info->u.rsym.true_name,
5408627f7eb2Smrg 						     gfc_current_ns);
5409627f7eb2Smrg 		  info->u.rsym.sym->name = gfc_dt_lower_string (info->u.rsym.true_name);
5410627f7eb2Smrg 		  sym = info->u.rsym.sym;
5411627f7eb2Smrg 		  sym->module = gfc_get_string ("%s", info->u.rsym.module);
5412627f7eb2Smrg 
5413627f7eb2Smrg 		  if (info->u.rsym.binding_label)
5414627f7eb2Smrg 		    {
5415627f7eb2Smrg 		      tree id = get_identifier (info->u.rsym.binding_label);
5416627f7eb2Smrg 		      sym->binding_label = IDENTIFIER_POINTER (id);
5417627f7eb2Smrg 		    }
5418627f7eb2Smrg 		}
5419627f7eb2Smrg 
5420627f7eb2Smrg 	      st->n.sym = sym;
5421627f7eb2Smrg 	      st->n.sym->refs++;
5422627f7eb2Smrg 
5423627f7eb2Smrg 	      if (strcmp (name, p) != 0)
5424627f7eb2Smrg 		sym->attr.use_rename = 1;
5425627f7eb2Smrg 
5426627f7eb2Smrg 	      if (name[0] != '_'
5427627f7eb2Smrg 		  || (!gfc_str_startswith (name, "__vtab_")
5428627f7eb2Smrg 		      && !gfc_str_startswith (name, "__vtype_")))
5429627f7eb2Smrg 		sym->attr.use_only = only_flag;
5430627f7eb2Smrg 
5431627f7eb2Smrg 	      /* Store the symtree pointing to this symbol.  */
5432627f7eb2Smrg 	      info->u.rsym.symtree = st;
5433627f7eb2Smrg 
5434627f7eb2Smrg 	      if (info->u.rsym.state == UNUSED)
5435627f7eb2Smrg 		info->u.rsym.state = NEEDED;
5436627f7eb2Smrg 	      info->u.rsym.referenced = 1;
5437627f7eb2Smrg 	    }
5438627f7eb2Smrg 	}
5439627f7eb2Smrg     }
5440627f7eb2Smrg 
5441627f7eb2Smrg   mio_rparen ();
5442627f7eb2Smrg 
5443627f7eb2Smrg   /* Load intrinsic operator interfaces.  */
5444627f7eb2Smrg   set_module_locus (&operator_interfaces);
5445627f7eb2Smrg   mio_lparen ();
5446627f7eb2Smrg 
5447627f7eb2Smrg   for (i = GFC_INTRINSIC_BEGIN; i != GFC_INTRINSIC_END; i++)
5448627f7eb2Smrg     {
5449627f7eb2Smrg       if (i == INTRINSIC_USER)
5450627f7eb2Smrg 	continue;
5451627f7eb2Smrg 
5452627f7eb2Smrg       if (only_flag)
5453627f7eb2Smrg 	{
5454627f7eb2Smrg 	  u = find_use_operator ((gfc_intrinsic_op) i);
5455627f7eb2Smrg 
5456627f7eb2Smrg 	  if (u == NULL)
5457627f7eb2Smrg 	    {
5458627f7eb2Smrg 	      skip_list ();
5459627f7eb2Smrg 	      continue;
5460627f7eb2Smrg 	    }
5461627f7eb2Smrg 
5462627f7eb2Smrg 	  u->found = 1;
5463627f7eb2Smrg 	}
5464627f7eb2Smrg 
5465627f7eb2Smrg       mio_interface (&gfc_current_ns->op[i]);
5466627f7eb2Smrg       if (u && !gfc_current_ns->op[i])
5467627f7eb2Smrg 	u->found = 0;
5468627f7eb2Smrg     }
5469627f7eb2Smrg 
5470627f7eb2Smrg   mio_rparen ();
5471627f7eb2Smrg 
5472627f7eb2Smrg   /* Load generic and user operator interfaces.  These must follow the
5473627f7eb2Smrg      loading of symtree because otherwise symbols can be marked as
5474627f7eb2Smrg      ambiguous.  */
5475627f7eb2Smrg 
5476627f7eb2Smrg   set_module_locus (&user_operators);
5477627f7eb2Smrg 
5478627f7eb2Smrg   load_operator_interfaces ();
5479627f7eb2Smrg   load_generic_interfaces ();
5480627f7eb2Smrg 
5481627f7eb2Smrg   load_commons ();
5482627f7eb2Smrg   load_equiv ();
5483627f7eb2Smrg 
5484627f7eb2Smrg   /* Load OpenMP user defined reductions.  */
5485627f7eb2Smrg   set_module_locus (&omp_udrs);
5486627f7eb2Smrg   load_omp_udrs ();
5487627f7eb2Smrg 
5488627f7eb2Smrg   /* At this point, we read those symbols that are needed but haven't
5489627f7eb2Smrg      been loaded yet.  If one symbol requires another, the other gets
5490627f7eb2Smrg      marked as NEEDED if its previous state was UNUSED.  */
5491627f7eb2Smrg 
5492627f7eb2Smrg   while (load_needed (pi_root));
5493627f7eb2Smrg 
5494627f7eb2Smrg   /* Make sure all elements of the rename-list were found in the module.  */
5495627f7eb2Smrg 
5496627f7eb2Smrg   for (u = gfc_rename_list; u; u = u->next)
5497627f7eb2Smrg     {
5498627f7eb2Smrg       if (u->found)
5499627f7eb2Smrg 	continue;
5500627f7eb2Smrg 
5501627f7eb2Smrg       if (u->op == INTRINSIC_NONE)
5502627f7eb2Smrg 	{
5503627f7eb2Smrg 	  gfc_error ("Symbol %qs referenced at %L not found in module %qs",
5504627f7eb2Smrg 		     u->use_name, &u->where, module_name);
5505627f7eb2Smrg 	  continue;
5506627f7eb2Smrg 	}
5507627f7eb2Smrg 
5508627f7eb2Smrg       if (u->op == INTRINSIC_USER)
5509627f7eb2Smrg 	{
5510627f7eb2Smrg 	  gfc_error ("User operator %qs referenced at %L not found "
5511627f7eb2Smrg 		     "in module %qs", u->use_name, &u->where, module_name);
5512627f7eb2Smrg 	  continue;
5513627f7eb2Smrg 	}
5514627f7eb2Smrg 
5515627f7eb2Smrg       gfc_error ("Intrinsic operator %qs referenced at %L not found "
5516627f7eb2Smrg 		 "in module %qs", gfc_op2string (u->op), &u->where,
5517627f7eb2Smrg 		 module_name);
5518627f7eb2Smrg     }
5519627f7eb2Smrg 
5520627f7eb2Smrg   /* Clean up symbol nodes that were never loaded, create references
5521627f7eb2Smrg      to hidden symbols.  */
5522627f7eb2Smrg 
5523627f7eb2Smrg   read_cleanup (pi_root);
5524627f7eb2Smrg }
5525627f7eb2Smrg 
5526627f7eb2Smrg 
5527627f7eb2Smrg /* Given an access type that is specific to an entity and the default
5528627f7eb2Smrg    access, return nonzero if the entity is publicly accessible.  If the
5529627f7eb2Smrg    element is declared as PUBLIC, then it is public; if declared
5530627f7eb2Smrg    PRIVATE, then private, and otherwise it is public unless the default
5531627f7eb2Smrg    access in this context has been declared PRIVATE.  */
5532627f7eb2Smrg 
5533627f7eb2Smrg static bool dump_smod = false;
5534627f7eb2Smrg 
5535627f7eb2Smrg static bool
check_access(gfc_access specific_access,gfc_access default_access)5536627f7eb2Smrg check_access (gfc_access specific_access, gfc_access default_access)
5537627f7eb2Smrg {
5538627f7eb2Smrg   if (dump_smod)
5539627f7eb2Smrg     return true;
5540627f7eb2Smrg 
5541627f7eb2Smrg   if (specific_access == ACCESS_PUBLIC)
5542627f7eb2Smrg     return TRUE;
5543627f7eb2Smrg   if (specific_access == ACCESS_PRIVATE)
5544627f7eb2Smrg     return FALSE;
5545627f7eb2Smrg 
5546627f7eb2Smrg   if (flag_module_private)
5547627f7eb2Smrg     return default_access == ACCESS_PUBLIC;
5548627f7eb2Smrg   else
5549627f7eb2Smrg     return default_access != ACCESS_PRIVATE;
5550627f7eb2Smrg }
5551627f7eb2Smrg 
5552627f7eb2Smrg 
5553627f7eb2Smrg bool
gfc_check_symbol_access(gfc_symbol * sym)5554627f7eb2Smrg gfc_check_symbol_access (gfc_symbol *sym)
5555627f7eb2Smrg {
5556627f7eb2Smrg   if (sym->attr.vtab || sym->attr.vtype)
5557627f7eb2Smrg     return true;
5558627f7eb2Smrg   else
5559627f7eb2Smrg     return check_access (sym->attr.access, sym->ns->default_access);
5560627f7eb2Smrg }
5561627f7eb2Smrg 
5562627f7eb2Smrg 
5563627f7eb2Smrg /* A structure to remember which commons we've already written.  */
5564627f7eb2Smrg 
5565627f7eb2Smrg struct written_common
5566627f7eb2Smrg {
5567627f7eb2Smrg   BBT_HEADER(written_common);
5568627f7eb2Smrg   const char *name, *label;
5569627f7eb2Smrg };
5570627f7eb2Smrg 
5571627f7eb2Smrg static struct written_common *written_commons = NULL;
5572627f7eb2Smrg 
5573627f7eb2Smrg /* Comparison function used for balancing the binary tree.  */
5574627f7eb2Smrg 
5575627f7eb2Smrg static int
compare_written_commons(void * a1,void * b1)5576627f7eb2Smrg compare_written_commons (void *a1, void *b1)
5577627f7eb2Smrg {
5578627f7eb2Smrg   const char *aname = ((struct written_common *) a1)->name;
5579627f7eb2Smrg   const char *alabel = ((struct written_common *) a1)->label;
5580627f7eb2Smrg   const char *bname = ((struct written_common *) b1)->name;
5581627f7eb2Smrg   const char *blabel = ((struct written_common *) b1)->label;
5582627f7eb2Smrg   int c = strcmp (aname, bname);
5583627f7eb2Smrg 
5584627f7eb2Smrg   return (c != 0 ? c : strcmp (alabel, blabel));
5585627f7eb2Smrg }
5586627f7eb2Smrg 
5587627f7eb2Smrg /* Free a list of written commons.  */
5588627f7eb2Smrg 
5589627f7eb2Smrg static void
free_written_common(struct written_common * w)5590627f7eb2Smrg free_written_common (struct written_common *w)
5591627f7eb2Smrg {
5592627f7eb2Smrg   if (!w)
5593627f7eb2Smrg     return;
5594627f7eb2Smrg 
5595627f7eb2Smrg   if (w->left)
5596627f7eb2Smrg     free_written_common (w->left);
5597627f7eb2Smrg   if (w->right)
5598627f7eb2Smrg     free_written_common (w->right);
5599627f7eb2Smrg 
5600627f7eb2Smrg   free (w);
5601627f7eb2Smrg }
5602627f7eb2Smrg 
5603627f7eb2Smrg /* Write a common block to the module -- recursive helper function.  */
5604627f7eb2Smrg 
5605627f7eb2Smrg static void
write_common_0(gfc_symtree * st,bool this_module)5606627f7eb2Smrg write_common_0 (gfc_symtree *st, bool this_module)
5607627f7eb2Smrg {
5608627f7eb2Smrg   gfc_common_head *p;
5609627f7eb2Smrg   const char * name;
5610627f7eb2Smrg   int flags;
5611627f7eb2Smrg   const char *label;
5612627f7eb2Smrg   struct written_common *w;
5613627f7eb2Smrg   bool write_me = true;
5614627f7eb2Smrg 
5615627f7eb2Smrg   if (st == NULL)
5616627f7eb2Smrg     return;
5617627f7eb2Smrg 
5618627f7eb2Smrg   write_common_0 (st->left, this_module);
5619627f7eb2Smrg 
5620627f7eb2Smrg   /* We will write out the binding label, or "" if no label given.  */
5621627f7eb2Smrg   name = st->n.common->name;
5622627f7eb2Smrg   p = st->n.common;
5623627f7eb2Smrg   label = (p->is_bind_c && p->binding_label) ? p->binding_label : "";
5624627f7eb2Smrg 
5625627f7eb2Smrg   /* Check if we've already output this common.  */
5626627f7eb2Smrg   w = written_commons;
5627627f7eb2Smrg   while (w)
5628627f7eb2Smrg     {
5629627f7eb2Smrg       int c = strcmp (name, w->name);
5630627f7eb2Smrg       c = (c != 0 ? c : strcmp (label, w->label));
5631627f7eb2Smrg       if (c == 0)
5632627f7eb2Smrg 	write_me = false;
5633627f7eb2Smrg 
5634627f7eb2Smrg       w = (c < 0) ? w->left : w->right;
5635627f7eb2Smrg     }
5636627f7eb2Smrg 
5637627f7eb2Smrg   if (this_module && p->use_assoc)
5638627f7eb2Smrg     write_me = false;
5639627f7eb2Smrg 
5640627f7eb2Smrg   if (write_me)
5641627f7eb2Smrg     {
5642627f7eb2Smrg       /* Write the common to the module.  */
5643627f7eb2Smrg       mio_lparen ();
5644627f7eb2Smrg       mio_pool_string (&name);
5645627f7eb2Smrg 
5646627f7eb2Smrg       mio_symbol_ref (&p->head);
5647627f7eb2Smrg       flags = p->saved ? 1 : 0;
5648627f7eb2Smrg       if (p->threadprivate)
5649627f7eb2Smrg 	flags |= 2;
5650627f7eb2Smrg       mio_integer (&flags);
5651627f7eb2Smrg 
5652627f7eb2Smrg       /* Write out whether the common block is bind(c) or not.  */
5653627f7eb2Smrg       mio_integer (&(p->is_bind_c));
5654627f7eb2Smrg 
5655627f7eb2Smrg       mio_pool_string (&label);
5656627f7eb2Smrg       mio_rparen ();
5657627f7eb2Smrg 
5658627f7eb2Smrg       /* Record that we have written this common.  */
5659627f7eb2Smrg       w = XCNEW (struct written_common);
5660627f7eb2Smrg       w->name = p->name;
5661627f7eb2Smrg       w->label = label;
5662627f7eb2Smrg       gfc_insert_bbt (&written_commons, w, compare_written_commons);
5663627f7eb2Smrg     }
5664627f7eb2Smrg 
5665627f7eb2Smrg   write_common_0 (st->right, this_module);
5666627f7eb2Smrg }
5667627f7eb2Smrg 
5668627f7eb2Smrg 
5669627f7eb2Smrg /* Write a common, by initializing the list of written commons, calling
5670627f7eb2Smrg    the recursive function write_common_0() and cleaning up afterwards.  */
5671627f7eb2Smrg 
5672627f7eb2Smrg static void
write_common(gfc_symtree * st)5673627f7eb2Smrg write_common (gfc_symtree *st)
5674627f7eb2Smrg {
5675627f7eb2Smrg   written_commons = NULL;
5676627f7eb2Smrg   write_common_0 (st, true);
5677627f7eb2Smrg   write_common_0 (st, false);
5678627f7eb2Smrg   free_written_common (written_commons);
5679627f7eb2Smrg   written_commons = NULL;
5680627f7eb2Smrg }
5681627f7eb2Smrg 
5682627f7eb2Smrg 
5683627f7eb2Smrg /* Write the blank common block to the module.  */
5684627f7eb2Smrg 
5685627f7eb2Smrg static void
write_blank_common(void)5686627f7eb2Smrg write_blank_common (void)
5687627f7eb2Smrg {
5688627f7eb2Smrg   const char * name = BLANK_COMMON_NAME;
5689627f7eb2Smrg   int saved;
5690627f7eb2Smrg   /* TODO: Blank commons are not bind(c).  The F2003 standard probably says
5691627f7eb2Smrg      this, but it hasn't been checked.  Just making it so for now.  */
5692627f7eb2Smrg   int is_bind_c = 0;
5693627f7eb2Smrg 
5694627f7eb2Smrg   if (gfc_current_ns->blank_common.head == NULL)
5695627f7eb2Smrg     return;
5696627f7eb2Smrg 
5697627f7eb2Smrg   mio_lparen ();
5698627f7eb2Smrg 
5699627f7eb2Smrg   mio_pool_string (&name);
5700627f7eb2Smrg 
5701627f7eb2Smrg   mio_symbol_ref (&gfc_current_ns->blank_common.head);
5702627f7eb2Smrg   saved = gfc_current_ns->blank_common.saved;
5703627f7eb2Smrg   mio_integer (&saved);
5704627f7eb2Smrg 
5705627f7eb2Smrg   /* Write out whether the common block is bind(c) or not.  */
5706627f7eb2Smrg   mio_integer (&is_bind_c);
5707627f7eb2Smrg 
5708627f7eb2Smrg   /* Write out an empty binding label.  */
5709627f7eb2Smrg   write_atom (ATOM_STRING, "");
5710627f7eb2Smrg 
5711627f7eb2Smrg   mio_rparen ();
5712627f7eb2Smrg }
5713627f7eb2Smrg 
5714627f7eb2Smrg 
5715627f7eb2Smrg /* Write equivalences to the module.  */
5716627f7eb2Smrg 
5717627f7eb2Smrg static void
write_equiv(void)5718627f7eb2Smrg write_equiv (void)
5719627f7eb2Smrg {
5720627f7eb2Smrg   gfc_equiv *eq, *e;
5721627f7eb2Smrg   int num;
5722627f7eb2Smrg 
5723627f7eb2Smrg   num = 0;
5724627f7eb2Smrg   for (eq = gfc_current_ns->equiv; eq; eq = eq->next)
5725627f7eb2Smrg     {
5726627f7eb2Smrg       mio_lparen ();
5727627f7eb2Smrg 
5728627f7eb2Smrg       for (e = eq; e; e = e->eq)
5729627f7eb2Smrg 	{
5730627f7eb2Smrg 	  if (e->module == NULL)
5731627f7eb2Smrg 	    e->module = gfc_get_string ("%s.eq.%d", module_name, num);
5732627f7eb2Smrg 	  mio_allocated_string (e->module);
5733627f7eb2Smrg 	  mio_expr (&e->expr);
5734627f7eb2Smrg 	}
5735627f7eb2Smrg 
5736627f7eb2Smrg       num++;
5737627f7eb2Smrg       mio_rparen ();
5738627f7eb2Smrg     }
5739627f7eb2Smrg }
5740627f7eb2Smrg 
5741627f7eb2Smrg 
5742627f7eb2Smrg /* Write a symbol to the module.  */
5743627f7eb2Smrg 
5744627f7eb2Smrg static void
write_symbol(int n,gfc_symbol * sym)5745627f7eb2Smrg write_symbol (int n, gfc_symbol *sym)
5746627f7eb2Smrg {
5747627f7eb2Smrg   const char *label;
5748627f7eb2Smrg 
5749627f7eb2Smrg   if (sym->attr.flavor == FL_UNKNOWN || sym->attr.flavor == FL_LABEL)
5750627f7eb2Smrg     gfc_internal_error ("write_symbol(): bad module symbol %qs", sym->name);
5751627f7eb2Smrg 
5752627f7eb2Smrg   mio_integer (&n);
5753627f7eb2Smrg 
5754627f7eb2Smrg   if (gfc_fl_struct (sym->attr.flavor))
5755627f7eb2Smrg     {
5756627f7eb2Smrg       const char *name;
5757627f7eb2Smrg       name = gfc_dt_upper_string (sym->name);
5758627f7eb2Smrg       mio_pool_string (&name);
5759627f7eb2Smrg     }
5760627f7eb2Smrg   else
5761627f7eb2Smrg     mio_pool_string (&sym->name);
5762627f7eb2Smrg 
5763627f7eb2Smrg   mio_pool_string (&sym->module);
5764627f7eb2Smrg   if ((sym->attr.is_bind_c || sym->attr.is_iso_c) && sym->binding_label)
5765627f7eb2Smrg     {
5766627f7eb2Smrg       label = sym->binding_label;
5767627f7eb2Smrg       mio_pool_string (&label);
5768627f7eb2Smrg     }
5769627f7eb2Smrg   else
5770627f7eb2Smrg     write_atom (ATOM_STRING, "");
5771627f7eb2Smrg 
5772627f7eb2Smrg   mio_pointer_ref (&sym->ns);
5773627f7eb2Smrg 
5774627f7eb2Smrg   mio_symbol (sym);
5775627f7eb2Smrg   write_char ('\n');
5776627f7eb2Smrg }
5777627f7eb2Smrg 
5778627f7eb2Smrg 
5779627f7eb2Smrg /* Recursive traversal function to write the initial set of symbols to
5780627f7eb2Smrg    the module.  We check to see if the symbol should be written
5781627f7eb2Smrg    according to the access specification.  */
5782627f7eb2Smrg 
5783627f7eb2Smrg static void
write_symbol0(gfc_symtree * st)5784627f7eb2Smrg write_symbol0 (gfc_symtree *st)
5785627f7eb2Smrg {
5786627f7eb2Smrg   gfc_symbol *sym;
5787627f7eb2Smrg   pointer_info *p;
5788627f7eb2Smrg   bool dont_write = false;
5789627f7eb2Smrg 
5790627f7eb2Smrg   if (st == NULL)
5791627f7eb2Smrg     return;
5792627f7eb2Smrg 
5793627f7eb2Smrg   write_symbol0 (st->left);
5794627f7eb2Smrg 
5795627f7eb2Smrg   sym = st->n.sym;
5796627f7eb2Smrg   if (sym->module == NULL)
5797627f7eb2Smrg     sym->module = module_name;
5798627f7eb2Smrg 
5799627f7eb2Smrg   if (sym->attr.flavor == FL_PROCEDURE && sym->attr.generic
5800627f7eb2Smrg       && !sym->attr.subroutine && !sym->attr.function)
5801627f7eb2Smrg     dont_write = true;
5802627f7eb2Smrg 
5803627f7eb2Smrg   if (!gfc_check_symbol_access (sym))
5804627f7eb2Smrg     dont_write = true;
5805627f7eb2Smrg 
5806627f7eb2Smrg   if (!dont_write)
5807627f7eb2Smrg     {
5808627f7eb2Smrg       p = get_pointer (sym);
5809627f7eb2Smrg       if (p->type == P_UNKNOWN)
5810627f7eb2Smrg 	p->type = P_SYMBOL;
5811627f7eb2Smrg 
5812627f7eb2Smrg       if (p->u.wsym.state != WRITTEN)
5813627f7eb2Smrg 	{
5814627f7eb2Smrg 	  write_symbol (p->integer, sym);
5815627f7eb2Smrg 	  p->u.wsym.state = WRITTEN;
5816627f7eb2Smrg 	}
5817627f7eb2Smrg     }
5818627f7eb2Smrg 
5819627f7eb2Smrg   write_symbol0 (st->right);
5820627f7eb2Smrg }
5821627f7eb2Smrg 
5822627f7eb2Smrg 
5823627f7eb2Smrg static void
write_omp_udr(gfc_omp_udr * udr)5824627f7eb2Smrg write_omp_udr (gfc_omp_udr *udr)
5825627f7eb2Smrg {
5826627f7eb2Smrg   switch (udr->rop)
5827627f7eb2Smrg     {
5828627f7eb2Smrg     case OMP_REDUCTION_USER:
5829627f7eb2Smrg       /* Non-operators can't be used outside of the module.  */
5830627f7eb2Smrg       if (udr->name[0] != '.')
5831627f7eb2Smrg 	return;
5832627f7eb2Smrg       else
5833627f7eb2Smrg 	{
5834627f7eb2Smrg 	  gfc_symtree *st;
5835627f7eb2Smrg 	  size_t len = strlen (udr->name + 1);
5836627f7eb2Smrg 	  char *name = XALLOCAVEC (char, len);
5837627f7eb2Smrg 	  memcpy (name, udr->name, len - 1);
5838627f7eb2Smrg 	  name[len - 1] = '\0';
5839627f7eb2Smrg 	  st = gfc_find_symtree (gfc_current_ns->uop_root, name);
5840627f7eb2Smrg 	  /* If corresponding user operator is private, don't write
5841627f7eb2Smrg 	     the UDR.  */
5842627f7eb2Smrg 	  if (st != NULL)
5843627f7eb2Smrg 	    {
5844627f7eb2Smrg 	      gfc_user_op *uop = st->n.uop;
5845627f7eb2Smrg 	      if (!check_access (uop->access, uop->ns->default_access))
5846627f7eb2Smrg 		return;
5847627f7eb2Smrg 	    }
5848627f7eb2Smrg 	}
5849627f7eb2Smrg       break;
5850627f7eb2Smrg     case OMP_REDUCTION_PLUS:
5851627f7eb2Smrg     case OMP_REDUCTION_MINUS:
5852627f7eb2Smrg     case OMP_REDUCTION_TIMES:
5853627f7eb2Smrg     case OMP_REDUCTION_AND:
5854627f7eb2Smrg     case OMP_REDUCTION_OR:
5855627f7eb2Smrg     case OMP_REDUCTION_EQV:
5856627f7eb2Smrg     case OMP_REDUCTION_NEQV:
5857627f7eb2Smrg       /* If corresponding operator is private, don't write the UDR.  */
5858627f7eb2Smrg       if (!check_access (gfc_current_ns->operator_access[udr->rop],
5859627f7eb2Smrg 			 gfc_current_ns->default_access))
5860627f7eb2Smrg 	return;
5861627f7eb2Smrg       break;
5862627f7eb2Smrg     default:
5863627f7eb2Smrg       break;
5864627f7eb2Smrg     }
5865627f7eb2Smrg   if (udr->ts.type == BT_DERIVED || udr->ts.type == BT_CLASS)
5866627f7eb2Smrg     {
5867627f7eb2Smrg       /* If derived type is private, don't write the UDR.  */
5868627f7eb2Smrg       if (!gfc_check_symbol_access (udr->ts.u.derived))
5869627f7eb2Smrg 	return;
5870627f7eb2Smrg     }
5871627f7eb2Smrg 
5872627f7eb2Smrg   mio_lparen ();
5873627f7eb2Smrg   mio_pool_string (&udr->name);
5874627f7eb2Smrg   mio_typespec (&udr->ts);
5875627f7eb2Smrg   mio_omp_udr_expr (udr, &udr->omp_out, &udr->omp_in, udr->combiner_ns, false);
5876627f7eb2Smrg   if (udr->initializer_ns)
5877627f7eb2Smrg     mio_omp_udr_expr (udr, &udr->omp_priv, &udr->omp_orig,
5878627f7eb2Smrg 		      udr->initializer_ns, true);
5879627f7eb2Smrg   mio_rparen ();
5880627f7eb2Smrg }
5881627f7eb2Smrg 
5882627f7eb2Smrg 
5883627f7eb2Smrg static void
write_omp_udrs(gfc_symtree * st)5884627f7eb2Smrg write_omp_udrs (gfc_symtree *st)
5885627f7eb2Smrg {
5886627f7eb2Smrg   if (st == NULL)
5887627f7eb2Smrg     return;
5888627f7eb2Smrg 
5889627f7eb2Smrg   write_omp_udrs (st->left);
5890627f7eb2Smrg   gfc_omp_udr *udr;
5891627f7eb2Smrg   for (udr = st->n.omp_udr; udr; udr = udr->next)
5892627f7eb2Smrg     write_omp_udr (udr);
5893627f7eb2Smrg   write_omp_udrs (st->right);
5894627f7eb2Smrg }
5895627f7eb2Smrg 
5896627f7eb2Smrg 
5897627f7eb2Smrg /* Type for the temporary tree used when writing secondary symbols.  */
5898627f7eb2Smrg 
5899627f7eb2Smrg struct sorted_pointer_info
5900627f7eb2Smrg {
5901627f7eb2Smrg   BBT_HEADER (sorted_pointer_info);
5902627f7eb2Smrg 
5903627f7eb2Smrg   pointer_info *p;
5904627f7eb2Smrg };
5905627f7eb2Smrg 
5906627f7eb2Smrg #define gfc_get_sorted_pointer_info() XCNEW (sorted_pointer_info)
5907627f7eb2Smrg 
5908627f7eb2Smrg /* Recursively traverse the temporary tree, free its contents.  */
5909627f7eb2Smrg 
5910627f7eb2Smrg static void
free_sorted_pointer_info_tree(sorted_pointer_info * p)5911627f7eb2Smrg free_sorted_pointer_info_tree (sorted_pointer_info *p)
5912627f7eb2Smrg {
5913627f7eb2Smrg   if (!p)
5914627f7eb2Smrg     return;
5915627f7eb2Smrg 
5916627f7eb2Smrg   free_sorted_pointer_info_tree (p->left);
5917627f7eb2Smrg   free_sorted_pointer_info_tree (p->right);
5918627f7eb2Smrg 
5919627f7eb2Smrg   free (p);
5920627f7eb2Smrg }
5921627f7eb2Smrg 
5922627f7eb2Smrg /* Comparison function for the temporary tree.  */
5923627f7eb2Smrg 
5924627f7eb2Smrg static int
compare_sorted_pointer_info(void * _spi1,void * _spi2)5925627f7eb2Smrg compare_sorted_pointer_info (void *_spi1, void *_spi2)
5926627f7eb2Smrg {
5927627f7eb2Smrg   sorted_pointer_info *spi1, *spi2;
5928627f7eb2Smrg   spi1 = (sorted_pointer_info *)_spi1;
5929627f7eb2Smrg   spi2 = (sorted_pointer_info *)_spi2;
5930627f7eb2Smrg 
5931627f7eb2Smrg   if (spi1->p->integer < spi2->p->integer)
5932627f7eb2Smrg     return -1;
5933627f7eb2Smrg   if (spi1->p->integer > spi2->p->integer)
5934627f7eb2Smrg     return 1;
5935627f7eb2Smrg   return 0;
5936627f7eb2Smrg }
5937627f7eb2Smrg 
5938627f7eb2Smrg 
5939627f7eb2Smrg /* Finds the symbols that need to be written and collects them in the
5940627f7eb2Smrg    sorted_pi tree so that they can be traversed in an order
5941627f7eb2Smrg    independent of memory addresses.  */
5942627f7eb2Smrg 
5943627f7eb2Smrg static void
find_symbols_to_write(sorted_pointer_info ** tree,pointer_info * p)5944627f7eb2Smrg find_symbols_to_write(sorted_pointer_info **tree, pointer_info *p)
5945627f7eb2Smrg {
5946627f7eb2Smrg   if (!p)
5947627f7eb2Smrg     return;
5948627f7eb2Smrg 
5949627f7eb2Smrg   if (p->type == P_SYMBOL && p->u.wsym.state == NEEDS_WRITE)
5950627f7eb2Smrg     {
5951627f7eb2Smrg       sorted_pointer_info *sp = gfc_get_sorted_pointer_info();
5952627f7eb2Smrg       sp->p = p;
5953627f7eb2Smrg 
5954627f7eb2Smrg       gfc_insert_bbt (tree, sp, compare_sorted_pointer_info);
5955627f7eb2Smrg    }
5956627f7eb2Smrg 
5957627f7eb2Smrg   find_symbols_to_write (tree, p->left);
5958627f7eb2Smrg   find_symbols_to_write (tree, p->right);
5959627f7eb2Smrg }
5960627f7eb2Smrg 
5961627f7eb2Smrg 
5962627f7eb2Smrg /* Recursive function that traverses the tree of symbols that need to be
5963627f7eb2Smrg    written and writes them in order.  */
5964627f7eb2Smrg 
5965627f7eb2Smrg static void
write_symbol1_recursion(sorted_pointer_info * sp)5966627f7eb2Smrg write_symbol1_recursion (sorted_pointer_info *sp)
5967627f7eb2Smrg {
5968627f7eb2Smrg   if (!sp)
5969627f7eb2Smrg     return;
5970627f7eb2Smrg 
5971627f7eb2Smrg   write_symbol1_recursion (sp->left);
5972627f7eb2Smrg 
5973627f7eb2Smrg   pointer_info *p1 = sp->p;
5974627f7eb2Smrg   gcc_assert (p1->type == P_SYMBOL && p1->u.wsym.state == NEEDS_WRITE);
5975627f7eb2Smrg 
5976627f7eb2Smrg   p1->u.wsym.state = WRITTEN;
5977627f7eb2Smrg   write_symbol (p1->integer, p1->u.wsym.sym);
5978627f7eb2Smrg   p1->u.wsym.sym->attr.public_used = 1;
5979627f7eb2Smrg 
5980627f7eb2Smrg   write_symbol1_recursion (sp->right);
5981627f7eb2Smrg }
5982627f7eb2Smrg 
5983627f7eb2Smrg 
5984627f7eb2Smrg /* Write the secondary set of symbols to the module file.  These are
5985627f7eb2Smrg    symbols that were not public yet are needed by the public symbols
5986627f7eb2Smrg    or another dependent symbol.  The act of writing a symbol can add
5987627f7eb2Smrg    symbols to the pointer_info tree, so we return nonzero if a symbol
5988627f7eb2Smrg    was written and pass that information upwards.  The caller will
5989627f7eb2Smrg    then call this function again until nothing was written.  It uses
5990627f7eb2Smrg    the utility functions and a temporary tree to ensure a reproducible
5991627f7eb2Smrg    ordering of the symbol output and thus the module file.  */
5992627f7eb2Smrg 
5993627f7eb2Smrg static int
write_symbol1(pointer_info * p)5994627f7eb2Smrg write_symbol1 (pointer_info *p)
5995627f7eb2Smrg {
5996627f7eb2Smrg   if (!p)
5997627f7eb2Smrg     return 0;
5998627f7eb2Smrg 
5999627f7eb2Smrg   /* Put symbols that need to be written into a tree sorted on the
6000627f7eb2Smrg      integer field.  */
6001627f7eb2Smrg 
6002627f7eb2Smrg   sorted_pointer_info *spi_root = NULL;
6003627f7eb2Smrg   find_symbols_to_write (&spi_root, p);
6004627f7eb2Smrg 
6005627f7eb2Smrg   /* No symbols to write, return.  */
6006627f7eb2Smrg   if (!spi_root)
6007627f7eb2Smrg     return 0;
6008627f7eb2Smrg 
6009627f7eb2Smrg   /* Otherwise, write and free the tree again.  */
6010627f7eb2Smrg   write_symbol1_recursion (spi_root);
6011627f7eb2Smrg   free_sorted_pointer_info_tree (spi_root);
6012627f7eb2Smrg 
6013627f7eb2Smrg   return 1;
6014627f7eb2Smrg }
6015627f7eb2Smrg 
6016627f7eb2Smrg 
6017627f7eb2Smrg /* Write operator interfaces associated with a symbol.  */
6018627f7eb2Smrg 
6019627f7eb2Smrg static void
write_operator(gfc_user_op * uop)6020627f7eb2Smrg write_operator (gfc_user_op *uop)
6021627f7eb2Smrg {
6022627f7eb2Smrg   static char nullstring[] = "";
6023627f7eb2Smrg   const char *p = nullstring;
6024627f7eb2Smrg 
6025627f7eb2Smrg   if (uop->op == NULL || !check_access (uop->access, uop->ns->default_access))
6026627f7eb2Smrg     return;
6027627f7eb2Smrg 
6028627f7eb2Smrg   mio_symbol_interface (&uop->name, &p, &uop->op);
6029627f7eb2Smrg }
6030627f7eb2Smrg 
6031627f7eb2Smrg 
6032627f7eb2Smrg /* Write generic interfaces from the namespace sym_root.  */
6033627f7eb2Smrg 
6034627f7eb2Smrg static void
write_generic(gfc_symtree * st)6035627f7eb2Smrg write_generic (gfc_symtree *st)
6036627f7eb2Smrg {
6037627f7eb2Smrg   gfc_symbol *sym;
6038627f7eb2Smrg 
6039627f7eb2Smrg   if (st == NULL)
6040627f7eb2Smrg     return;
6041627f7eb2Smrg 
6042627f7eb2Smrg   write_generic (st->left);
6043627f7eb2Smrg 
6044627f7eb2Smrg   sym = st->n.sym;
6045627f7eb2Smrg   if (sym && !check_unique_name (st->name)
6046627f7eb2Smrg       && sym->generic && gfc_check_symbol_access (sym))
6047627f7eb2Smrg     {
6048627f7eb2Smrg       if (!sym->module)
6049627f7eb2Smrg 	sym->module = module_name;
6050627f7eb2Smrg 
6051627f7eb2Smrg       mio_symbol_interface (&st->name, &sym->module, &sym->generic);
6052627f7eb2Smrg     }
6053627f7eb2Smrg 
6054627f7eb2Smrg   write_generic (st->right);
6055627f7eb2Smrg }
6056627f7eb2Smrg 
6057627f7eb2Smrg 
6058627f7eb2Smrg static void
write_symtree(gfc_symtree * st)6059627f7eb2Smrg write_symtree (gfc_symtree *st)
6060627f7eb2Smrg {
6061627f7eb2Smrg   gfc_symbol *sym;
6062627f7eb2Smrg   pointer_info *p;
6063627f7eb2Smrg 
6064627f7eb2Smrg   sym = st->n.sym;
6065627f7eb2Smrg 
6066627f7eb2Smrg   /* A symbol in an interface body must not be visible in the
6067627f7eb2Smrg      module file.  */
6068627f7eb2Smrg   if (sym->ns != gfc_current_ns
6069627f7eb2Smrg 	&& sym->ns->proc_name
6070627f7eb2Smrg 	&& sym->ns->proc_name->attr.if_source == IFSRC_IFBODY)
6071627f7eb2Smrg     return;
6072627f7eb2Smrg 
6073627f7eb2Smrg   if (!gfc_check_symbol_access (sym)
6074627f7eb2Smrg       || (sym->attr.flavor == FL_PROCEDURE && sym->attr.generic
6075627f7eb2Smrg 	  && !sym->attr.subroutine && !sym->attr.function))
6076627f7eb2Smrg     return;
6077627f7eb2Smrg 
6078627f7eb2Smrg   if (check_unique_name (st->name))
6079627f7eb2Smrg     return;
6080627f7eb2Smrg 
6081*4c3eb207Smrg   /* From F2003 onwards, intrinsic procedures are no longer subject to
6082*4c3eb207Smrg      the restriction, "that an elemental intrinsic function here be of
6083*4c3eb207Smrg      type integer or character and each argument must be an initialization
6084*4c3eb207Smrg      expr of type integer or character" is lifted so that intrinsic
6085*4c3eb207Smrg      procedures can be over-ridden. This requires that the intrinsic
6086*4c3eb207Smrg      symbol not appear in the module file, thereby preventing ambiguity
6087*4c3eb207Smrg      when USEd.  */
6088*4c3eb207Smrg   if (strcmp (sym->module, "(intrinsic)") == 0
6089*4c3eb207Smrg       && (gfc_option.allow_std & GFC_STD_F2003))
6090*4c3eb207Smrg     return;
6091*4c3eb207Smrg 
6092627f7eb2Smrg   p = find_pointer (sym);
6093627f7eb2Smrg   if (p == NULL)
6094627f7eb2Smrg     gfc_internal_error ("write_symtree(): Symbol not written");
6095627f7eb2Smrg 
6096627f7eb2Smrg   mio_pool_string (&st->name);
6097627f7eb2Smrg   mio_integer (&st->ambiguous);
6098627f7eb2Smrg   mio_hwi (&p->integer);
6099627f7eb2Smrg }
6100627f7eb2Smrg 
6101627f7eb2Smrg 
6102627f7eb2Smrg static void
write_module(void)6103627f7eb2Smrg write_module (void)
6104627f7eb2Smrg {
6105627f7eb2Smrg   int i;
6106627f7eb2Smrg 
6107*4c3eb207Smrg   /* Initialize the column counter. */
6108*4c3eb207Smrg   module_column = 1;
6109*4c3eb207Smrg 
6110627f7eb2Smrg   /* Write the operator interfaces.  */
6111627f7eb2Smrg   mio_lparen ();
6112627f7eb2Smrg 
6113627f7eb2Smrg   for (i = GFC_INTRINSIC_BEGIN; i != GFC_INTRINSIC_END; i++)
6114627f7eb2Smrg     {
6115627f7eb2Smrg       if (i == INTRINSIC_USER)
6116627f7eb2Smrg 	continue;
6117627f7eb2Smrg 
6118627f7eb2Smrg       mio_interface (check_access (gfc_current_ns->operator_access[i],
6119627f7eb2Smrg 				   gfc_current_ns->default_access)
6120627f7eb2Smrg 		     ? &gfc_current_ns->op[i] : NULL);
6121627f7eb2Smrg     }
6122627f7eb2Smrg 
6123627f7eb2Smrg   mio_rparen ();
6124627f7eb2Smrg   write_char ('\n');
6125627f7eb2Smrg   write_char ('\n');
6126627f7eb2Smrg 
6127627f7eb2Smrg   mio_lparen ();
6128627f7eb2Smrg   gfc_traverse_user_op (gfc_current_ns, write_operator);
6129627f7eb2Smrg   mio_rparen ();
6130627f7eb2Smrg   write_char ('\n');
6131627f7eb2Smrg   write_char ('\n');
6132627f7eb2Smrg 
6133627f7eb2Smrg   mio_lparen ();
6134627f7eb2Smrg   write_generic (gfc_current_ns->sym_root);
6135627f7eb2Smrg   mio_rparen ();
6136627f7eb2Smrg   write_char ('\n');
6137627f7eb2Smrg   write_char ('\n');
6138627f7eb2Smrg 
6139627f7eb2Smrg   mio_lparen ();
6140627f7eb2Smrg   write_blank_common ();
6141627f7eb2Smrg   write_common (gfc_current_ns->common_root);
6142627f7eb2Smrg   mio_rparen ();
6143627f7eb2Smrg   write_char ('\n');
6144627f7eb2Smrg   write_char ('\n');
6145627f7eb2Smrg 
6146627f7eb2Smrg   mio_lparen ();
6147627f7eb2Smrg   write_equiv ();
6148627f7eb2Smrg   mio_rparen ();
6149627f7eb2Smrg   write_char ('\n');
6150627f7eb2Smrg   write_char ('\n');
6151627f7eb2Smrg 
6152627f7eb2Smrg   mio_lparen ();
6153627f7eb2Smrg   write_omp_udrs (gfc_current_ns->omp_udr_root);
6154627f7eb2Smrg   mio_rparen ();
6155627f7eb2Smrg   write_char ('\n');
6156627f7eb2Smrg   write_char ('\n');
6157627f7eb2Smrg 
6158627f7eb2Smrg   /* Write symbol information.  First we traverse all symbols in the
6159627f7eb2Smrg      primary namespace, writing those that need to be written.
6160627f7eb2Smrg      Sometimes writing one symbol will cause another to need to be
6161627f7eb2Smrg      written.  A list of these symbols ends up on the write stack, and
6162627f7eb2Smrg      we end by popping the bottom of the stack and writing the symbol
6163627f7eb2Smrg      until the stack is empty.  */
6164627f7eb2Smrg 
6165627f7eb2Smrg   mio_lparen ();
6166627f7eb2Smrg 
6167627f7eb2Smrg   write_symbol0 (gfc_current_ns->sym_root);
6168627f7eb2Smrg   while (write_symbol1 (pi_root))
6169627f7eb2Smrg     /* Nothing.  */;
6170627f7eb2Smrg 
6171627f7eb2Smrg   mio_rparen ();
6172627f7eb2Smrg 
6173627f7eb2Smrg   write_char ('\n');
6174627f7eb2Smrg   write_char ('\n');
6175627f7eb2Smrg 
6176627f7eb2Smrg   mio_lparen ();
6177627f7eb2Smrg   gfc_traverse_symtree (gfc_current_ns->sym_root, write_symtree);
6178627f7eb2Smrg   mio_rparen ();
6179627f7eb2Smrg }
6180627f7eb2Smrg 
6181627f7eb2Smrg 
6182627f7eb2Smrg /* Read a CRC32 sum from the gzip trailer of a module file.  Returns
6183627f7eb2Smrg    true on success, false on failure.  */
6184627f7eb2Smrg 
6185627f7eb2Smrg static bool
read_crc32_from_module_file(const char * filename,uLong * crc)6186627f7eb2Smrg read_crc32_from_module_file (const char* filename, uLong* crc)
6187627f7eb2Smrg {
6188627f7eb2Smrg   FILE *file;
6189627f7eb2Smrg   char buf[4];
6190627f7eb2Smrg   unsigned int val;
6191627f7eb2Smrg 
6192627f7eb2Smrg   /* Open the file in binary mode.  */
6193627f7eb2Smrg   if ((file = fopen (filename, "rb")) == NULL)
6194627f7eb2Smrg     return false;
6195627f7eb2Smrg 
6196627f7eb2Smrg   /* The gzip crc32 value is found in the [END-8, END-4] bytes of the
6197627f7eb2Smrg      file. See RFC 1952.  */
6198627f7eb2Smrg   if (fseek (file, -8, SEEK_END) != 0)
6199627f7eb2Smrg     {
6200627f7eb2Smrg       fclose (file);
6201627f7eb2Smrg       return false;
6202627f7eb2Smrg     }
6203627f7eb2Smrg 
6204627f7eb2Smrg   /* Read the CRC32.  */
6205627f7eb2Smrg   if (fread (buf, 1, 4, file) != 4)
6206627f7eb2Smrg     {
6207627f7eb2Smrg       fclose (file);
6208627f7eb2Smrg       return false;
6209627f7eb2Smrg     }
6210627f7eb2Smrg 
6211627f7eb2Smrg   /* Close the file.  */
6212627f7eb2Smrg   fclose (file);
6213627f7eb2Smrg 
6214627f7eb2Smrg   val = (buf[0] & 0xFF) + ((buf[1] & 0xFF) << 8) + ((buf[2] & 0xFF) << 16)
6215627f7eb2Smrg     + ((buf[3] & 0xFF) << 24);
6216627f7eb2Smrg   *crc = val;
6217627f7eb2Smrg 
6218627f7eb2Smrg   /* For debugging, the CRC value printed in hexadecimal should match
6219627f7eb2Smrg      the CRC printed by "zcat -l -v filename".
6220627f7eb2Smrg      printf("CRC of file %s is %x\n", filename, val); */
6221627f7eb2Smrg 
6222627f7eb2Smrg   return true;
6223627f7eb2Smrg }
6224627f7eb2Smrg 
6225627f7eb2Smrg 
6226627f7eb2Smrg /* Given module, dump it to disk.  If there was an error while
6227627f7eb2Smrg    processing the module, dump_flag will be set to zero and we delete
6228627f7eb2Smrg    the module file, even if it was already there.  */
6229627f7eb2Smrg 
6230627f7eb2Smrg static void
dump_module(const char * name,int dump_flag)6231627f7eb2Smrg dump_module (const char *name, int dump_flag)
6232627f7eb2Smrg {
6233627f7eb2Smrg   int n;
6234627f7eb2Smrg   char *filename, *filename_tmp;
6235627f7eb2Smrg   uLong crc, crc_old;
6236627f7eb2Smrg 
6237627f7eb2Smrg   module_name = gfc_get_string ("%s", name);
6238627f7eb2Smrg 
6239627f7eb2Smrg   if (dump_smod)
6240627f7eb2Smrg     {
6241627f7eb2Smrg       name = submodule_name;
6242627f7eb2Smrg       n = strlen (name) + strlen (SUBMODULE_EXTENSION) + 1;
6243627f7eb2Smrg     }
6244627f7eb2Smrg   else
6245627f7eb2Smrg     n = strlen (name) + strlen (MODULE_EXTENSION) + 1;
6246627f7eb2Smrg 
6247627f7eb2Smrg   if (gfc_option.module_dir != NULL)
6248627f7eb2Smrg     {
6249627f7eb2Smrg       n += strlen (gfc_option.module_dir);
6250627f7eb2Smrg       filename = (char *) alloca (n);
6251627f7eb2Smrg       strcpy (filename, gfc_option.module_dir);
6252627f7eb2Smrg       strcat (filename, name);
6253627f7eb2Smrg     }
6254627f7eb2Smrg   else
6255627f7eb2Smrg     {
6256627f7eb2Smrg       filename = (char *) alloca (n);
6257627f7eb2Smrg       strcpy (filename, name);
6258627f7eb2Smrg     }
6259627f7eb2Smrg 
6260627f7eb2Smrg   if (dump_smod)
6261627f7eb2Smrg     strcat (filename, SUBMODULE_EXTENSION);
6262627f7eb2Smrg   else
6263627f7eb2Smrg   strcat (filename, MODULE_EXTENSION);
6264627f7eb2Smrg 
6265627f7eb2Smrg   /* Name of the temporary file used to write the module.  */
6266627f7eb2Smrg   filename_tmp = (char *) alloca (n + 1);
6267627f7eb2Smrg   strcpy (filename_tmp, filename);
6268627f7eb2Smrg   strcat (filename_tmp, "0");
6269627f7eb2Smrg 
6270627f7eb2Smrg   /* There was an error while processing the module.  We delete the
6271627f7eb2Smrg      module file, even if it was already there.  */
6272627f7eb2Smrg   if (!dump_flag)
6273627f7eb2Smrg     {
6274627f7eb2Smrg       remove (filename);
6275627f7eb2Smrg       return;
6276627f7eb2Smrg     }
6277627f7eb2Smrg 
6278627f7eb2Smrg   if (gfc_cpp_makedep ())
6279627f7eb2Smrg     gfc_cpp_add_target (filename);
6280627f7eb2Smrg 
6281627f7eb2Smrg   /* Write the module to the temporary file.  */
6282627f7eb2Smrg   module_fp = gzopen (filename_tmp, "w");
6283627f7eb2Smrg   if (module_fp == NULL)
6284627f7eb2Smrg     gfc_fatal_error ("Cannot open module file %qs for writing at %C: %s",
6285627f7eb2Smrg 		     filename_tmp, xstrerror (errno));
6286627f7eb2Smrg 
6287627f7eb2Smrg   /* Use lbasename to ensure module files are reproducible regardless
6288627f7eb2Smrg      of the build path (see the reproducible builds project).  */
6289627f7eb2Smrg   gzprintf (module_fp, "GFORTRAN module version '%s' created from %s\n",
6290627f7eb2Smrg 	    MOD_VERSION, lbasename (gfc_source_file));
6291627f7eb2Smrg 
6292627f7eb2Smrg   /* Write the module itself.  */
6293627f7eb2Smrg   iomode = IO_OUTPUT;
6294627f7eb2Smrg 
6295627f7eb2Smrg   init_pi_tree ();
6296627f7eb2Smrg 
6297627f7eb2Smrg   write_module ();
6298627f7eb2Smrg 
6299627f7eb2Smrg   free_pi_tree (pi_root);
6300627f7eb2Smrg   pi_root = NULL;
6301627f7eb2Smrg 
6302627f7eb2Smrg   write_char ('\n');
6303627f7eb2Smrg 
6304627f7eb2Smrg   if (gzclose (module_fp))
6305627f7eb2Smrg     gfc_fatal_error ("Error writing module file %qs for writing: %s",
6306627f7eb2Smrg 		     filename_tmp, xstrerror (errno));
6307627f7eb2Smrg 
6308627f7eb2Smrg   /* Read the CRC32 from the gzip trailers of the module files and
6309627f7eb2Smrg      compare.  */
6310627f7eb2Smrg   if (!read_crc32_from_module_file (filename_tmp, &crc)
6311627f7eb2Smrg       || !read_crc32_from_module_file (filename, &crc_old)
6312627f7eb2Smrg       || crc_old != crc)
6313627f7eb2Smrg     {
6314627f7eb2Smrg       /* Module file have changed, replace the old one.  */
6315627f7eb2Smrg       if (remove (filename) && errno != ENOENT)
6316627f7eb2Smrg 	gfc_fatal_error ("Cannot delete module file %qs: %s", filename,
6317627f7eb2Smrg 			 xstrerror (errno));
6318627f7eb2Smrg       if (rename (filename_tmp, filename))
6319627f7eb2Smrg 	gfc_fatal_error ("Cannot rename module file %qs to %qs: %s",
6320627f7eb2Smrg 			 filename_tmp, filename, xstrerror (errno));
6321627f7eb2Smrg     }
6322627f7eb2Smrg   else
6323627f7eb2Smrg     {
6324627f7eb2Smrg       if (remove (filename_tmp))
6325627f7eb2Smrg 	gfc_fatal_error ("Cannot delete temporary module file %qs: %s",
6326627f7eb2Smrg 			 filename_tmp, xstrerror (errno));
6327627f7eb2Smrg     }
6328627f7eb2Smrg }
6329627f7eb2Smrg 
6330627f7eb2Smrg 
6331627f7eb2Smrg /* Suppress the output of a .smod file by module, if no module
6332627f7eb2Smrg    procedures have been seen.  */
6333627f7eb2Smrg static bool no_module_procedures;
6334627f7eb2Smrg 
6335627f7eb2Smrg static void
check_for_module_procedures(gfc_symbol * sym)6336627f7eb2Smrg check_for_module_procedures (gfc_symbol *sym)
6337627f7eb2Smrg {
6338627f7eb2Smrg   if (sym && sym->attr.module_procedure)
6339627f7eb2Smrg     no_module_procedures = false;
6340627f7eb2Smrg }
6341627f7eb2Smrg 
6342627f7eb2Smrg 
6343627f7eb2Smrg void
gfc_dump_module(const char * name,int dump_flag)6344627f7eb2Smrg gfc_dump_module (const char *name, int dump_flag)
6345627f7eb2Smrg {
6346627f7eb2Smrg   if (gfc_state_stack->state == COMP_SUBMODULE)
6347627f7eb2Smrg     dump_smod = true;
6348627f7eb2Smrg   else
6349627f7eb2Smrg     dump_smod =false;
6350627f7eb2Smrg 
6351627f7eb2Smrg   no_module_procedures = true;
6352627f7eb2Smrg   gfc_traverse_ns (gfc_current_ns, check_for_module_procedures);
6353627f7eb2Smrg 
6354627f7eb2Smrg   dump_module (name, dump_flag);
6355627f7eb2Smrg 
6356627f7eb2Smrg   if (no_module_procedures || dump_smod)
6357627f7eb2Smrg     return;
6358627f7eb2Smrg 
6359627f7eb2Smrg   /* Write a submodule file from a module.  The 'dump_smod' flag switches
6360627f7eb2Smrg      off the check for PRIVATE entities.  */
6361627f7eb2Smrg   dump_smod = true;
6362627f7eb2Smrg   submodule_name = module_name;
6363627f7eb2Smrg   dump_module (name, dump_flag);
6364627f7eb2Smrg   dump_smod = false;
6365627f7eb2Smrg }
6366627f7eb2Smrg 
6367627f7eb2Smrg static void
create_intrinsic_function(const char * name,int id,const char * modname,intmod_id module,bool subroutine,gfc_symbol * result_type)6368627f7eb2Smrg create_intrinsic_function (const char *name, int id,
6369627f7eb2Smrg 			   const char *modname, intmod_id module,
6370627f7eb2Smrg 			   bool subroutine, gfc_symbol *result_type)
6371627f7eb2Smrg {
6372627f7eb2Smrg   gfc_intrinsic_sym *isym;
6373627f7eb2Smrg   gfc_symtree *tmp_symtree;
6374627f7eb2Smrg   gfc_symbol *sym;
6375627f7eb2Smrg 
6376627f7eb2Smrg   tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root, name);
6377627f7eb2Smrg   if (tmp_symtree)
6378627f7eb2Smrg     {
6379627f7eb2Smrg       if (tmp_symtree->n.sym && tmp_symtree->n.sym->module
6380627f7eb2Smrg 	  && strcmp (modname, tmp_symtree->n.sym->module) == 0)
6381627f7eb2Smrg 	return;
6382627f7eb2Smrg       gfc_error ("Symbol %qs at %C already declared", name);
6383627f7eb2Smrg       return;
6384627f7eb2Smrg     }
6385627f7eb2Smrg 
6386627f7eb2Smrg   gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree, false);
6387627f7eb2Smrg   sym = tmp_symtree->n.sym;
6388627f7eb2Smrg 
6389627f7eb2Smrg   if (subroutine)
6390627f7eb2Smrg     {
6391627f7eb2Smrg       gfc_isym_id isym_id = gfc_isym_id_by_intmod (module, id);
6392627f7eb2Smrg       isym = gfc_intrinsic_subroutine_by_id (isym_id);
6393627f7eb2Smrg       sym->attr.subroutine = 1;
6394627f7eb2Smrg     }
6395627f7eb2Smrg   else
6396627f7eb2Smrg     {
6397627f7eb2Smrg       gfc_isym_id isym_id = gfc_isym_id_by_intmod (module, id);
6398627f7eb2Smrg       isym = gfc_intrinsic_function_by_id (isym_id);
6399627f7eb2Smrg 
6400627f7eb2Smrg       sym->attr.function = 1;
6401627f7eb2Smrg       if (result_type)
6402627f7eb2Smrg 	{
6403627f7eb2Smrg 	  sym->ts.type = BT_DERIVED;
6404627f7eb2Smrg 	  sym->ts.u.derived = result_type;
6405627f7eb2Smrg 	  sym->ts.is_c_interop = 1;
6406627f7eb2Smrg 	  isym->ts.f90_type = BT_VOID;
6407627f7eb2Smrg 	  isym->ts.type = BT_DERIVED;
6408627f7eb2Smrg 	  isym->ts.f90_type = BT_VOID;
6409627f7eb2Smrg 	  isym->ts.u.derived = result_type;
6410627f7eb2Smrg 	  isym->ts.is_c_interop = 1;
6411627f7eb2Smrg 	}
6412627f7eb2Smrg     }
6413627f7eb2Smrg   gcc_assert (isym);
6414627f7eb2Smrg 
6415627f7eb2Smrg   sym->attr.flavor = FL_PROCEDURE;
6416627f7eb2Smrg   sym->attr.intrinsic = 1;
6417627f7eb2Smrg 
6418627f7eb2Smrg   sym->module = gfc_get_string ("%s", modname);
6419627f7eb2Smrg   sym->attr.use_assoc = 1;
6420627f7eb2Smrg   sym->from_intmod = module;
6421627f7eb2Smrg   sym->intmod_sym_id = id;
6422627f7eb2Smrg }
6423627f7eb2Smrg 
6424627f7eb2Smrg 
6425627f7eb2Smrg /* Import the intrinsic ISO_C_BINDING module, generating symbols in
6426627f7eb2Smrg    the current namespace for all named constants, pointer types, and
6427627f7eb2Smrg    procedures in the module unless the only clause was used or a rename
6428627f7eb2Smrg    list was provided.  */
6429627f7eb2Smrg 
6430627f7eb2Smrg static void
import_iso_c_binding_module(void)6431627f7eb2Smrg import_iso_c_binding_module (void)
6432627f7eb2Smrg {
6433627f7eb2Smrg   gfc_symbol *mod_sym = NULL, *return_type;
6434627f7eb2Smrg   gfc_symtree *mod_symtree = NULL, *tmp_symtree;
6435627f7eb2Smrg   gfc_symtree *c_ptr = NULL, *c_funptr = NULL;
6436627f7eb2Smrg   const char *iso_c_module_name = "__iso_c_binding";
6437627f7eb2Smrg   gfc_use_rename *u;
6438627f7eb2Smrg   int i;
6439627f7eb2Smrg   bool want_c_ptr = false, want_c_funptr = false;
6440627f7eb2Smrg 
6441627f7eb2Smrg   /* Look only in the current namespace.  */
6442627f7eb2Smrg   mod_symtree = gfc_find_symtree (gfc_current_ns->sym_root, iso_c_module_name);
6443627f7eb2Smrg 
6444627f7eb2Smrg   if (mod_symtree == NULL)
6445627f7eb2Smrg     {
6446627f7eb2Smrg       /* symtree doesn't already exist in current namespace.  */
6447627f7eb2Smrg       gfc_get_sym_tree (iso_c_module_name, gfc_current_ns, &mod_symtree,
6448627f7eb2Smrg 			false);
6449627f7eb2Smrg 
6450627f7eb2Smrg       if (mod_symtree != NULL)
6451627f7eb2Smrg 	mod_sym = mod_symtree->n.sym;
6452627f7eb2Smrg       else
6453627f7eb2Smrg 	gfc_internal_error ("import_iso_c_binding_module(): Unable to "
6454627f7eb2Smrg 			    "create symbol for %s", iso_c_module_name);
6455627f7eb2Smrg 
6456627f7eb2Smrg       mod_sym->attr.flavor = FL_MODULE;
6457627f7eb2Smrg       mod_sym->attr.intrinsic = 1;
6458627f7eb2Smrg       mod_sym->module = gfc_get_string ("%s", iso_c_module_name);
6459627f7eb2Smrg       mod_sym->from_intmod = INTMOD_ISO_C_BINDING;
6460627f7eb2Smrg     }
6461627f7eb2Smrg 
6462627f7eb2Smrg   /* Check whether C_PTR or C_FUNPTR are in the include list, if so, load it;
6463627f7eb2Smrg      check also whether C_NULL_(FUN)PTR or C_(FUN)LOC are requested, which
6464627f7eb2Smrg      need C_(FUN)PTR.  */
6465627f7eb2Smrg   for (u = gfc_rename_list; u; u = u->next)
6466627f7eb2Smrg     {
6467627f7eb2Smrg       if (strcmp (c_interop_kinds_table[ISOCBINDING_NULL_PTR].name,
6468627f7eb2Smrg 		  u->use_name) == 0)
6469627f7eb2Smrg         want_c_ptr = true;
6470627f7eb2Smrg       else if (strcmp (c_interop_kinds_table[ISOCBINDING_LOC].name,
6471627f7eb2Smrg 		       u->use_name) == 0)
6472627f7eb2Smrg         want_c_ptr = true;
6473627f7eb2Smrg       else if (strcmp (c_interop_kinds_table[ISOCBINDING_NULL_FUNPTR].name,
6474627f7eb2Smrg 		       u->use_name) == 0)
6475627f7eb2Smrg         want_c_funptr = true;
6476627f7eb2Smrg       else if (strcmp (c_interop_kinds_table[ISOCBINDING_FUNLOC].name,
6477627f7eb2Smrg 		       u->use_name) == 0)
6478627f7eb2Smrg         want_c_funptr = true;
6479627f7eb2Smrg       else if (strcmp (c_interop_kinds_table[ISOCBINDING_PTR].name,
6480627f7eb2Smrg                        u->use_name) == 0)
6481627f7eb2Smrg 	{
6482627f7eb2Smrg 	  c_ptr = generate_isocbinding_symbol (iso_c_module_name,
6483627f7eb2Smrg                                                (iso_c_binding_symbol)
6484627f7eb2Smrg 							ISOCBINDING_PTR,
6485627f7eb2Smrg                                                u->local_name[0] ? u->local_name
6486627f7eb2Smrg                                                                 : u->use_name,
6487627f7eb2Smrg                                                NULL, false);
6488627f7eb2Smrg 	}
6489627f7eb2Smrg       else if (strcmp (c_interop_kinds_table[ISOCBINDING_FUNPTR].name,
6490627f7eb2Smrg                        u->use_name) == 0)
6491627f7eb2Smrg 	{
6492627f7eb2Smrg 	  c_funptr
6493627f7eb2Smrg 	     = generate_isocbinding_symbol (iso_c_module_name,
6494627f7eb2Smrg 					    (iso_c_binding_symbol)
6495627f7eb2Smrg 							ISOCBINDING_FUNPTR,
6496627f7eb2Smrg 					     u->local_name[0] ? u->local_name
6497627f7eb2Smrg 							      : u->use_name,
6498627f7eb2Smrg 					     NULL, false);
6499627f7eb2Smrg 	}
6500627f7eb2Smrg     }
6501627f7eb2Smrg 
6502627f7eb2Smrg   if ((want_c_ptr || !only_flag) && !c_ptr)
6503627f7eb2Smrg     c_ptr = generate_isocbinding_symbol (iso_c_module_name,
6504627f7eb2Smrg 					 (iso_c_binding_symbol)
6505627f7eb2Smrg 							ISOCBINDING_PTR,
6506627f7eb2Smrg 					 NULL, NULL, only_flag);
6507627f7eb2Smrg   if ((want_c_funptr || !only_flag) && !c_funptr)
6508627f7eb2Smrg     c_funptr = generate_isocbinding_symbol (iso_c_module_name,
6509627f7eb2Smrg 					    (iso_c_binding_symbol)
6510627f7eb2Smrg 							ISOCBINDING_FUNPTR,
6511627f7eb2Smrg 					    NULL, NULL, only_flag);
6512627f7eb2Smrg 
6513627f7eb2Smrg   /* Generate the symbols for the named constants representing
6514627f7eb2Smrg      the kinds for intrinsic data types.  */
6515627f7eb2Smrg   for (i = 0; i < ISOCBINDING_NUMBER; i++)
6516627f7eb2Smrg     {
6517627f7eb2Smrg       bool found = false;
6518627f7eb2Smrg       for (u = gfc_rename_list; u; u = u->next)
6519627f7eb2Smrg 	if (strcmp (c_interop_kinds_table[i].name, u->use_name) == 0)
6520627f7eb2Smrg 	  {
6521627f7eb2Smrg 	    bool not_in_std;
6522627f7eb2Smrg 	    const char *name;
6523627f7eb2Smrg 	    u->found = 1;
6524627f7eb2Smrg 	    found = true;
6525627f7eb2Smrg 
6526627f7eb2Smrg 	    switch (i)
6527627f7eb2Smrg 	      {
6528627f7eb2Smrg #define NAMED_FUNCTION(a,b,c,d) \
6529627f7eb2Smrg 	        case a: \
6530627f7eb2Smrg 		  not_in_std = (gfc_option.allow_std & d) == 0; \
6531627f7eb2Smrg 		  name = b; \
6532627f7eb2Smrg 		  break;
6533627f7eb2Smrg #define NAMED_SUBROUTINE(a,b,c,d) \
6534627f7eb2Smrg 	        case a: \
6535627f7eb2Smrg 		  not_in_std = (gfc_option.allow_std & d) == 0; \
6536627f7eb2Smrg 		  name = b; \
6537627f7eb2Smrg 		  break;
6538627f7eb2Smrg #define NAMED_INTCST(a,b,c,d) \
6539627f7eb2Smrg 	        case a: \
6540627f7eb2Smrg 		  not_in_std = (gfc_option.allow_std & d) == 0; \
6541627f7eb2Smrg 		  name = b; \
6542627f7eb2Smrg 		  break;
6543627f7eb2Smrg #define NAMED_REALCST(a,b,c,d) \
6544627f7eb2Smrg 	        case a: \
6545627f7eb2Smrg 		  not_in_std = (gfc_option.allow_std & d) == 0; \
6546627f7eb2Smrg 		  name = b; \
6547627f7eb2Smrg 		  break;
6548627f7eb2Smrg #define NAMED_CMPXCST(a,b,c,d) \
6549627f7eb2Smrg 	        case a: \
6550627f7eb2Smrg 		  not_in_std = (gfc_option.allow_std & d) == 0; \
6551627f7eb2Smrg 		  name = b; \
6552627f7eb2Smrg 		  break;
6553627f7eb2Smrg #include "iso-c-binding.def"
6554627f7eb2Smrg 		default:
6555627f7eb2Smrg 		  not_in_std = false;
6556627f7eb2Smrg 		  name = "";
6557627f7eb2Smrg 	      }
6558627f7eb2Smrg 
6559627f7eb2Smrg 	    if (not_in_std)
6560627f7eb2Smrg 	      {
6561627f7eb2Smrg 		gfc_error ("The symbol %qs, referenced at %L, is not "
6562627f7eb2Smrg 			   "in the selected standard", name, &u->where);
6563627f7eb2Smrg 		continue;
6564627f7eb2Smrg 	      }
6565627f7eb2Smrg 
6566627f7eb2Smrg 	    switch (i)
6567627f7eb2Smrg 	      {
6568627f7eb2Smrg #define NAMED_FUNCTION(a,b,c,d) \
6569627f7eb2Smrg 	        case a: \
6570627f7eb2Smrg 		  if (a == ISOCBINDING_LOC) \
6571627f7eb2Smrg 		    return_type = c_ptr->n.sym; \
6572627f7eb2Smrg 		  else if (a == ISOCBINDING_FUNLOC) \
6573627f7eb2Smrg 		    return_type = c_funptr->n.sym; \
6574627f7eb2Smrg 		  else \
6575627f7eb2Smrg 		    return_type = NULL; \
6576627f7eb2Smrg 		  create_intrinsic_function (u->local_name[0] \
6577627f7eb2Smrg 					     ? u->local_name : u->use_name, \
6578627f7eb2Smrg 					     a, iso_c_module_name, \
6579627f7eb2Smrg 					     INTMOD_ISO_C_BINDING, false, \
6580627f7eb2Smrg 					     return_type); \
6581627f7eb2Smrg 		  break;
6582627f7eb2Smrg #define NAMED_SUBROUTINE(a,b,c,d) \
6583627f7eb2Smrg 	        case a: \
6584627f7eb2Smrg 		  create_intrinsic_function (u->local_name[0] ? u->local_name \
6585627f7eb2Smrg 							      : u->use_name, \
6586627f7eb2Smrg                                              a, iso_c_module_name, \
6587627f7eb2Smrg                                              INTMOD_ISO_C_BINDING, true, NULL); \
6588627f7eb2Smrg 		  break;
6589627f7eb2Smrg #include "iso-c-binding.def"
6590627f7eb2Smrg 
6591627f7eb2Smrg 		case ISOCBINDING_PTR:
6592627f7eb2Smrg 		case ISOCBINDING_FUNPTR:
6593627f7eb2Smrg 		  /* Already handled above.  */
6594627f7eb2Smrg 		  break;
6595627f7eb2Smrg 		default:
6596627f7eb2Smrg 		  if (i == ISOCBINDING_NULL_PTR)
6597627f7eb2Smrg 		    tmp_symtree = c_ptr;
6598627f7eb2Smrg 		  else if (i == ISOCBINDING_NULL_FUNPTR)
6599627f7eb2Smrg 		    tmp_symtree = c_funptr;
6600627f7eb2Smrg 		  else
6601627f7eb2Smrg 		    tmp_symtree = NULL;
6602627f7eb2Smrg 		  generate_isocbinding_symbol (iso_c_module_name,
6603627f7eb2Smrg 					       (iso_c_binding_symbol) i,
6604627f7eb2Smrg 					       u->local_name[0]
6605627f7eb2Smrg 					       ? u->local_name : u->use_name,
6606627f7eb2Smrg 					       tmp_symtree, false);
6607627f7eb2Smrg 	      }
6608627f7eb2Smrg 	  }
6609627f7eb2Smrg 
6610627f7eb2Smrg       if (!found && !only_flag)
6611627f7eb2Smrg 	{
6612627f7eb2Smrg 	  /* Skip, if the symbol is not in the enabled standard.  */
6613627f7eb2Smrg 	  switch (i)
6614627f7eb2Smrg 	    {
6615627f7eb2Smrg #define NAMED_FUNCTION(a,b,c,d) \
6616627f7eb2Smrg 	      case a: \
6617627f7eb2Smrg 		if ((gfc_option.allow_std & d) == 0) \
6618627f7eb2Smrg 		  continue; \
6619627f7eb2Smrg 		break;
6620627f7eb2Smrg #define NAMED_SUBROUTINE(a,b,c,d) \
6621627f7eb2Smrg 	      case a: \
6622627f7eb2Smrg 		if ((gfc_option.allow_std & d) == 0) \
6623627f7eb2Smrg 		  continue; \
6624627f7eb2Smrg 		break;
6625627f7eb2Smrg #define NAMED_INTCST(a,b,c,d) \
6626627f7eb2Smrg 	      case a: \
6627627f7eb2Smrg 		if ((gfc_option.allow_std & d) == 0) \
6628627f7eb2Smrg 		  continue; \
6629627f7eb2Smrg 		break;
6630627f7eb2Smrg #define NAMED_REALCST(a,b,c,d) \
6631627f7eb2Smrg 	      case a: \
6632627f7eb2Smrg 		if ((gfc_option.allow_std & d) == 0) \
6633627f7eb2Smrg 		  continue; \
6634627f7eb2Smrg 		break;
6635627f7eb2Smrg #define NAMED_CMPXCST(a,b,c,d) \
6636627f7eb2Smrg 	      case a: \
6637627f7eb2Smrg 		if ((gfc_option.allow_std & d) == 0) \
6638627f7eb2Smrg 		  continue; \
6639627f7eb2Smrg 		break;
6640627f7eb2Smrg #include "iso-c-binding.def"
6641627f7eb2Smrg 	      default:
6642627f7eb2Smrg 		; /* Not GFC_STD_* versioned.  */
6643627f7eb2Smrg 	    }
6644627f7eb2Smrg 
6645627f7eb2Smrg 	  switch (i)
6646627f7eb2Smrg 	    {
6647627f7eb2Smrg #define NAMED_FUNCTION(a,b,c,d) \
6648627f7eb2Smrg 	      case a: \
6649627f7eb2Smrg 		if (a == ISOCBINDING_LOC) \
6650627f7eb2Smrg 		  return_type = c_ptr->n.sym; \
6651627f7eb2Smrg 		else if (a == ISOCBINDING_FUNLOC) \
6652627f7eb2Smrg 		  return_type = c_funptr->n.sym; \
6653627f7eb2Smrg 		else \
6654627f7eb2Smrg 		  return_type = NULL; \
6655627f7eb2Smrg 		create_intrinsic_function (b, a, iso_c_module_name, \
6656627f7eb2Smrg 					   INTMOD_ISO_C_BINDING, false, \
6657627f7eb2Smrg 					   return_type); \
6658627f7eb2Smrg 		break;
6659627f7eb2Smrg #define NAMED_SUBROUTINE(a,b,c,d) \
6660627f7eb2Smrg 	      case a: \
6661627f7eb2Smrg 		create_intrinsic_function (b, a, iso_c_module_name, \
6662627f7eb2Smrg 					   INTMOD_ISO_C_BINDING, true, NULL); \
6663627f7eb2Smrg 		  break;
6664627f7eb2Smrg #include "iso-c-binding.def"
6665627f7eb2Smrg 
6666627f7eb2Smrg 	      case ISOCBINDING_PTR:
6667627f7eb2Smrg 	      case ISOCBINDING_FUNPTR:
6668627f7eb2Smrg 		/* Already handled above.  */
6669627f7eb2Smrg 		break;
6670627f7eb2Smrg 	      default:
6671627f7eb2Smrg 		if (i == ISOCBINDING_NULL_PTR)
6672627f7eb2Smrg 		  tmp_symtree = c_ptr;
6673627f7eb2Smrg 		else if (i == ISOCBINDING_NULL_FUNPTR)
6674627f7eb2Smrg 		  tmp_symtree = c_funptr;
6675627f7eb2Smrg 		else
6676627f7eb2Smrg 		  tmp_symtree = NULL;
6677627f7eb2Smrg 		generate_isocbinding_symbol (iso_c_module_name,
6678627f7eb2Smrg 					     (iso_c_binding_symbol) i, NULL,
6679627f7eb2Smrg 					     tmp_symtree, false);
6680627f7eb2Smrg 	    }
6681627f7eb2Smrg 	}
6682627f7eb2Smrg    }
6683627f7eb2Smrg 
6684627f7eb2Smrg    for (u = gfc_rename_list; u; u = u->next)
6685627f7eb2Smrg      {
6686627f7eb2Smrg       if (u->found)
6687627f7eb2Smrg 	continue;
6688627f7eb2Smrg 
6689627f7eb2Smrg       gfc_error ("Symbol %qs referenced at %L not found in intrinsic "
6690627f7eb2Smrg 		 "module ISO_C_BINDING", u->use_name, &u->where);
6691627f7eb2Smrg      }
6692627f7eb2Smrg }
6693627f7eb2Smrg 
6694627f7eb2Smrg 
6695627f7eb2Smrg /* Add an integer named constant from a given module.  */
6696627f7eb2Smrg 
6697627f7eb2Smrg static void
create_int_parameter(const char * name,int value,const char * modname,intmod_id module,int id)6698627f7eb2Smrg create_int_parameter (const char *name, int value, const char *modname,
6699627f7eb2Smrg 		      intmod_id module, int id)
6700627f7eb2Smrg {
6701627f7eb2Smrg   gfc_symtree *tmp_symtree;
6702627f7eb2Smrg   gfc_symbol *sym;
6703627f7eb2Smrg 
6704627f7eb2Smrg   tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root, name);
6705627f7eb2Smrg   if (tmp_symtree != NULL)
6706627f7eb2Smrg     {
6707627f7eb2Smrg       if (strcmp (modname, tmp_symtree->n.sym->module) == 0)
6708627f7eb2Smrg 	return;
6709627f7eb2Smrg       else
6710627f7eb2Smrg 	gfc_error ("Symbol %qs already declared", name);
6711627f7eb2Smrg     }
6712627f7eb2Smrg 
6713627f7eb2Smrg   gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree, false);
6714627f7eb2Smrg   sym = tmp_symtree->n.sym;
6715627f7eb2Smrg 
6716627f7eb2Smrg   sym->module = gfc_get_string ("%s", modname);
6717627f7eb2Smrg   sym->attr.flavor = FL_PARAMETER;
6718627f7eb2Smrg   sym->ts.type = BT_INTEGER;
6719627f7eb2Smrg   sym->ts.kind = gfc_default_integer_kind;
6720627f7eb2Smrg   sym->value = gfc_get_int_expr (gfc_default_integer_kind, NULL, value);
6721627f7eb2Smrg   sym->attr.use_assoc = 1;
6722627f7eb2Smrg   sym->from_intmod = module;
6723627f7eb2Smrg   sym->intmod_sym_id = id;
6724627f7eb2Smrg }
6725627f7eb2Smrg 
6726627f7eb2Smrg 
6727627f7eb2Smrg /* Value is already contained by the array constructor, but not
6728627f7eb2Smrg    yet the shape.  */
6729627f7eb2Smrg 
6730627f7eb2Smrg static void
create_int_parameter_array(const char * name,int size,gfc_expr * value,const char * modname,intmod_id module,int id)6731627f7eb2Smrg create_int_parameter_array (const char *name, int size, gfc_expr *value,
6732627f7eb2Smrg 			    const char *modname, intmod_id module, int id)
6733627f7eb2Smrg {
6734627f7eb2Smrg   gfc_symtree *tmp_symtree;
6735627f7eb2Smrg   gfc_symbol *sym;
6736627f7eb2Smrg 
6737627f7eb2Smrg   tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root, name);
6738627f7eb2Smrg   if (tmp_symtree != NULL)
6739627f7eb2Smrg     {
6740627f7eb2Smrg       if (strcmp (modname, tmp_symtree->n.sym->module) == 0)
6741627f7eb2Smrg 	return;
6742627f7eb2Smrg       else
6743627f7eb2Smrg 	gfc_error ("Symbol %qs already declared", name);
6744627f7eb2Smrg     }
6745627f7eb2Smrg 
6746627f7eb2Smrg   gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree, false);
6747627f7eb2Smrg   sym = tmp_symtree->n.sym;
6748627f7eb2Smrg 
6749627f7eb2Smrg   sym->module = gfc_get_string ("%s", modname);
6750627f7eb2Smrg   sym->attr.flavor = FL_PARAMETER;
6751627f7eb2Smrg   sym->ts.type = BT_INTEGER;
6752627f7eb2Smrg   sym->ts.kind = gfc_default_integer_kind;
6753627f7eb2Smrg   sym->attr.use_assoc = 1;
6754627f7eb2Smrg   sym->from_intmod = module;
6755627f7eb2Smrg   sym->intmod_sym_id = id;
6756627f7eb2Smrg   sym->attr.dimension = 1;
6757627f7eb2Smrg   sym->as = gfc_get_array_spec ();
6758627f7eb2Smrg   sym->as->rank = 1;
6759627f7eb2Smrg   sym->as->type = AS_EXPLICIT;
6760627f7eb2Smrg   sym->as->lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
6761627f7eb2Smrg   sym->as->upper[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, size);
6762627f7eb2Smrg 
6763627f7eb2Smrg   sym->value = value;
6764627f7eb2Smrg   sym->value->shape = gfc_get_shape (1);
6765627f7eb2Smrg   mpz_init_set_ui (sym->value->shape[0], size);
6766627f7eb2Smrg }
6767627f7eb2Smrg 
6768627f7eb2Smrg 
6769627f7eb2Smrg /* Add an derived type for a given module.  */
6770627f7eb2Smrg 
6771627f7eb2Smrg static void
create_derived_type(const char * name,const char * modname,intmod_id module,int id)6772627f7eb2Smrg create_derived_type (const char *name, const char *modname,
6773627f7eb2Smrg 		      intmod_id module, int id)
6774627f7eb2Smrg {
6775627f7eb2Smrg   gfc_symtree *tmp_symtree;
6776627f7eb2Smrg   gfc_symbol *sym, *dt_sym;
6777627f7eb2Smrg   gfc_interface *intr, *head;
6778627f7eb2Smrg 
6779627f7eb2Smrg   tmp_symtree = gfc_find_symtree (gfc_current_ns->sym_root, name);
6780627f7eb2Smrg   if (tmp_symtree != NULL)
6781627f7eb2Smrg     {
6782627f7eb2Smrg       if (strcmp (modname, tmp_symtree->n.sym->module) == 0)
6783627f7eb2Smrg 	return;
6784627f7eb2Smrg       else
6785627f7eb2Smrg 	gfc_error ("Symbol %qs already declared", name);
6786627f7eb2Smrg     }
6787627f7eb2Smrg 
6788627f7eb2Smrg   gfc_get_sym_tree (name, gfc_current_ns, &tmp_symtree, false);
6789627f7eb2Smrg   sym = tmp_symtree->n.sym;
6790627f7eb2Smrg   sym->module = gfc_get_string ("%s", modname);
6791627f7eb2Smrg   sym->from_intmod = module;
6792627f7eb2Smrg   sym->intmod_sym_id = id;
6793627f7eb2Smrg   sym->attr.flavor = FL_PROCEDURE;
6794627f7eb2Smrg   sym->attr.function = 1;
6795627f7eb2Smrg   sym->attr.generic = 1;
6796627f7eb2Smrg 
6797627f7eb2Smrg   gfc_get_sym_tree (gfc_dt_upper_string (sym->name),
6798627f7eb2Smrg 		    gfc_current_ns, &tmp_symtree, false);
6799627f7eb2Smrg   dt_sym = tmp_symtree->n.sym;
6800627f7eb2Smrg   dt_sym->name = gfc_get_string ("%s", sym->name);
6801627f7eb2Smrg   dt_sym->attr.flavor = FL_DERIVED;
6802627f7eb2Smrg   dt_sym->attr.private_comp = 1;
6803627f7eb2Smrg   dt_sym->attr.zero_comp = 1;
6804627f7eb2Smrg   dt_sym->attr.use_assoc = 1;
6805627f7eb2Smrg   dt_sym->module = gfc_get_string ("%s", modname);
6806627f7eb2Smrg   dt_sym->from_intmod = module;
6807627f7eb2Smrg   dt_sym->intmod_sym_id = id;
6808627f7eb2Smrg 
6809627f7eb2Smrg   head = sym->generic;
6810627f7eb2Smrg   intr = gfc_get_interface ();
6811627f7eb2Smrg   intr->sym = dt_sym;
6812627f7eb2Smrg   intr->where = gfc_current_locus;
6813627f7eb2Smrg   intr->next = head;
6814627f7eb2Smrg   sym->generic = intr;
6815627f7eb2Smrg   sym->attr.if_source = IFSRC_DECL;
6816627f7eb2Smrg }
6817627f7eb2Smrg 
6818627f7eb2Smrg 
6819627f7eb2Smrg /* Read the contents of the module file into a temporary buffer.  */
6820627f7eb2Smrg 
6821627f7eb2Smrg static void
read_module_to_tmpbuf()6822627f7eb2Smrg read_module_to_tmpbuf ()
6823627f7eb2Smrg {
6824627f7eb2Smrg   /* We don't know the uncompressed size, so enlarge the buffer as
6825627f7eb2Smrg      needed.  */
6826627f7eb2Smrg   int cursz = 4096;
6827627f7eb2Smrg   int rsize = cursz;
6828627f7eb2Smrg   int len = 0;
6829627f7eb2Smrg 
6830627f7eb2Smrg   module_content = XNEWVEC (char, cursz);
6831627f7eb2Smrg 
6832627f7eb2Smrg   while (1)
6833627f7eb2Smrg     {
6834627f7eb2Smrg       int nread = gzread (module_fp, module_content + len, rsize);
6835627f7eb2Smrg       len += nread;
6836627f7eb2Smrg       if (nread < rsize)
6837627f7eb2Smrg 	break;
6838627f7eb2Smrg       cursz *= 2;
6839627f7eb2Smrg       module_content = XRESIZEVEC (char, module_content, cursz);
6840627f7eb2Smrg       rsize = cursz - len;
6841627f7eb2Smrg     }
6842627f7eb2Smrg 
6843627f7eb2Smrg   module_content = XRESIZEVEC (char, module_content, len + 1);
6844627f7eb2Smrg   module_content[len] = '\0';
6845627f7eb2Smrg 
6846627f7eb2Smrg   module_pos = 0;
6847627f7eb2Smrg }
6848627f7eb2Smrg 
6849627f7eb2Smrg 
6850627f7eb2Smrg /* USE the ISO_FORTRAN_ENV intrinsic module.  */
6851627f7eb2Smrg 
6852627f7eb2Smrg static void
use_iso_fortran_env_module(void)6853627f7eb2Smrg use_iso_fortran_env_module (void)
6854627f7eb2Smrg {
6855627f7eb2Smrg   static char mod[] = "iso_fortran_env";
6856627f7eb2Smrg   gfc_use_rename *u;
6857627f7eb2Smrg   gfc_symbol *mod_sym;
6858627f7eb2Smrg   gfc_symtree *mod_symtree;
6859627f7eb2Smrg   gfc_expr *expr;
6860627f7eb2Smrg   int i, j;
6861627f7eb2Smrg 
6862627f7eb2Smrg   intmod_sym symbol[] = {
6863627f7eb2Smrg #define NAMED_INTCST(a,b,c,d) { a, b, 0, d },
6864627f7eb2Smrg #define NAMED_KINDARRAY(a,b,c,d) { a, b, 0, d },
6865627f7eb2Smrg #define NAMED_DERIVED_TYPE(a,b,c,d) { a, b, 0, d },
6866627f7eb2Smrg #define NAMED_FUNCTION(a,b,c,d) { a, b, c, d },
6867627f7eb2Smrg #define NAMED_SUBROUTINE(a,b,c,d) { a, b, c, d },
6868627f7eb2Smrg #include "iso-fortran-env.def"
6869627f7eb2Smrg     { ISOFORTRANENV_INVALID, NULL, -1234, 0 } };
6870627f7eb2Smrg 
6871627f7eb2Smrg   i = 0;
6872627f7eb2Smrg #define NAMED_INTCST(a,b,c,d) symbol[i++].value = c;
6873627f7eb2Smrg #include "iso-fortran-env.def"
6874627f7eb2Smrg 
6875627f7eb2Smrg   /* Generate the symbol for the module itself.  */
6876627f7eb2Smrg   mod_symtree = gfc_find_symtree (gfc_current_ns->sym_root, mod);
6877627f7eb2Smrg   if (mod_symtree == NULL)
6878627f7eb2Smrg     {
6879627f7eb2Smrg       gfc_get_sym_tree (mod, gfc_current_ns, &mod_symtree, false);
6880627f7eb2Smrg       gcc_assert (mod_symtree);
6881627f7eb2Smrg       mod_sym = mod_symtree->n.sym;
6882627f7eb2Smrg 
6883627f7eb2Smrg       mod_sym->attr.flavor = FL_MODULE;
6884627f7eb2Smrg       mod_sym->attr.intrinsic = 1;
6885627f7eb2Smrg       mod_sym->module = gfc_get_string ("%s", mod);
6886627f7eb2Smrg       mod_sym->from_intmod = INTMOD_ISO_FORTRAN_ENV;
6887627f7eb2Smrg     }
6888627f7eb2Smrg   else
6889627f7eb2Smrg     if (!mod_symtree->n.sym->attr.intrinsic)
6890627f7eb2Smrg       gfc_error ("Use of intrinsic module %qs at %C conflicts with "
6891627f7eb2Smrg 		 "non-intrinsic module name used previously", mod);
6892627f7eb2Smrg 
6893627f7eb2Smrg   /* Generate the symbols for the module integer named constants.  */
6894627f7eb2Smrg 
6895627f7eb2Smrg   for (i = 0; symbol[i].name; i++)
6896627f7eb2Smrg     {
6897627f7eb2Smrg       bool found = false;
6898627f7eb2Smrg       for (u = gfc_rename_list; u; u = u->next)
6899627f7eb2Smrg 	{
6900627f7eb2Smrg 	  if (strcmp (symbol[i].name, u->use_name) == 0)
6901627f7eb2Smrg 	    {
6902627f7eb2Smrg 	      found = true;
6903627f7eb2Smrg 	      u->found = 1;
6904627f7eb2Smrg 
6905627f7eb2Smrg 	      if (!gfc_notify_std (symbol[i].standard, "The symbol %qs, "
6906627f7eb2Smrg 				   "referenced at %L, is not in the selected "
6907627f7eb2Smrg 				   "standard", symbol[i].name, &u->where))
6908627f7eb2Smrg 	        continue;
6909627f7eb2Smrg 
6910627f7eb2Smrg 	      if ((flag_default_integer || flag_default_real_8)
6911627f7eb2Smrg 		  && symbol[i].id == ISOFORTRANENV_NUMERIC_STORAGE_SIZE)
6912627f7eb2Smrg 		gfc_warning_now (0, "Use of the NUMERIC_STORAGE_SIZE named "
6913627f7eb2Smrg 				 "constant from intrinsic module "
6914627f7eb2Smrg 				 "ISO_FORTRAN_ENV at %L is incompatible with "
6915627f7eb2Smrg 				 "option %qs", &u->where,
6916627f7eb2Smrg 				 flag_default_integer
6917627f7eb2Smrg 				   ? "-fdefault-integer-8"
6918627f7eb2Smrg 				   : "-fdefault-real-8");
6919627f7eb2Smrg 	      switch (symbol[i].id)
6920627f7eb2Smrg 		{
6921627f7eb2Smrg #define NAMED_INTCST(a,b,c,d) \
6922627f7eb2Smrg 		case a:
6923627f7eb2Smrg #include "iso-fortran-env.def"
6924627f7eb2Smrg 		  create_int_parameter (u->local_name[0] ? u->local_name
6925627f7eb2Smrg 							 : u->use_name,
6926627f7eb2Smrg 					symbol[i].value, mod,
6927627f7eb2Smrg 					INTMOD_ISO_FORTRAN_ENV, symbol[i].id);
6928627f7eb2Smrg 		  break;
6929627f7eb2Smrg 
6930627f7eb2Smrg #define NAMED_KINDARRAY(a,b,KINDS,d) \
6931627f7eb2Smrg 		case a:\
6932627f7eb2Smrg 		  expr = gfc_get_array_expr (BT_INTEGER, \
6933627f7eb2Smrg 					     gfc_default_integer_kind,\
6934627f7eb2Smrg 					     NULL); \
6935627f7eb2Smrg 		  for (j = 0; KINDS[j].kind != 0; j++) \
6936627f7eb2Smrg 		    gfc_constructor_append_expr (&expr->value.constructor, \
6937627f7eb2Smrg 			gfc_get_int_expr (gfc_default_integer_kind, NULL, \
6938627f7eb2Smrg 					  KINDS[j].kind), NULL); \
6939627f7eb2Smrg 		  create_int_parameter_array (u->local_name[0] ? u->local_name \
6940627f7eb2Smrg 							 : u->use_name, \
6941627f7eb2Smrg 					      j, expr, mod, \
6942627f7eb2Smrg 					      INTMOD_ISO_FORTRAN_ENV, \
6943627f7eb2Smrg 					      symbol[i].id); \
6944627f7eb2Smrg 		  break;
6945627f7eb2Smrg #include "iso-fortran-env.def"
6946627f7eb2Smrg 
6947627f7eb2Smrg #define NAMED_DERIVED_TYPE(a,b,TYPE,STD) \
6948627f7eb2Smrg 		case a:
6949627f7eb2Smrg #include "iso-fortran-env.def"
6950627f7eb2Smrg                   create_derived_type (u->local_name[0] ? u->local_name
6951627f7eb2Smrg 							: u->use_name,
6952627f7eb2Smrg 				       mod, INTMOD_ISO_FORTRAN_ENV,
6953627f7eb2Smrg 				       symbol[i].id);
6954627f7eb2Smrg 		  break;
6955627f7eb2Smrg 
6956627f7eb2Smrg #define NAMED_FUNCTION(a,b,c,d) \
6957627f7eb2Smrg 		case a:
6958627f7eb2Smrg #include "iso-fortran-env.def"
6959627f7eb2Smrg 		  create_intrinsic_function (u->local_name[0] ? u->local_name
6960627f7eb2Smrg 							      : u->use_name,
6961627f7eb2Smrg 					     symbol[i].id, mod,
6962627f7eb2Smrg 					     INTMOD_ISO_FORTRAN_ENV, false,
6963627f7eb2Smrg 					     NULL);
6964627f7eb2Smrg 		  break;
6965627f7eb2Smrg 
6966627f7eb2Smrg 		default:
6967627f7eb2Smrg 		  gcc_unreachable ();
6968627f7eb2Smrg 		}
6969627f7eb2Smrg 	    }
6970627f7eb2Smrg 	}
6971627f7eb2Smrg 
6972627f7eb2Smrg       if (!found && !only_flag)
6973627f7eb2Smrg 	{
6974627f7eb2Smrg 	  if ((gfc_option.allow_std & symbol[i].standard) == 0)
6975627f7eb2Smrg 	    continue;
6976627f7eb2Smrg 
6977627f7eb2Smrg 	  if ((flag_default_integer || flag_default_real_8)
6978627f7eb2Smrg 	      && symbol[i].id == ISOFORTRANENV_NUMERIC_STORAGE_SIZE)
6979627f7eb2Smrg 	    gfc_warning_now (0,
6980627f7eb2Smrg 			     "Use of the NUMERIC_STORAGE_SIZE named constant "
6981627f7eb2Smrg 			     "from intrinsic module ISO_FORTRAN_ENV at %C is "
6982627f7eb2Smrg 			     "incompatible with option %s",
6983627f7eb2Smrg 			     flag_default_integer
6984627f7eb2Smrg 				? "-fdefault-integer-8" : "-fdefault-real-8");
6985627f7eb2Smrg 
6986627f7eb2Smrg 	  switch (symbol[i].id)
6987627f7eb2Smrg 	    {
6988627f7eb2Smrg #define NAMED_INTCST(a,b,c,d) \
6989627f7eb2Smrg 	    case a:
6990627f7eb2Smrg #include "iso-fortran-env.def"
6991627f7eb2Smrg 	      create_int_parameter (symbol[i].name, symbol[i].value, mod,
6992627f7eb2Smrg 				    INTMOD_ISO_FORTRAN_ENV, symbol[i].id);
6993627f7eb2Smrg 	      break;
6994627f7eb2Smrg 
6995627f7eb2Smrg #define NAMED_KINDARRAY(a,b,KINDS,d) \
6996627f7eb2Smrg 	    case a:\
6997627f7eb2Smrg 	      expr = gfc_get_array_expr (BT_INTEGER, gfc_default_integer_kind, \
6998627f7eb2Smrg 					 NULL); \
6999627f7eb2Smrg 	      for (j = 0; KINDS[j].kind != 0; j++) \
7000627f7eb2Smrg 		gfc_constructor_append_expr (&expr->value.constructor, \
7001627f7eb2Smrg                       gfc_get_int_expr (gfc_default_integer_kind, NULL, \
7002627f7eb2Smrg                                         KINDS[j].kind), NULL); \
7003627f7eb2Smrg             create_int_parameter_array (symbol[i].name, j, expr, mod, \
7004627f7eb2Smrg                                         INTMOD_ISO_FORTRAN_ENV, symbol[i].id);\
7005627f7eb2Smrg             break;
7006627f7eb2Smrg #include "iso-fortran-env.def"
7007627f7eb2Smrg 
7008627f7eb2Smrg #define NAMED_DERIVED_TYPE(a,b,TYPE,STD) \
7009627f7eb2Smrg 	  case a:
7010627f7eb2Smrg #include "iso-fortran-env.def"
7011627f7eb2Smrg 	    create_derived_type (symbol[i].name, mod, INTMOD_ISO_FORTRAN_ENV,
7012627f7eb2Smrg 				 symbol[i].id);
7013627f7eb2Smrg 	    break;
7014627f7eb2Smrg 
7015627f7eb2Smrg #define NAMED_FUNCTION(a,b,c,d) \
7016627f7eb2Smrg 		case a:
7017627f7eb2Smrg #include "iso-fortran-env.def"
7018627f7eb2Smrg 		  create_intrinsic_function (symbol[i].name, symbol[i].id, mod,
7019627f7eb2Smrg 					     INTMOD_ISO_FORTRAN_ENV, false,
7020627f7eb2Smrg 					     NULL);
7021627f7eb2Smrg 		  break;
7022627f7eb2Smrg 
7023627f7eb2Smrg 	  default:
7024627f7eb2Smrg 	    gcc_unreachable ();
7025627f7eb2Smrg 	  }
7026627f7eb2Smrg 	}
7027627f7eb2Smrg     }
7028627f7eb2Smrg 
7029627f7eb2Smrg   for (u = gfc_rename_list; u; u = u->next)
7030627f7eb2Smrg     {
7031627f7eb2Smrg       if (u->found)
7032627f7eb2Smrg 	continue;
7033627f7eb2Smrg 
7034627f7eb2Smrg       gfc_error ("Symbol %qs referenced at %L not found in intrinsic "
7035627f7eb2Smrg 		     "module ISO_FORTRAN_ENV", u->use_name, &u->where);
7036627f7eb2Smrg     }
7037627f7eb2Smrg }
7038627f7eb2Smrg 
7039627f7eb2Smrg 
7040627f7eb2Smrg /* Process a USE directive.  */
7041627f7eb2Smrg 
7042627f7eb2Smrg static void
gfc_use_module(gfc_use_list * module)7043627f7eb2Smrg gfc_use_module (gfc_use_list *module)
7044627f7eb2Smrg {
7045627f7eb2Smrg   char *filename;
7046627f7eb2Smrg   gfc_state_data *p;
7047627f7eb2Smrg   int c, line, start;
7048627f7eb2Smrg   gfc_symtree *mod_symtree;
7049627f7eb2Smrg   gfc_use_list *use_stmt;
7050627f7eb2Smrg   locus old_locus = gfc_current_locus;
7051627f7eb2Smrg 
7052627f7eb2Smrg   gfc_current_locus = module->where;
7053627f7eb2Smrg   module_name = module->module_name;
7054627f7eb2Smrg   gfc_rename_list = module->rename;
7055627f7eb2Smrg   only_flag = module->only_flag;
7056627f7eb2Smrg   current_intmod = INTMOD_NONE;
7057627f7eb2Smrg 
7058627f7eb2Smrg   if (!only_flag)
7059627f7eb2Smrg     gfc_warning_now (OPT_Wuse_without_only,
7060627f7eb2Smrg 		     "USE statement at %C has no ONLY qualifier");
7061627f7eb2Smrg 
7062627f7eb2Smrg   if (gfc_state_stack->state == COMP_MODULE
7063627f7eb2Smrg       || module->submodule_name == NULL)
7064627f7eb2Smrg     {
7065627f7eb2Smrg       filename = XALLOCAVEC (char, strlen (module_name)
7066627f7eb2Smrg 				   + strlen (MODULE_EXTENSION) + 1);
7067627f7eb2Smrg       strcpy (filename, module_name);
7068627f7eb2Smrg       strcat (filename, MODULE_EXTENSION);
7069627f7eb2Smrg     }
7070627f7eb2Smrg   else
7071627f7eb2Smrg     {
7072627f7eb2Smrg       filename = XALLOCAVEC (char, strlen (module->submodule_name)
7073627f7eb2Smrg 				   + strlen (SUBMODULE_EXTENSION) + 1);
7074627f7eb2Smrg       strcpy (filename, module->submodule_name);
7075627f7eb2Smrg       strcat (filename, SUBMODULE_EXTENSION);
7076627f7eb2Smrg     }
7077627f7eb2Smrg 
7078627f7eb2Smrg   /* First, try to find an non-intrinsic module, unless the USE statement
7079627f7eb2Smrg      specified that the module is intrinsic.  */
7080627f7eb2Smrg   module_fp = NULL;
7081627f7eb2Smrg   if (!module->intrinsic)
7082627f7eb2Smrg     module_fp = gzopen_included_file (filename, true, true);
7083627f7eb2Smrg 
7084627f7eb2Smrg   /* Then, see if it's an intrinsic one, unless the USE statement
7085627f7eb2Smrg      specified that the module is non-intrinsic.  */
7086627f7eb2Smrg   if (module_fp == NULL && !module->non_intrinsic)
7087627f7eb2Smrg     {
7088627f7eb2Smrg       if (strcmp (module_name, "iso_fortran_env") == 0
7089627f7eb2Smrg 	  && gfc_notify_std (GFC_STD_F2003, "ISO_FORTRAN_ENV "
7090627f7eb2Smrg 			     "intrinsic module at %C"))
7091627f7eb2Smrg        {
7092627f7eb2Smrg 	 use_iso_fortran_env_module ();
7093627f7eb2Smrg 	 free_rename (module->rename);
7094627f7eb2Smrg 	 module->rename = NULL;
7095627f7eb2Smrg 	 gfc_current_locus = old_locus;
7096627f7eb2Smrg 	 module->intrinsic = true;
7097627f7eb2Smrg 	 return;
7098627f7eb2Smrg        }
7099627f7eb2Smrg 
7100627f7eb2Smrg       if (strcmp (module_name, "iso_c_binding") == 0
7101627f7eb2Smrg 	  && gfc_notify_std (GFC_STD_F2003, "ISO_C_BINDING module at %C"))
7102627f7eb2Smrg 	{
7103627f7eb2Smrg 	  import_iso_c_binding_module();
7104627f7eb2Smrg 	  free_rename (module->rename);
7105627f7eb2Smrg 	  module->rename = NULL;
7106627f7eb2Smrg 	  gfc_current_locus = old_locus;
7107627f7eb2Smrg 	  module->intrinsic = true;
7108627f7eb2Smrg 	  return;
7109627f7eb2Smrg 	}
7110627f7eb2Smrg 
7111627f7eb2Smrg       module_fp = gzopen_intrinsic_module (filename);
7112627f7eb2Smrg 
7113627f7eb2Smrg       if (module_fp == NULL && module->intrinsic)
7114627f7eb2Smrg 	gfc_fatal_error ("Cannot find an intrinsic module named %qs at %C",
7115627f7eb2Smrg 			 module_name);
7116627f7eb2Smrg 
7117627f7eb2Smrg       /* Check for the IEEE modules, so we can mark their symbols
7118627f7eb2Smrg 	 accordingly when we read them.  */
7119627f7eb2Smrg       if (strcmp (module_name, "ieee_features") == 0
7120627f7eb2Smrg 	  && gfc_notify_std (GFC_STD_F2003, "IEEE_FEATURES module at %C"))
7121627f7eb2Smrg 	{
7122627f7eb2Smrg 	  current_intmod = INTMOD_IEEE_FEATURES;
7123627f7eb2Smrg 	}
7124627f7eb2Smrg       else if (strcmp (module_name, "ieee_exceptions") == 0
7125627f7eb2Smrg 	       && gfc_notify_std (GFC_STD_F2003,
7126627f7eb2Smrg 				  "IEEE_EXCEPTIONS module at %C"))
7127627f7eb2Smrg 	{
7128627f7eb2Smrg 	  current_intmod = INTMOD_IEEE_EXCEPTIONS;
7129627f7eb2Smrg 	}
7130627f7eb2Smrg       else if (strcmp (module_name, "ieee_arithmetic") == 0
7131627f7eb2Smrg 	       && gfc_notify_std (GFC_STD_F2003,
7132627f7eb2Smrg 				  "IEEE_ARITHMETIC module at %C"))
7133627f7eb2Smrg 	{
7134627f7eb2Smrg 	  current_intmod = INTMOD_IEEE_ARITHMETIC;
7135627f7eb2Smrg 	}
7136627f7eb2Smrg     }
7137627f7eb2Smrg 
7138627f7eb2Smrg   if (module_fp == NULL)
7139627f7eb2Smrg     {
7140627f7eb2Smrg       if (gfc_state_stack->state != COMP_SUBMODULE
7141627f7eb2Smrg 	  && module->submodule_name == NULL)
7142627f7eb2Smrg 	gfc_fatal_error ("Cannot open module file %qs for reading at %C: %s",
7143627f7eb2Smrg 			 filename, xstrerror (errno));
7144627f7eb2Smrg       else
7145627f7eb2Smrg 	gfc_fatal_error ("Module file %qs has not been generated, either "
7146627f7eb2Smrg 			 "because the module does not contain a MODULE "
7147627f7eb2Smrg 			 "PROCEDURE or there is an error in the module.",
7148627f7eb2Smrg 			 filename);
7149627f7eb2Smrg     }
7150627f7eb2Smrg 
7151627f7eb2Smrg   /* Check that we haven't already USEd an intrinsic module with the
7152627f7eb2Smrg      same name.  */
7153627f7eb2Smrg 
7154627f7eb2Smrg   mod_symtree = gfc_find_symtree (gfc_current_ns->sym_root, module_name);
7155627f7eb2Smrg   if (mod_symtree && mod_symtree->n.sym->attr.intrinsic)
7156627f7eb2Smrg     gfc_error ("Use of non-intrinsic module %qs at %C conflicts with "
7157627f7eb2Smrg 	       "intrinsic module name used previously", module_name);
7158627f7eb2Smrg 
7159627f7eb2Smrg   iomode = IO_INPUT;
7160627f7eb2Smrg   module_line = 1;
7161627f7eb2Smrg   module_column = 1;
7162627f7eb2Smrg   start = 0;
7163627f7eb2Smrg 
7164627f7eb2Smrg   read_module_to_tmpbuf ();
7165627f7eb2Smrg   gzclose (module_fp);
7166627f7eb2Smrg 
7167627f7eb2Smrg   /* Skip the first line of the module, after checking that this is
7168627f7eb2Smrg      a gfortran module file.  */
7169627f7eb2Smrg   line = 0;
7170627f7eb2Smrg   while (line < 1)
7171627f7eb2Smrg     {
7172627f7eb2Smrg       c = module_char ();
7173627f7eb2Smrg       if (c == EOF)
7174627f7eb2Smrg 	bad_module ("Unexpected end of module");
7175627f7eb2Smrg       if (start++ < 3)
7176627f7eb2Smrg 	parse_name (c);
7177627f7eb2Smrg       if ((start == 1 && strcmp (atom_name, "GFORTRAN") != 0)
7178627f7eb2Smrg 	  || (start == 2 && strcmp (atom_name, " module") != 0))
7179627f7eb2Smrg 	gfc_fatal_error ("File %qs opened at %C is not a GNU Fortran"
7180*4c3eb207Smrg 			 " module file", module_fullpath);
7181627f7eb2Smrg       if (start == 3)
7182627f7eb2Smrg 	{
7183627f7eb2Smrg 	  if (strcmp (atom_name, " version") != 0
7184627f7eb2Smrg 	      || module_char () != ' '
7185627f7eb2Smrg 	      || parse_atom () != ATOM_STRING
7186627f7eb2Smrg 	      || strcmp (atom_string, MOD_VERSION))
7187627f7eb2Smrg 	    gfc_fatal_error ("Cannot read module file %qs opened at %C,"
7188627f7eb2Smrg 			     " because it was created by a different"
7189*4c3eb207Smrg 			     " version of GNU Fortran", module_fullpath);
7190627f7eb2Smrg 
7191627f7eb2Smrg 	  free (atom_string);
7192627f7eb2Smrg 	}
7193627f7eb2Smrg 
7194627f7eb2Smrg       if (c == '\n')
7195627f7eb2Smrg 	line++;
7196627f7eb2Smrg     }
7197627f7eb2Smrg 
7198627f7eb2Smrg   /* Make sure we're not reading the same module that we may be building.  */
7199627f7eb2Smrg   for (p = gfc_state_stack; p; p = p->previous)
7200627f7eb2Smrg     if ((p->state == COMP_MODULE || p->state == COMP_SUBMODULE)
7201627f7eb2Smrg 	 && strcmp (p->sym->name, module_name) == 0)
7202627f7eb2Smrg       {
7203627f7eb2Smrg 	if (p->state == COMP_SUBMODULE)
7204627f7eb2Smrg 	  gfc_fatal_error ("Cannot USE a submodule that is currently built");
7205627f7eb2Smrg 	else
7206627f7eb2Smrg 	  gfc_fatal_error ("Cannot USE a module that is currently built");
7207627f7eb2Smrg       }
7208627f7eb2Smrg 
7209627f7eb2Smrg   init_pi_tree ();
7210627f7eb2Smrg   init_true_name_tree ();
7211627f7eb2Smrg 
7212627f7eb2Smrg   read_module ();
7213627f7eb2Smrg 
7214627f7eb2Smrg   free_true_name (true_name_root);
7215627f7eb2Smrg   true_name_root = NULL;
7216627f7eb2Smrg 
7217627f7eb2Smrg   free_pi_tree (pi_root);
7218627f7eb2Smrg   pi_root = NULL;
7219627f7eb2Smrg 
7220627f7eb2Smrg   XDELETEVEC (module_content);
7221627f7eb2Smrg   module_content = NULL;
7222627f7eb2Smrg 
7223627f7eb2Smrg   use_stmt = gfc_get_use_list ();
7224627f7eb2Smrg   *use_stmt = *module;
7225627f7eb2Smrg   use_stmt->next = gfc_current_ns->use_stmts;
7226627f7eb2Smrg   gfc_current_ns->use_stmts = use_stmt;
7227627f7eb2Smrg 
7228627f7eb2Smrg   gfc_current_locus = old_locus;
7229627f7eb2Smrg }
7230627f7eb2Smrg 
7231627f7eb2Smrg 
7232627f7eb2Smrg /* Remove duplicated intrinsic operators from the rename list.  */
7233627f7eb2Smrg 
7234627f7eb2Smrg static void
rename_list_remove_duplicate(gfc_use_rename * list)7235627f7eb2Smrg rename_list_remove_duplicate (gfc_use_rename *list)
7236627f7eb2Smrg {
7237627f7eb2Smrg   gfc_use_rename *seek, *last;
7238627f7eb2Smrg 
7239627f7eb2Smrg   for (; list; list = list->next)
7240627f7eb2Smrg     if (list->op != INTRINSIC_USER && list->op != INTRINSIC_NONE)
7241627f7eb2Smrg       {
7242627f7eb2Smrg 	last = list;
7243627f7eb2Smrg 	for (seek = list->next; seek; seek = last->next)
7244627f7eb2Smrg 	  {
7245627f7eb2Smrg 	    if (list->op == seek->op)
7246627f7eb2Smrg 	      {
7247627f7eb2Smrg 		last->next = seek->next;
7248627f7eb2Smrg 		free (seek);
7249627f7eb2Smrg 	      }
7250627f7eb2Smrg 	    else
7251627f7eb2Smrg 	      last = seek;
7252627f7eb2Smrg 	  }
7253627f7eb2Smrg       }
7254627f7eb2Smrg }
7255627f7eb2Smrg 
7256627f7eb2Smrg 
7257627f7eb2Smrg /* Process all USE directives.  */
7258627f7eb2Smrg 
7259627f7eb2Smrg void
gfc_use_modules(void)7260627f7eb2Smrg gfc_use_modules (void)
7261627f7eb2Smrg {
7262627f7eb2Smrg   gfc_use_list *next, *seek, *last;
7263627f7eb2Smrg 
7264627f7eb2Smrg   for (next = module_list; next; next = next->next)
7265627f7eb2Smrg     {
7266627f7eb2Smrg       bool non_intrinsic = next->non_intrinsic;
7267627f7eb2Smrg       bool intrinsic = next->intrinsic;
7268627f7eb2Smrg       bool neither = !non_intrinsic && !intrinsic;
7269627f7eb2Smrg 
7270627f7eb2Smrg       for (seek = next->next; seek; seek = seek->next)
7271627f7eb2Smrg 	{
7272627f7eb2Smrg 	  if (next->module_name != seek->module_name)
7273627f7eb2Smrg 	    continue;
7274627f7eb2Smrg 
7275627f7eb2Smrg 	  if (seek->non_intrinsic)
7276627f7eb2Smrg 	    non_intrinsic = true;
7277627f7eb2Smrg 	  else if (seek->intrinsic)
7278627f7eb2Smrg 	    intrinsic = true;
7279627f7eb2Smrg 	  else
7280627f7eb2Smrg 	    neither = true;
7281627f7eb2Smrg 	}
7282627f7eb2Smrg 
7283627f7eb2Smrg       if (intrinsic && neither && !non_intrinsic)
7284627f7eb2Smrg 	{
7285627f7eb2Smrg 	  char *filename;
7286627f7eb2Smrg           FILE *fp;
7287627f7eb2Smrg 
7288627f7eb2Smrg 	  filename = XALLOCAVEC (char,
7289627f7eb2Smrg 				 strlen (next->module_name)
7290627f7eb2Smrg 				 + strlen (MODULE_EXTENSION) + 1);
7291627f7eb2Smrg 	  strcpy (filename, next->module_name);
7292627f7eb2Smrg 	  strcat (filename, MODULE_EXTENSION);
7293627f7eb2Smrg 	  fp = gfc_open_included_file (filename, true, true);
7294627f7eb2Smrg 	  if (fp != NULL)
7295627f7eb2Smrg 	    {
7296627f7eb2Smrg 	      non_intrinsic = true;
7297627f7eb2Smrg 	      fclose (fp);
7298627f7eb2Smrg 	    }
7299627f7eb2Smrg 	}
7300627f7eb2Smrg 
7301627f7eb2Smrg       last = next;
7302627f7eb2Smrg       for (seek = next->next; seek; seek = last->next)
7303627f7eb2Smrg 	{
7304627f7eb2Smrg 	  if (next->module_name != seek->module_name)
7305627f7eb2Smrg 	    {
7306627f7eb2Smrg 	      last = seek;
7307627f7eb2Smrg 	      continue;
7308627f7eb2Smrg 	    }
7309627f7eb2Smrg 
7310627f7eb2Smrg 	  if ((!next->intrinsic && !seek->intrinsic)
7311627f7eb2Smrg 	      || (next->intrinsic && seek->intrinsic)
7312627f7eb2Smrg 	      || !non_intrinsic)
7313627f7eb2Smrg 	    {
7314627f7eb2Smrg 	      if (!seek->only_flag)
7315627f7eb2Smrg 		next->only_flag = false;
7316627f7eb2Smrg 	      if (seek->rename)
7317627f7eb2Smrg 		{
7318627f7eb2Smrg 		  gfc_use_rename *r = seek->rename;
7319627f7eb2Smrg 		  while (r->next)
7320627f7eb2Smrg 		    r = r->next;
7321627f7eb2Smrg 		  r->next = next->rename;
7322627f7eb2Smrg 		  next->rename = seek->rename;
7323627f7eb2Smrg 		}
7324627f7eb2Smrg 	      last->next = seek->next;
7325627f7eb2Smrg 	      free (seek);
7326627f7eb2Smrg 	    }
7327627f7eb2Smrg 	  else
7328627f7eb2Smrg 	    last = seek;
7329627f7eb2Smrg 	}
7330627f7eb2Smrg     }
7331627f7eb2Smrg 
7332627f7eb2Smrg   for (; module_list; module_list = next)
7333627f7eb2Smrg     {
7334627f7eb2Smrg       next = module_list->next;
7335627f7eb2Smrg       rename_list_remove_duplicate (module_list->rename);
7336627f7eb2Smrg       gfc_use_module (module_list);
7337627f7eb2Smrg       free (module_list);
7338627f7eb2Smrg     }
7339627f7eb2Smrg   gfc_rename_list = NULL;
7340627f7eb2Smrg }
7341627f7eb2Smrg 
7342627f7eb2Smrg 
7343627f7eb2Smrg void
gfc_free_use_stmts(gfc_use_list * use_stmts)7344627f7eb2Smrg gfc_free_use_stmts (gfc_use_list *use_stmts)
7345627f7eb2Smrg {
7346627f7eb2Smrg   gfc_use_list *next;
7347627f7eb2Smrg   for (; use_stmts; use_stmts = next)
7348627f7eb2Smrg     {
7349627f7eb2Smrg       gfc_use_rename *next_rename;
7350627f7eb2Smrg 
7351627f7eb2Smrg       for (; use_stmts->rename; use_stmts->rename = next_rename)
7352627f7eb2Smrg 	{
7353627f7eb2Smrg 	  next_rename = use_stmts->rename->next;
7354627f7eb2Smrg 	  free (use_stmts->rename);
7355627f7eb2Smrg 	}
7356627f7eb2Smrg       next = use_stmts->next;
7357627f7eb2Smrg       free (use_stmts);
7358627f7eb2Smrg     }
7359627f7eb2Smrg }
7360627f7eb2Smrg 
7361627f7eb2Smrg 
7362627f7eb2Smrg void
gfc_module_init_2(void)7363627f7eb2Smrg gfc_module_init_2 (void)
7364627f7eb2Smrg {
7365627f7eb2Smrg   last_atom = ATOM_LPAREN;
7366627f7eb2Smrg   gfc_rename_list = NULL;
7367627f7eb2Smrg   module_list = NULL;
7368627f7eb2Smrg }
7369627f7eb2Smrg 
7370627f7eb2Smrg 
7371627f7eb2Smrg void
gfc_module_done_2(void)7372627f7eb2Smrg gfc_module_done_2 (void)
7373627f7eb2Smrg {
7374627f7eb2Smrg   free_rename (gfc_rename_list);
7375627f7eb2Smrg   gfc_rename_list = NULL;
7376627f7eb2Smrg }
7377