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 = ¤t_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