OSDN Git Service

* Rework fields used to describe positions of bitfields and
[pf3gnuchains/gcc-fork.git] / gcc / f / com.c
1 /* com.c -- Implementation File (module.c template V1.0)
2    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
3    Free Software Foundation, Inc.
4    Contributed by James Craig Burley.
5
6 This file is part of GNU Fortran.
7
8 GNU Fortran is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU Fortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Fortran; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA.
22
23    Related Modules:
24       None
25
26    Description:
27       Contains compiler-specific functions.
28
29    Modifications:
30 */
31
32 /* Understanding this module means understanding the interface between
33    the g77 front end and the gcc back end (or, perhaps, some other
34    back end).  In here are the functions called by the front end proper
35    to notify whatever back end is in place about certain things, and
36    also the back-end-specific functions.  It's a bear to deal with, so
37    lately I've been trying to simplify things, especially with regard
38    to the gcc-back-end-specific stuff.
39
40    Building expressions generally seems quite easy, but building decls
41    has been challenging and is undergoing revision.  gcc has several
42    kinds of decls:
43
44    TYPE_DECL -- a type (int, float, struct, function, etc.)
45    CONST_DECL -- a constant of some type other than function
46    LABEL_DECL -- a variable or a constant?
47    PARM_DECL -- an argument to a function (a variable that is a dummy)
48    RESULT_DECL -- the return value of a function (a variable)
49    VAR_DECL -- other variable (can hold a ptr-to-function, struct, int, etc.)
50    FUNCTION_DECL -- a function (either the actual function or an extern ref)
51    FIELD_DECL -- a field in a struct or union (goes into types)
52
53    g77 has a set of functions that somewhat parallels the gcc front end
54    when it comes to building decls:
55
56    Internal Function (one we define, not just declare as extern):
57    int yes;
58    yes = suspend_momentary ();
59    if (is_nested) push_f_function_context ();
60    start_function (get_identifier ("function_name"), function_type,
61                    is_nested, is_public);
62    // for each arg, build PARM_DECL and call push_parm_decl (decl) with it;
63    store_parm_decls (is_main_program);
64    ffecom_start_compstmt ();
65    // for stmts and decls inside function, do appropriate things;
66    ffecom_end_compstmt ();
67    finish_function (is_nested);
68    if (is_nested) pop_f_function_context ();
69    if (is_nested) resume_momentary (yes);
70
71    Everything Else:
72    int yes;
73    tree d;
74    tree init;
75    yes = suspend_momentary ();
76    // fill in external, public, static, &c for decl, and
77    // set DECL_INITIAL to error_mark_node if going to initialize
78    // set is_top_level TRUE only if not at top level and decl
79    // must go in top level (i.e. not within current function decl context)
80    d = start_decl (decl, is_top_level);
81    init = ...;  // if have initializer
82    finish_decl (d, init, is_top_level);
83    resume_momentary (yes);
84
85 */
86
87 /* Include files. */
88
89 #include "proj.h"
90 #if FFECOM_targetCURRENT == FFECOM_targetGCC
91 #include "flags.j"
92 #include "rtl.j"
93 #include "toplev.j"
94 #include "tree.j"
95 #include "output.j"  /* Must follow tree.j so TREE_CODE is defined! */
96 #include "convert.j"
97 #include "ggc.j"
98 #endif  /* FFECOM_targetCURRENT == FFECOM_targetGCC */
99
100 #define FFECOM_GCC_INCLUDE 1    /* Enable -I. */
101
102 /* BEGIN stuff from gcc/cccp.c.  */
103
104 /* The following symbols should be autoconfigured:
105         HAVE_FCNTL_H
106         HAVE_STDLIB_H
107         HAVE_SYS_TIME_H
108         HAVE_UNISTD_H
109         STDC_HEADERS
110         TIME_WITH_SYS_TIME
111    In the mean time, we'll get by with approximations based
112    on existing GCC configuration symbols.  */
113
114 #ifdef POSIX
115 # ifndef HAVE_STDLIB_H
116 # define HAVE_STDLIB_H 1
117 # endif
118 # ifndef HAVE_UNISTD_H
119 # define HAVE_UNISTD_H 1
120 # endif
121 # ifndef STDC_HEADERS
122 # define STDC_HEADERS 1
123 # endif
124 #endif /* defined (POSIX) */
125
126 #if defined (POSIX) || (defined (USG) && !defined (VMS))
127 # ifndef HAVE_FCNTL_H
128 # define HAVE_FCNTL_H 1
129 # endif
130 #endif
131
132 #ifndef RLIMIT_STACK
133 # include <time.h>
134 #else
135 # if TIME_WITH_SYS_TIME
136 #  include <sys/time.h>
137 #  include <time.h>
138 # else
139 #  if HAVE_SYS_TIME_H
140 #   include <sys/time.h>
141 #  else
142 #   include <time.h>
143 #  endif
144 # endif
145 # include <sys/resource.h>
146 #endif
147
148 #if HAVE_FCNTL_H
149 # include <fcntl.h>
150 #endif
151
152 /* This defines "errno" properly for VMS, and gives us EACCES. */
153 #include <errno.h>
154
155 #if HAVE_STDLIB_H
156 # include <stdlib.h>
157 #else
158 char *getenv ();
159 #endif
160
161 #if HAVE_UNISTD_H
162 # include <unistd.h>
163 #endif
164
165 /* VMS-specific definitions */
166 #ifdef VMS
167 #include <descrip.h>
168 #define O_RDONLY        0       /* Open arg for Read/Only  */
169 #define O_WRONLY        1       /* Open arg for Write/Only */
170 #define read(fd,buf,size)       VMS_read (fd,buf,size)
171 #define write(fd,buf,size)      VMS_write (fd,buf,size)
172 #define open(fname,mode,prot)   VMS_open (fname,mode,prot)
173 #define fopen(fname,mode)       VMS_fopen (fname,mode)
174 #define freopen(fname,mode,ofile) VMS_freopen (fname,mode,ofile)
175 #define strncat(dst,src,cnt) VMS_strncat (dst,src,cnt)
176 #define fstat(fd,stbuf)         VMS_fstat (fd,stbuf)
177 static int VMS_fstat (), VMS_stat ();
178 static char * VMS_strncat ();
179 static int VMS_read ();
180 static int VMS_write ();
181 static int VMS_open ();
182 static FILE * VMS_fopen ();
183 static FILE * VMS_freopen ();
184 static void hack_vms_include_specification ();
185 typedef struct { unsigned :16, :16, :16; } vms_ino_t;
186 #define ino_t vms_ino_t
187 #define INCLUDE_LEN_FUDGE 10    /* leave room for VMS syntax conversion */
188 #ifdef __GNUC__
189 #define BSTRING                 /* VMS/GCC supplies the bstring routines */
190 #endif /* __GNUC__ */
191 #endif /* VMS */
192
193 #ifndef O_RDONLY
194 #define O_RDONLY 0
195 #endif
196
197 /* END stuff from gcc/cccp.c.  */
198
199 #define FFECOM_DETERMINE_TYPES 1 /* for com.h */
200 #include "com.h"
201 #include "bad.h"
202 #include "bld.h"
203 #include "equiv.h"
204 #include "expr.h"
205 #include "implic.h"
206 #include "info.h"
207 #include "malloc.h"
208 #include "src.h"
209 #include "st.h"
210 #include "storag.h"
211 #include "symbol.h"
212 #include "target.h"
213 #include "top.h"
214 #include "type.h"
215
216 /* Externals defined here.  */
217
218 #if FFECOM_targetCURRENT == FFECOM_targetGCC
219
220 /* ~~gcc/tree.h *should* declare this, because toplev.c and dwarfout.c
221    reference it.  */
222
223 const char * const language_string = "GNU F77";
224
225 /* Stream for reading from the input file.  */
226 FILE *finput;
227
228 /* These definitions parallel those in c-decl.c so that code from that
229    module can be used pretty much as is.  Much of these defs aren't
230    otherwise used, i.e. by g77 code per se, except some of them are used
231    to build some of them that are.  The ones that are global (i.e. not
232    "static") are those that ste.c and such might use (directly
233    or by using com macros that reference them in their definitions).  */
234
235 tree string_type_node;
236
237 /* The rest of these are inventions for g77, though there might be
238    similar things in the C front end.  As they are found, these
239    inventions should be renamed to be canonical.  Note that only
240    the ones currently required to be global are so.  */
241
242 static tree ffecom_tree_fun_type_void;
243
244 tree ffecom_integer_type_node;  /* Abbrev for _tree_type[blah][blah]. */
245 tree ffecom_integer_zero_node;  /* Like *_*_* with g77's integer type. */
246 tree ffecom_integer_one_node;   /* " */
247 tree ffecom_tree_type[FFEINFO_basictype][FFEINFO_kindtype];
248
249 /* _fun_type things are the f2c-specific versions.  For -fno-f2c,
250    just use build_function_type and build_pointer_type on the
251    appropriate _tree_type array element.  */
252
253 static tree ffecom_tree_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
254 static tree ffecom_tree_ptr_to_fun_type[FFEINFO_basictype][FFEINFO_kindtype];
255 static tree ffecom_tree_subr_type;
256 static tree ffecom_tree_ptr_to_subr_type;
257 static tree ffecom_tree_blockdata_type;
258
259 static tree ffecom_tree_xargc_;
260
261 ffecomSymbol ffecom_symbol_null_
262 =
263 {
264   NULL_TREE,
265   NULL_TREE,
266   NULL_TREE,
267   NULL_TREE,
268   false
269 };
270 ffeinfoKindtype ffecom_pointer_kind_ = FFEINFO_basictypeNONE;
271 ffeinfoKindtype ffecom_label_kind_ = FFEINFO_basictypeNONE;
272
273 int ffecom_f2c_typecode_[FFEINFO_basictype][FFEINFO_kindtype];
274 tree ffecom_f2c_integer_type_node;
275 tree ffecom_f2c_ptr_to_integer_type_node;
276 tree ffecom_f2c_address_type_node;
277 tree ffecom_f2c_real_type_node;
278 tree ffecom_f2c_ptr_to_real_type_node;
279 tree ffecom_f2c_doublereal_type_node;
280 tree ffecom_f2c_complex_type_node;
281 tree ffecom_f2c_doublecomplex_type_node;
282 tree ffecom_f2c_longint_type_node;
283 tree ffecom_f2c_logical_type_node;
284 tree ffecom_f2c_flag_type_node;
285 tree ffecom_f2c_ftnlen_type_node;
286 tree ffecom_f2c_ftnlen_zero_node;
287 tree ffecom_f2c_ftnlen_one_node;
288 tree ffecom_f2c_ftnlen_two_node;
289 tree ffecom_f2c_ptr_to_ftnlen_type_node;
290 tree ffecom_f2c_ftnint_type_node;
291 tree ffecom_f2c_ptr_to_ftnint_type_node;
292 #endif  /* FFECOM_targetCURRENT == FFECOM_targetGCC */
293
294 /* Simple definitions and enumerations. */
295
296 #ifndef FFECOM_sizeMAXSTACKITEM
297 #define FFECOM_sizeMAXSTACKITEM 32*1024 /* Keep user-declared things
298                                            larger than this # bytes
299                                            off stack if possible. */
300 #endif
301
302 /* For systems that have large enough stacks, they should define
303    this to 0, and here, for ease of use later on, we just undefine
304    it if it is 0.  */
305
306 #if FFECOM_sizeMAXSTACKITEM == 0
307 #undef FFECOM_sizeMAXSTACKITEM
308 #endif
309
310 typedef enum
311   {
312     FFECOM_rttypeVOID_,
313     FFECOM_rttypeVOIDSTAR_,     /* C's `void *' type. */
314     FFECOM_rttypeFTNINT_,       /* f2c's `ftnint' type. */
315     FFECOM_rttypeINTEGER_,      /* f2c's `integer' type. */
316     FFECOM_rttypeLONGINT_,      /* f2c's `longint' type. */
317     FFECOM_rttypeLOGICAL_,      /* f2c's `logical' type. */
318     FFECOM_rttypeREAL_F2C_,     /* f2c's `real' returned as `double'. */
319     FFECOM_rttypeREAL_GNU_,     /* `real' returned as such. */
320     FFECOM_rttypeCOMPLEX_F2C_,  /* f2c's `complex' returned via 1st arg. */
321     FFECOM_rttypeCOMPLEX_GNU_,  /* f2c's `complex' returned directly. */
322     FFECOM_rttypeDOUBLE_,       /* C's `double' type. */
323     FFECOM_rttypeDOUBLEREAL_,   /* f2c's `doublereal' type. */
324     FFECOM_rttypeDBLCMPLX_F2C_, /* f2c's `doublecomplex' returned via 1st arg. */
325     FFECOM_rttypeDBLCMPLX_GNU_, /* f2c's `doublecomplex' returned directly. */
326     FFECOM_rttypeCHARACTER_,    /* f2c `char *'/`ftnlen' pair. */
327     FFECOM_rttype_
328   } ffecomRttype_;
329
330 /* Internal typedefs. */
331
332 #if FFECOM_targetCURRENT == FFECOM_targetGCC
333 typedef struct _ffecom_concat_list_ ffecomConcatList_;
334 #endif  /* FFECOM_targetCURRENT == FFECOM_targetGCC */
335
336 /* Private include files. */
337
338
339 /* Internal structure definitions. */
340
341 #if FFECOM_targetCURRENT == FFECOM_targetGCC
342 struct _ffecom_concat_list_
343   {
344     ffebld *exprs;
345     int count;
346     int max;
347     ffetargetCharacterSize minlen;
348     ffetargetCharacterSize maxlen;
349   };
350 #endif  /* FFECOM_targetCURRENT == FFECOM_targetGCC */
351
352 /* Static functions (internal). */
353
354 #if FFECOM_targetCURRENT == FFECOM_targetGCC
355 static tree ffecom_arglist_expr_ (const char *argstring, ffebld args);
356 static tree ffecom_widest_expr_type_ (ffebld list);
357 static bool ffecom_overlap_ (tree dest_decl, tree dest_offset,
358                              tree dest_size, tree source_tree,
359                              ffebld source, bool scalar_arg);
360 static bool ffecom_args_overlapping_ (tree dest_tree, ffebld dest,
361                                       tree args, tree callee_commons,
362                                       bool scalar_args);
363 static tree ffecom_build_f2c_string_ (int i, const char *s);
364 static tree ffecom_call_ (tree fn, ffeinfoKindtype kt,
365                           bool is_f2c_complex, tree type,
366                           tree args, tree dest_tree,
367                           ffebld dest, bool *dest_used,
368                           tree callee_commons, bool scalar_args, tree hook);
369 static tree ffecom_call_binop_ (tree fn, ffeinfoKindtype kt,
370                                 bool is_f2c_complex, tree type,
371                                 ffebld left, ffebld right,
372                                 tree dest_tree, ffebld dest,
373                                 bool *dest_used, tree callee_commons,
374                                 bool scalar_args, tree hook);
375 static void ffecom_char_args_x_ (tree *xitem, tree *length,
376                                  ffebld expr, bool with_null);
377 static tree ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy);
378 static tree ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s);
379 static ffecomConcatList_
380   ffecom_concat_list_gather_ (ffecomConcatList_ catlist,
381                               ffebld expr,
382                               ffetargetCharacterSize max);
383 static void ffecom_concat_list_kill_ (ffecomConcatList_ catlist);
384 static ffecomConcatList_ ffecom_concat_list_new_ (ffebld expr,
385                                                 ffetargetCharacterSize max);
386 static void ffecom_debug_kludge_ (tree aggr, const char *aggr_type,
387                                   ffesymbol member, tree member_type,
388                                   ffetargetOffset offset);
389 static void ffecom_do_entry_ (ffesymbol fn, int entrynum);
390 static tree ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
391                           bool *dest_used, bool assignp, bool widenp);
392 static tree ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
393                                     ffebld dest, bool *dest_used);
394 static tree ffecom_expr_power_integer_ (ffebld expr);
395 static void ffecom_expr_transform_ (ffebld expr);
396 static void ffecom_f2c_make_type_ (tree *type, int tcode, const char *name);
397 static void ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
398                                       int code);
399 static ffeglobal ffecom_finish_global_ (ffeglobal global);
400 static ffesymbol ffecom_finish_symbol_transform_ (ffesymbol s);
401 static tree ffecom_get_appended_identifier_ (char us, const char *text);
402 static tree ffecom_get_external_identifier_ (ffesymbol s);
403 static tree ffecom_get_identifier_ (const char *text);
404 static tree ffecom_gen_sfuncdef_ (ffesymbol s,
405                                   ffeinfoBasictype bt,
406                                   ffeinfoKindtype kt);
407 static const char *ffecom_gfrt_args_ (ffecomGfrt ix);
408 static tree ffecom_gfrt_tree_ (ffecomGfrt ix);
409 static tree ffecom_init_zero_ (tree decl);
410 static tree ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
411                                      tree *maybe_tree);
412 static tree ffecom_intrinsic_len_ (ffebld expr);
413 static void ffecom_let_char_ (tree dest_tree,
414                               tree dest_length,
415                               ffetargetCharacterSize dest_size,
416                               ffebld source);
417 static void ffecom_make_gfrt_ (ffecomGfrt ix);
418 static void ffecom_member_phase1_ (ffestorag mst, ffestorag st);
419 static void ffecom_member_phase2_ (ffestorag mst, ffestorag st);
420 static void ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size,
421                                       ffebld source);
422 static void ffecom_push_dummy_decls_ (ffebld dumlist,
423                                       bool stmtfunc);
424 static void ffecom_start_progunit_ (void);
425 static ffesymbol ffecom_sym_transform_ (ffesymbol s);
426 static ffesymbol ffecom_sym_transform_assign_ (ffesymbol s);
427 static void ffecom_transform_common_ (ffesymbol s);
428 static void ffecom_transform_equiv_ (ffestorag st);
429 static tree ffecom_transform_namelist_ (ffesymbol s);
430 static void ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
431                                        tree t);
432 static void ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
433                                        tree *size, tree tree);
434 static tree ffecom_tree_divide_ (tree tree_type, tree left, tree right,
435                                  tree dest_tree, ffebld dest,
436                                  bool *dest_used, tree hook);
437 static tree ffecom_type_localvar_ (ffesymbol s,
438                                    ffeinfoBasictype bt,
439                                    ffeinfoKindtype kt);
440 static tree ffecom_type_namelist_ (void);
441 static tree ffecom_type_vardesc_ (void);
442 static tree ffecom_vardesc_ (ffebld expr);
443 static tree ffecom_vardesc_array_ (ffesymbol s);
444 static tree ffecom_vardesc_dims_ (ffesymbol s);
445 static tree ffecom_convert_narrow_ (tree type, tree expr);
446 static tree ffecom_convert_widen_ (tree type, tree expr);
447 #endif  /* FFECOM_targetCURRENT == FFECOM_targetGCC */
448
449 /* These are static functions that parallel those found in the C front
450    end and thus have the same names.  */
451
452 #if FFECOM_targetCURRENT == FFECOM_targetGCC
453 static tree bison_rule_compstmt_ (void);
454 static void bison_rule_pushlevel_ (void);
455 static void delete_block (tree block);
456 static int duplicate_decls (tree newdecl, tree olddecl);
457 static void finish_decl (tree decl, tree init, bool is_top_level);
458 static void finish_function (int nested);
459 static const char *lang_printable_name (tree decl, int v);
460 static tree lookup_name_current_level (tree name);
461 static struct binding_level *make_binding_level (void);
462 static void pop_f_function_context (void);
463 static void push_f_function_context (void);
464 static void push_parm_decl (tree parm);
465 static tree pushdecl_top_level (tree decl);
466 static int kept_level_p (void);
467 static tree storedecls (tree decls);
468 static void store_parm_decls (int is_main_program);
469 static tree start_decl (tree decl, bool is_top_level);
470 static void start_function (tree name, tree type, int nested, int public);
471 #endif  /* FFECOM_targetCURRENT == FFECOM_targetGCC */
472 #if FFECOM_GCC_INCLUDE
473 static void ffecom_file_ (const char *name);
474 static void ffecom_initialize_char_syntax_ (void);
475 static void ffecom_close_include_ (FILE *f);
476 static int ffecom_decode_include_option_ (char *spec);
477 static FILE *ffecom_open_include_ (char *name, ffewhereLine l,
478                                    ffewhereColumn c);
479 #endif  /* FFECOM_GCC_INCLUDE */
480
481 /* Static objects accessed by functions in this module. */
482
483 static ffesymbol ffecom_primary_entry_ = NULL;
484 static ffesymbol ffecom_nested_entry_ = NULL;
485 static ffeinfoKind ffecom_primary_entry_kind_;
486 static bool ffecom_primary_entry_is_proc_;
487 #if FFECOM_targetCURRENT == FFECOM_targetGCC
488 static tree ffecom_outer_function_decl_;
489 static tree ffecom_previous_function_decl_;
490 static tree ffecom_which_entrypoint_decl_;
491 static tree ffecom_float_zero_ = NULL_TREE;
492 static tree ffecom_float_half_ = NULL_TREE;
493 static tree ffecom_double_zero_ = NULL_TREE;
494 static tree ffecom_double_half_ = NULL_TREE;
495 static tree ffecom_func_result_;/* For functions. */
496 static tree ffecom_func_length_;/* For CHARACTER fns. */
497 static ffebld ffecom_list_blockdata_;
498 static ffebld ffecom_list_common_;
499 static ffebld ffecom_master_arglist_;
500 static ffeinfoBasictype ffecom_master_bt_;
501 static ffeinfoKindtype ffecom_master_kt_;
502 static ffetargetCharacterSize ffecom_master_size_;
503 static int ffecom_num_fns_ = 0;
504 static int ffecom_num_entrypoints_ = 0;
505 static bool ffecom_is_altreturning_ = FALSE;
506 static tree ffecom_multi_type_node_;
507 static tree ffecom_multi_retval_;
508 static tree
509   ffecom_multi_fields_[FFEINFO_basictype][FFEINFO_kindtype];
510 static bool ffecom_member_namelisted_;  /* _member_phase1_ namelisted? */
511 static bool ffecom_doing_entry_ = FALSE;
512 static bool ffecom_transform_only_dummies_ = FALSE;
513 static int ffecom_typesize_pointer_;
514 static int ffecom_typesize_integer1_;
515
516 /* Holds pointer-to-function expressions.  */
517
518 static tree ffecom_gfrt_[FFECOM_gfrt]
519 =
520 {
521 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NULL_TREE,
522 #include "com-rt.def"
523 #undef DEFGFRT
524 };
525
526 /* Holds the external names of the functions.  */
527
528 static const char *ffecom_gfrt_name_[FFECOM_gfrt]
529 =
530 {
531 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) NAME,
532 #include "com-rt.def"
533 #undef DEFGFRT
534 };
535
536 /* Whether the function returns.  */
537
538 static bool ffecom_gfrt_volatile_[FFECOM_gfrt]
539 =
540 {
541 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) VOLATILE,
542 #include "com-rt.def"
543 #undef DEFGFRT
544 };
545
546 /* Whether the function returns type complex.  */
547
548 static bool ffecom_gfrt_complex_[FFECOM_gfrt]
549 =
550 {
551 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) COMPLEX,
552 #include "com-rt.def"
553 #undef DEFGFRT
554 };
555
556 /* Type code for the function return value.  */
557
558 static ffecomRttype_ ffecom_gfrt_type_[FFECOM_gfrt]
559 =
560 {
561 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) TYPE,
562 #include "com-rt.def"
563 #undef DEFGFRT
564 };
565
566 /* String of codes for the function's arguments.  */
567
568 static const char *ffecom_gfrt_argstring_[FFECOM_gfrt]
569 =
570 {
571 #define DEFGFRT(CODE,NAME,TYPE,ARGS,VOLATILE,COMPLEX) ARGS,
572 #include "com-rt.def"
573 #undef DEFGFRT
574 };
575 #endif  /* FFECOM_targetCURRENT == FFECOM_targetGCC */
576
577 /* Internal macros. */
578
579 #if FFECOM_targetCURRENT == FFECOM_targetGCC
580
581 /* We let tm.h override the types used here, to handle trivial differences
582    such as the choice of unsigned int or long unsigned int for size_t.
583    When machines start needing nontrivial differences in the size type,
584    it would be best to do something here to figure out automatically
585    from other information what type to use.  */
586
587 #ifndef SIZE_TYPE
588 #define SIZE_TYPE "long unsigned int"
589 #endif
590
591 #define ffecom_concat_list_count_(catlist) ((catlist).count)
592 #define ffecom_concat_list_expr_(catlist,i) ((catlist).exprs[(i)])
593 #define ffecom_concat_list_maxlen_(catlist) ((catlist).maxlen)
594 #define ffecom_concat_list_minlen_(catlist) ((catlist).minlen)
595
596 #define ffecom_char_args_(i,l,e) ffecom_char_args_x_((i),(l),(e),FALSE)
597 #define ffecom_char_args_with_null_(i,l,e) ffecom_char_args_x_((i),(l),(e),TRUE)
598
599 /* For each binding contour we allocate a binding_level structure
600  * which records the names defined in that contour.
601  * Contours include:
602  *  0) the global one
603  *  1) one for each function definition,
604  *     where internal declarations of the parameters appear.
605  *
606  * The current meaning of a name can be found by searching the levels from
607  * the current one out to the global one.
608  */
609
610 /* Note that the information in the `names' component of the global contour
611    is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers.  */
612
613 struct binding_level
614   {
615     /* A chain of _DECL nodes for all variables, constants, functions,
616        and typedef types.  These are in the reverse of the order supplied.
617      */
618     tree names;
619
620     /* For each level (except not the global one),
621        a chain of BLOCK nodes for all the levels
622        that were entered and exited one level down.  */
623     tree blocks;
624
625     /* The BLOCK node for this level, if one has been preallocated.
626        If 0, the BLOCK is allocated (if needed) when the level is popped.  */
627     tree this_block;
628
629     /* The binding level which this one is contained in (inherits from).  */
630     struct binding_level *level_chain;
631
632     /* 0: no ffecom_prepare_* functions called at this level yet;
633        1: ffecom_prepare* functions called, except not ffecom_prepare_end;
634        2: ffecom_prepare_end called.  */
635     int prep_state;
636   };
637
638 #define NULL_BINDING_LEVEL (struct binding_level *) NULL
639
640 /* The binding level currently in effect.  */
641
642 static struct binding_level *current_binding_level;
643
644 /* A chain of binding_level structures awaiting reuse.  */
645
646 static struct binding_level *free_binding_level;
647
648 /* The outermost binding level, for names of file scope.
649    This is created when the compiler is started and exists
650    through the entire run.  */
651
652 static struct binding_level *global_binding_level;
653
654 /* Binding level structures are initialized by copying this one.  */
655
656 static struct binding_level clear_binding_level
657 =
658 {NULL, NULL, NULL, NULL_BINDING_LEVEL, 0};
659
660 /* Language-dependent contents of an identifier.  */
661
662 struct lang_identifier
663   {
664     struct tree_identifier ignore;
665     tree global_value, local_value, label_value;
666     bool invented;
667   };
668
669 /* Macros for access to language-specific slots in an identifier.  */
670 /* Each of these slots contains a DECL node or null.  */
671
672 /* This represents the value which the identifier has in the
673    file-scope namespace.  */
674 #define IDENTIFIER_GLOBAL_VALUE(NODE)   \
675   (((struct lang_identifier *)(NODE))->global_value)
676 /* This represents the value which the identifier has in the current
677    scope.  */
678 #define IDENTIFIER_LOCAL_VALUE(NODE)    \
679   (((struct lang_identifier *)(NODE))->local_value)
680 /* This represents the value which the identifier has as a label in
681    the current label scope.  */
682 #define IDENTIFIER_LABEL_VALUE(NODE)    \
683   (((struct lang_identifier *)(NODE))->label_value)
684 /* This is nonzero if the identifier was "made up" by g77 code.  */
685 #define IDENTIFIER_INVENTED(NODE)       \
686   (((struct lang_identifier *)(NODE))->invented)
687
688 /* In identifiers, C uses the following fields in a special way:
689    TREE_PUBLIC        to record that there was a previous local extern decl.
690    TREE_USED          to record that such a decl was used.
691    TREE_ADDRESSABLE   to record that the address of such a decl was used.  */
692
693 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
694    that have names.  Here so we can clear out their names' definitions
695    at the end of the function.  */
696
697 static tree named_labels;
698
699 /* A list of LABEL_DECLs from outer contexts that are currently shadowed.  */
700
701 static tree shadowed_labels;
702
703 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
704 \f
705 /* Return the subscript expression, modified to do range-checking.
706
707    `array' is the array to be checked against.
708    `element' is the subscript expression to check.
709    `dim' is the dimension number (starting at 0).
710    `total_dims' is the total number of dimensions (0 for CHARACTER substring).
711 */
712
713 static tree
714 ffecom_subscript_check_ (tree array, tree element, int dim, int total_dims,
715                          char *array_name)
716 {
717   tree low = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
718   tree high = TYPE_MAX_VALUE (TYPE_DOMAIN (array));
719   tree cond;
720   tree die;
721   tree args;
722
723   if (element == error_mark_node)
724     return element;
725
726   if (TREE_TYPE (low) != TREE_TYPE (element))
727     {
728       if (TYPE_PRECISION (TREE_TYPE (low))
729           > TYPE_PRECISION (TREE_TYPE (element)))
730         element = convert (TREE_TYPE (low), element);
731       else
732         {
733           low = convert (TREE_TYPE (element), low);
734           if (high)
735             high = convert (TREE_TYPE (element), high);
736         }
737     }
738
739   element = ffecom_save_tree (element);
740   cond = ffecom_2 (LE_EXPR, integer_type_node,
741                    low,
742                    element);
743   if (high)
744     {
745       cond = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
746                        cond,
747                        ffecom_2 (LE_EXPR, integer_type_node,
748                                  element,
749                                  high));
750     }
751
752   {
753     int len;
754     char *proc;
755     char *var;
756     tree arg3;
757     tree arg2;
758     tree arg1;
759     tree arg4;
760
761     switch (total_dims)
762       {
763       case 0:
764         var = xmalloc (strlen (array_name) + 20);
765         sprintf (&var[0], "%s[%s-substring]",
766                  array_name,
767                  dim ? "end" : "start");
768         len = strlen (var) + 1;
769         break;
770
771       case 1:
772         len = strlen (array_name) + 1;
773         var = array_name;
774         break;
775
776       default:
777         var = xmalloc (strlen (array_name) + 40);
778         sprintf (&var[0], "%s[subscript-%d-of-%d]",
779                  array_name,
780                  dim + 1, total_dims);
781         len = strlen (var) + 1;
782         break;
783       }
784
785     arg1 = build_string (len, var);
786
787     if (total_dims != 1)
788       free (var);
789
790     TREE_TYPE (arg1)
791       = build_type_variant (build_array_type (char_type_node,
792                                               build_range_type
793                                               (integer_type_node,
794                                                integer_one_node,
795                                                build_int_2 (len, 0))),
796                             1, 0);
797     TREE_CONSTANT (arg1) = 1;
798     TREE_STATIC (arg1) = 1;
799     arg1 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg1)),
800                      arg1);
801
802     /* s_rnge adds one to the element to print it, so bias against
803        that -- want to print a faithful *subscript* value.  */
804     arg2 = convert (ffecom_f2c_ftnint_type_node,
805                     ffecom_2 (MINUS_EXPR,
806                               TREE_TYPE (element),
807                               element,
808                               convert (TREE_TYPE (element),
809                                        integer_one_node)));
810
811     proc = xmalloc ((len = strlen (input_filename)
812                      + IDENTIFIER_LENGTH (DECL_NAME (current_function_decl))
813                      + 2));
814
815     sprintf (&proc[0], "%s/%s",
816              input_filename,
817              IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
818     arg3 = build_string (len, proc);
819
820     free (proc);
821
822     TREE_TYPE (arg3)
823       = build_type_variant (build_array_type (char_type_node,
824                                               build_range_type
825                                               (integer_type_node,
826                                                integer_one_node,
827                                                build_int_2 (len, 0))),
828                             1, 0);
829     TREE_CONSTANT (arg3) = 1;
830     TREE_STATIC (arg3) = 1;
831     arg3 = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg3)),
832                      arg3);
833
834     arg4 = convert (ffecom_f2c_ftnint_type_node,
835                     build_int_2 (lineno, 0));
836
837     arg1 = build_tree_list (NULL_TREE, arg1);
838     arg2 = build_tree_list (NULL_TREE, arg2);
839     arg3 = build_tree_list (NULL_TREE, arg3);
840     arg4 = build_tree_list (NULL_TREE, arg4);
841     TREE_CHAIN (arg3) = arg4;
842     TREE_CHAIN (arg2) = arg3;
843     TREE_CHAIN (arg1) = arg2;
844
845     args = arg1;
846   }
847   die = ffecom_call_gfrt (FFECOM_gfrtRANGE,
848                           args, NULL_TREE);
849   TREE_SIDE_EFFECTS (die) = 1;
850
851   element = ffecom_3 (COND_EXPR,
852                       TREE_TYPE (element),
853                       cond,
854                       element,
855                       die);
856
857   return element;
858 }
859
860 /* Return the computed element of an array reference.
861
862    `item' is NULL_TREE, or the transformed pointer to the array.
863    `expr' is the original opARRAYREF expression, which is transformed
864      if `item' is NULL_TREE.
865    `want_ptr' is non-zero if a pointer to the element, instead of
866      the element itself, is to be returned.  */
867
868 static tree
869 ffecom_arrayref_ (tree item, ffebld expr, int want_ptr)
870 {
871   ffebld dims[FFECOM_dimensionsMAX];
872   int i;
873   int total_dims;
874   int flatten = ffe_is_flatten_arrays ();
875   int need_ptr;
876   tree array;
877   tree element;
878   tree tree_type;
879   tree tree_type_x;
880   char *array_name;
881   ffetype type;
882   ffebld list;
883
884   if (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER)
885     array_name = ffesymbol_text (ffebld_symter (ffebld_left (expr)));
886   else
887     array_name = "[expr?]";
888
889   /* Build up ARRAY_REFs in reverse order (since we're column major
890      here in Fortran land). */
891
892   for (i = 0, list = ffebld_right (expr);
893        list != NULL;
894        ++i, list = ffebld_trail (list))
895     {
896       dims[i] = ffebld_head (list);
897       type = ffeinfo_type (ffebld_basictype (dims[i]),
898                            ffebld_kindtype (dims[i]));
899       if (! flatten
900           && ffecom_typesize_pointer_ > ffecom_typesize_integer1_
901           && ffetype_size (type) > ffecom_typesize_integer1_)
902         /* E.g. ARRAY(INDEX), given INTEGER*8 INDEX, on a system with 64-bit
903            pointers and 32-bit integers.  Do the full 64-bit pointer
904            arithmetic, for codes using arrays for nonstandard heap-like
905            work.  */
906         flatten = 1;
907     }
908
909   total_dims = i;
910
911   need_ptr = want_ptr || flatten;
912
913   if (! item)
914     {
915       if (need_ptr)
916         item = ffecom_ptr_to_expr (ffebld_left (expr));
917       else
918         item = ffecom_expr (ffebld_left (expr));
919
920       if (item == error_mark_node)
921         return item;
922
923       if (ffeinfo_where (ffebld_info (expr)) == FFEINFO_whereFLEETING
924           && ! mark_addressable (item))
925         return error_mark_node;
926     }
927
928   if (item == error_mark_node)
929     return item;
930
931   if (need_ptr)
932     {
933       tree min;
934
935       for (--i, array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
936            i >= 0;
937            --i, array = TYPE_MAIN_VARIANT (TREE_TYPE (array)))
938         {
939           min = TYPE_MIN_VALUE (TYPE_DOMAIN (array));
940           element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
941           if (flag_bounds_check)
942             element = ffecom_subscript_check_ (array, element, i, total_dims,
943                                                array_name);
944           if (element == error_mark_node)
945             return element;
946
947           /* Widen integral arithmetic as desired while preserving
948              signedness.  */
949           tree_type = TREE_TYPE (element);
950           tree_type_x = tree_type;
951           if (tree_type
952               && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
953               && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
954             tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
955
956           if (TREE_TYPE (min) != tree_type_x)
957             min = convert (tree_type_x, min);
958           if (TREE_TYPE (element) != tree_type_x)
959             element = convert (tree_type_x, element);
960
961           item = ffecom_2 (PLUS_EXPR,
962                            build_pointer_type (TREE_TYPE (array)),
963                            item,
964                            size_binop (MULT_EXPR,
965                                        size_in_bytes (TREE_TYPE (array)),
966                                        convert (sizetype,
967                                                 fold (build (MINUS_EXPR,
968                                                              tree_type_x,
969                                                              element, min)))));
970         }
971       if (! want_ptr)
972         {
973           item = ffecom_1 (INDIRECT_REF,
974                            TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
975                            item);
976         }
977     }
978   else
979     {
980       for (--i;
981            i >= 0;
982            --i)
983         {
984           array = TYPE_MAIN_VARIANT (TREE_TYPE (item));
985
986           element = ffecom_expr_ (dims[i], NULL, NULL, NULL, FALSE, TRUE);
987           if (flag_bounds_check)
988             element = ffecom_subscript_check_ (array, element, i, total_dims,
989                                                array_name);
990           if (element == error_mark_node)
991             return element;
992
993           /* Widen integral arithmetic as desired while preserving
994              signedness.  */
995           tree_type = TREE_TYPE (element);
996           tree_type_x = tree_type;
997           if (tree_type
998               && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
999               && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
1000             tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
1001
1002           element = convert (tree_type_x, element);
1003
1004           item = ffecom_2 (ARRAY_REF,
1005                            TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item))),
1006                            item,
1007                            element);
1008         }
1009     }
1010
1011   return item;
1012 }
1013
1014 /* This is like gcc's stabilize_reference -- in fact, most of the code
1015    comes from that -- but it handles the situation where the reference
1016    is going to have its subparts picked at, and it shouldn't change
1017    (or trigger extra invocations of functions in the subtrees) due to
1018    this.  save_expr is a bit overzealous, because we don't need the
1019    entire thing calculated and saved like a temp.  So, for DECLs, no
1020    change is needed, because these are stable aggregates, and ARRAY_REF
1021    and such might well be stable too, but for things like calculations,
1022    we do need to calculate a snapshot of a value before picking at it.  */
1023
1024 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1025 static tree
1026 ffecom_stabilize_aggregate_ (tree ref)
1027 {
1028   tree result;
1029   enum tree_code code = TREE_CODE (ref);
1030
1031   switch (code)
1032     {
1033     case VAR_DECL:
1034     case PARM_DECL:
1035     case RESULT_DECL:
1036       /* No action is needed in this case.  */
1037       return ref;
1038
1039     case NOP_EXPR:
1040     case CONVERT_EXPR:
1041     case FLOAT_EXPR:
1042     case FIX_TRUNC_EXPR:
1043     case FIX_FLOOR_EXPR:
1044     case FIX_ROUND_EXPR:
1045     case FIX_CEIL_EXPR:
1046       result = build_nt (code, stabilize_reference (TREE_OPERAND (ref, 0)));
1047       break;
1048
1049     case INDIRECT_REF:
1050       result = build_nt (INDIRECT_REF,
1051                          stabilize_reference_1 (TREE_OPERAND (ref, 0)));
1052       break;
1053
1054     case COMPONENT_REF:
1055       result = build_nt (COMPONENT_REF,
1056                          stabilize_reference (TREE_OPERAND (ref, 0)),
1057                          TREE_OPERAND (ref, 1));
1058       break;
1059
1060     case BIT_FIELD_REF:
1061       result = build_nt (BIT_FIELD_REF,
1062                          stabilize_reference (TREE_OPERAND (ref, 0)),
1063                          stabilize_reference_1 (TREE_OPERAND (ref, 1)),
1064                          stabilize_reference_1 (TREE_OPERAND (ref, 2)));
1065       break;
1066
1067     case ARRAY_REF:
1068       result = build_nt (ARRAY_REF,
1069                          stabilize_reference (TREE_OPERAND (ref, 0)),
1070                          stabilize_reference_1 (TREE_OPERAND (ref, 1)));
1071       break;
1072
1073     case COMPOUND_EXPR:
1074       result = build_nt (COMPOUND_EXPR,
1075                          stabilize_reference_1 (TREE_OPERAND (ref, 0)),
1076                          stabilize_reference (TREE_OPERAND (ref, 1)));
1077       break;
1078
1079     case RTL_EXPR:
1080       result = build1 (INDIRECT_REF, TREE_TYPE (ref),
1081                        save_expr (build1 (ADDR_EXPR,
1082                                           build_pointer_type (TREE_TYPE (ref)),
1083                                           ref)));
1084       break;
1085
1086
1087     default:
1088       return save_expr (ref);
1089
1090     case ERROR_MARK:
1091       return error_mark_node;
1092     }
1093
1094   TREE_TYPE (result) = TREE_TYPE (ref);
1095   TREE_READONLY (result) = TREE_READONLY (ref);
1096   TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
1097   TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
1098
1099   return result;
1100 }
1101 #endif
1102
1103 /* A rip-off of gcc's convert.c convert_to_complex function,
1104    reworked to handle complex implemented as C structures
1105    (RECORD_TYPE with two fields, real and imaginary `r' and `i').  */
1106
1107 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1108 static tree
1109 ffecom_convert_to_complex_ (tree type, tree expr)
1110 {
1111   register enum tree_code form = TREE_CODE (TREE_TYPE (expr));
1112   tree subtype;
1113
1114   assert (TREE_CODE (type) == RECORD_TYPE);
1115
1116   subtype = TREE_TYPE (TYPE_FIELDS (type));
1117   
1118   if (form == REAL_TYPE || form == INTEGER_TYPE || form == ENUMERAL_TYPE)
1119     {
1120       expr = convert (subtype, expr);
1121       return ffecom_2 (COMPLEX_EXPR, type, expr,
1122                        convert (subtype, integer_zero_node));
1123     }
1124
1125   if (form == RECORD_TYPE)
1126     {
1127       tree elt_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr)));
1128       if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype))
1129         return expr;
1130       else
1131         {
1132           expr = save_expr (expr);
1133           return ffecom_2 (COMPLEX_EXPR,
1134                            type,
1135                            convert (subtype,
1136                                     ffecom_1 (REALPART_EXPR,
1137                                               TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1138                                               expr)),
1139                            convert (subtype,
1140                                     ffecom_1 (IMAGPART_EXPR,
1141                                               TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))),
1142                                               expr)));
1143         }
1144     }
1145
1146   if (form == POINTER_TYPE || form == REFERENCE_TYPE)
1147     error ("pointer value used where a complex was expected");
1148   else
1149     error ("aggregate value used where a complex was expected");
1150   
1151   return ffecom_2 (COMPLEX_EXPR, type,
1152                    convert (subtype, integer_zero_node),
1153                    convert (subtype, integer_zero_node));
1154 }
1155 #endif
1156
1157 /* Like gcc's convert(), but crashes if widening might happen.  */
1158
1159 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1160 static tree
1161 ffecom_convert_narrow_ (type, expr)
1162      tree type, expr;
1163 {
1164   register tree e = expr;
1165   register enum tree_code code = TREE_CODE (type);
1166
1167   if (type == TREE_TYPE (e)
1168       || TREE_CODE (e) == ERROR_MARK)
1169     return e;
1170   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1171     return fold (build1 (NOP_EXPR, type, e));
1172   if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1173       || code == ERROR_MARK)
1174     return error_mark_node;
1175   if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1176     {
1177       assert ("void value not ignored as it ought to be" == NULL);
1178       return error_mark_node;
1179     }
1180   assert (code != VOID_TYPE);
1181   if ((code != RECORD_TYPE)
1182       && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1183     assert ("converting COMPLEX to REAL" == NULL);
1184   assert (code != ENUMERAL_TYPE);
1185   if (code == INTEGER_TYPE)
1186     {
1187       assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1188                && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)))
1189               || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1190                   && (TYPE_PRECISION (type)
1191                       == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1192       return fold (convert_to_integer (type, e));
1193     }
1194   if (code == POINTER_TYPE)
1195     {
1196       assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1197       return fold (convert_to_pointer (type, e));
1198     }
1199   if (code == REAL_TYPE)
1200     {
1201       assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1202       assert (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (e)));
1203       return fold (convert_to_real (type, e));
1204     }
1205   if (code == COMPLEX_TYPE)
1206     {
1207       assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1208       assert (TYPE_PRECISION (TREE_TYPE (type)) <= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1209       return fold (convert_to_complex (type, e));
1210     }
1211   if (code == RECORD_TYPE)
1212     {
1213       assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1214       /* Check that at least the first field name agrees.  */
1215       assert (DECL_NAME (TYPE_FIELDS (type))
1216               == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1217       assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1218               <= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1219       if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1220           == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1221         return e;
1222       return fold (ffecom_convert_to_complex_ (type, e));
1223     }
1224
1225   assert ("conversion to non-scalar type requested" == NULL);
1226   return error_mark_node;
1227 }
1228 #endif
1229
1230 /* Like gcc's convert(), but crashes if narrowing might happen.  */
1231
1232 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1233 static tree
1234 ffecom_convert_widen_ (type, expr)
1235      tree type, expr;
1236 {
1237   register tree e = expr;
1238   register enum tree_code code = TREE_CODE (type);
1239
1240   if (type == TREE_TYPE (e)
1241       || TREE_CODE (e) == ERROR_MARK)
1242     return e;
1243   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
1244     return fold (build1 (NOP_EXPR, type, e));
1245   if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
1246       || code == ERROR_MARK)
1247     return error_mark_node;
1248   if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
1249     {
1250       assert ("void value not ignored as it ought to be" == NULL);
1251       return error_mark_node;
1252     }
1253   assert (code != VOID_TYPE);
1254   if ((code != RECORD_TYPE)
1255       && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
1256     assert ("narrowing COMPLEX to REAL" == NULL);
1257   assert (code != ENUMERAL_TYPE);
1258   if (code == INTEGER_TYPE)
1259     {
1260       assert ((TREE_CODE (TREE_TYPE (e)) == INTEGER_TYPE
1261                && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)))
1262               || (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
1263                   && (TYPE_PRECISION (type)
1264                       == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (e))))));
1265       return fold (convert_to_integer (type, e));
1266     }
1267   if (code == POINTER_TYPE)
1268     {
1269       assert (TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE);
1270       return fold (convert_to_pointer (type, e));
1271     }
1272   if (code == REAL_TYPE)
1273     {
1274       assert (TREE_CODE (TREE_TYPE (e)) == REAL_TYPE);
1275       assert (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (e)));
1276       return fold (convert_to_real (type, e));
1277     }
1278   if (code == COMPLEX_TYPE)
1279     {
1280       assert (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE);
1281       assert (TYPE_PRECISION (TREE_TYPE (type)) >= TYPE_PRECISION (TREE_TYPE (TREE_TYPE (e))));
1282       return fold (convert_to_complex (type, e));
1283     }
1284   if (code == RECORD_TYPE)
1285     {
1286       assert (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE);
1287       /* Check that at least the first field name agrees.  */
1288       assert (DECL_NAME (TYPE_FIELDS (type))
1289               == DECL_NAME (TYPE_FIELDS (TREE_TYPE (e))));
1290       assert (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1291               >= TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))));
1292       if (TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (type)))
1293           == TYPE_PRECISION (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e)))))
1294         return e;
1295       return fold (ffecom_convert_to_complex_ (type, e));
1296     }
1297
1298   assert ("conversion to non-scalar type requested" == NULL);
1299   return error_mark_node;
1300 }
1301 #endif
1302
1303 /* Handles making a COMPLEX type, either the standard
1304    (but buggy?) gbe way, or the safer (but less elegant?)
1305    f2c way.  */
1306
1307 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1308 static tree
1309 ffecom_make_complex_type_ (tree subtype)
1310 {
1311   tree type;
1312   tree realfield;
1313   tree imagfield;
1314
1315   if (ffe_is_emulate_complex ())
1316     {
1317       type = make_node (RECORD_TYPE);
1318       realfield = ffecom_decl_field (type, NULL_TREE, "r", subtype);
1319       imagfield = ffecom_decl_field (type, realfield, "i", subtype);
1320       TYPE_FIELDS (type) = realfield;
1321       layout_type (type);
1322     }
1323   else
1324     {
1325       type = make_node (COMPLEX_TYPE);
1326       TREE_TYPE (type) = subtype;
1327       layout_type (type);
1328     }
1329
1330   return type;
1331 }
1332 #endif
1333
1334 /* Chooses either the gbe or the f2c way to build a
1335    complex constant.  */
1336
1337 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1338 static tree
1339 ffecom_build_complex_constant_ (tree type, tree realpart, tree imagpart)
1340 {
1341   tree bothparts;
1342
1343   if (ffe_is_emulate_complex ())
1344     {
1345       bothparts = build_tree_list (TYPE_FIELDS (type), realpart);
1346       TREE_CHAIN (bothparts) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), imagpart);
1347       bothparts = build (CONSTRUCTOR, type, NULL_TREE, bothparts);
1348     }
1349   else
1350     {
1351       bothparts = build_complex (type, realpart, imagpart);
1352     }
1353
1354   return bothparts;
1355 }
1356 #endif
1357
1358 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1359 static tree
1360 ffecom_arglist_expr_ (const char *c, ffebld expr)
1361 {
1362   tree list;
1363   tree *plist = &list;
1364   tree trail = NULL_TREE;       /* Append char length args here. */
1365   tree *ptrail = &trail;
1366   tree length;
1367   ffebld exprh;
1368   tree item;
1369   bool ptr = FALSE;
1370   tree wanted = NULL_TREE;
1371   static char zed[] = "0";
1372
1373   if (c == NULL)
1374     c = &zed[0];
1375
1376   while (expr != NULL)
1377     {
1378       if (*c != '\0')
1379         {
1380           ptr = FALSE;
1381           if (*c == '&')
1382             {
1383               ptr = TRUE;
1384               ++c;
1385             }
1386           switch (*(c++))
1387             {
1388             case '\0':
1389               ptr = TRUE;
1390               wanted = NULL_TREE;
1391               break;
1392
1393             case 'a':
1394               assert (ptr);
1395               wanted = NULL_TREE;
1396               break;
1397
1398             case 'c':
1399               wanted = ffecom_f2c_complex_type_node;
1400               break;
1401
1402             case 'd':
1403               wanted = ffecom_f2c_doublereal_type_node;
1404               break;
1405
1406             case 'e':
1407               wanted = ffecom_f2c_doublecomplex_type_node;
1408               break;
1409
1410             case 'f':
1411               wanted = ffecom_f2c_real_type_node;
1412               break;
1413
1414             case 'i':
1415               wanted = ffecom_f2c_integer_type_node;
1416               break;
1417
1418             case 'j':
1419               wanted = ffecom_f2c_longint_type_node;
1420               break;
1421
1422             default:
1423               assert ("bad argstring code" == NULL);
1424               wanted = NULL_TREE;
1425               break;
1426             }
1427         }
1428
1429       exprh = ffebld_head (expr);
1430       if (exprh == NULL)
1431         wanted = NULL_TREE;
1432
1433       if ((wanted == NULL_TREE)
1434           || (ptr
1435               && (TYPE_MODE
1436                   (ffecom_tree_type[ffeinfo_basictype (ffebld_info (exprh))]
1437                    [ffeinfo_kindtype (ffebld_info (exprh))])
1438                    == TYPE_MODE (wanted))))
1439         *plist
1440           = build_tree_list (NULL_TREE,
1441                              ffecom_arg_ptr_to_expr (exprh,
1442                                                      &length));
1443       else
1444         {
1445           item = ffecom_arg_expr (exprh, &length);
1446           item = ffecom_convert_widen_ (wanted, item);
1447           if (ptr)
1448             {
1449               item = ffecom_1 (ADDR_EXPR,
1450                                build_pointer_type (TREE_TYPE (item)),
1451                                item);
1452             }
1453           *plist
1454             = build_tree_list (NULL_TREE,
1455                                item);
1456         }
1457
1458       plist = &TREE_CHAIN (*plist);
1459       expr = ffebld_trail (expr);
1460       if (length != NULL_TREE)
1461         {
1462           *ptrail = build_tree_list (NULL_TREE, length);
1463           ptrail = &TREE_CHAIN (*ptrail);
1464         }
1465     }
1466
1467   /* We've run out of args in the call; if the implementation expects
1468      more, supply null pointers for them, which the implementation can
1469      check to see if an arg was omitted. */
1470
1471   while (*c != '\0' && *c != '0')
1472     {
1473       if (*c == '&')
1474         ++c;
1475       else
1476         assert ("missing arg to run-time routine!" == NULL);
1477
1478       switch (*(c++))
1479         {
1480         case '\0':
1481         case 'a':
1482         case 'c':
1483         case 'd':
1484         case 'e':
1485         case 'f':
1486         case 'i':
1487         case 'j':
1488           break;
1489
1490         default:
1491           assert ("bad arg string code" == NULL);
1492           break;
1493         }
1494       *plist
1495         = build_tree_list (NULL_TREE,
1496                            null_pointer_node);
1497       plist = &TREE_CHAIN (*plist);
1498     }
1499
1500   *plist = trail;
1501
1502   return list;
1503 }
1504 #endif
1505
1506 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1507 static tree
1508 ffecom_widest_expr_type_ (ffebld list)
1509 {
1510   ffebld item;
1511   ffebld widest = NULL;
1512   ffetype type;
1513   ffetype widest_type = NULL;
1514   tree t;
1515
1516   for (; list != NULL; list = ffebld_trail (list))
1517     {
1518       item = ffebld_head (list);
1519       if (item == NULL)
1520         continue;
1521       if ((widest != NULL)
1522           && (ffeinfo_basictype (ffebld_info (item))
1523               != ffeinfo_basictype (ffebld_info (widest))))
1524         continue;
1525       type = ffeinfo_type (ffeinfo_basictype (ffebld_info (item)),
1526                            ffeinfo_kindtype (ffebld_info (item)));
1527       if ((widest == FFEINFO_kindtypeNONE)
1528           || (ffetype_size (type)
1529               > ffetype_size (widest_type)))
1530         {
1531           widest = item;
1532           widest_type = type;
1533         }
1534     }
1535
1536   assert (widest != NULL);
1537   t = ffecom_tree_type[ffeinfo_basictype (ffebld_info (widest))]
1538     [ffeinfo_kindtype (ffebld_info (widest))];
1539   assert (t != NULL_TREE);
1540   return t;
1541 }
1542 #endif
1543
1544 /* Check whether a partial overlap between two expressions is possible.
1545
1546    Can *starting* to write a portion of expr1 change the value
1547    computed (perhaps already, *partially*) by expr2?
1548
1549    Currently, this is a concern only for a COMPLEX expr1.  But if it
1550    isn't in COMMON or local EQUIVALENCE, since we don't support
1551    aliasing of arguments, it isn't a concern.  */
1552
1553 static bool
1554 ffecom_possible_partial_overlap_ (ffebld expr1, ffebld expr2 ATTRIBUTE_UNUSED)
1555 {
1556   ffesymbol sym;
1557   ffestorag st;
1558
1559   switch (ffebld_op (expr1))
1560     {
1561     case FFEBLD_opSYMTER:
1562       sym = ffebld_symter (expr1);
1563       break;
1564
1565     case FFEBLD_opARRAYREF:
1566       if (ffebld_op (ffebld_left (expr1)) != FFEBLD_opSYMTER)
1567         return FALSE;
1568       sym = ffebld_symter (ffebld_left (expr1));
1569       break;
1570
1571     default:
1572       return FALSE;
1573     }
1574
1575   if (ffesymbol_where (sym) != FFEINFO_whereCOMMON
1576       && (ffesymbol_where (sym) != FFEINFO_whereLOCAL
1577           || ! (st = ffesymbol_storage (sym))
1578           || ! ffestorag_parent (st)))
1579     return FALSE;
1580
1581   /* It's in COMMON or local EQUIVALENCE.  */
1582
1583   return TRUE;
1584 }
1585
1586 /* Check whether dest and source might overlap.  ffebld versions of these
1587    might or might not be passed, will be NULL if not.
1588
1589    The test is really whether source_tree is modifiable and, if modified,
1590    might overlap destination such that the value(s) in the destination might
1591    change before it is finally modified.  dest_* are the canonized
1592    destination itself.  */
1593
1594 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1595 static bool
1596 ffecom_overlap_ (tree dest_decl, tree dest_offset, tree dest_size,
1597                  tree source_tree, ffebld source UNUSED,
1598                  bool scalar_arg)
1599 {
1600   tree source_decl;
1601   tree source_offset;
1602   tree source_size;
1603   tree t;
1604
1605   if (source_tree == NULL_TREE)
1606     return FALSE;
1607
1608   switch (TREE_CODE (source_tree))
1609     {
1610     case ERROR_MARK:
1611     case IDENTIFIER_NODE:
1612     case INTEGER_CST:
1613     case REAL_CST:
1614     case COMPLEX_CST:
1615     case STRING_CST:
1616     case CONST_DECL:
1617     case VAR_DECL:
1618     case RESULT_DECL:
1619     case FIELD_DECL:
1620     case MINUS_EXPR:
1621     case MULT_EXPR:
1622     case TRUNC_DIV_EXPR:
1623     case CEIL_DIV_EXPR:
1624     case FLOOR_DIV_EXPR:
1625     case ROUND_DIV_EXPR:
1626     case TRUNC_MOD_EXPR:
1627     case CEIL_MOD_EXPR:
1628     case FLOOR_MOD_EXPR:
1629     case ROUND_MOD_EXPR:
1630     case RDIV_EXPR:
1631     case EXACT_DIV_EXPR:
1632     case FIX_TRUNC_EXPR:
1633     case FIX_CEIL_EXPR:
1634     case FIX_FLOOR_EXPR:
1635     case FIX_ROUND_EXPR:
1636     case FLOAT_EXPR:
1637     case EXPON_EXPR:
1638     case NEGATE_EXPR:
1639     case MIN_EXPR:
1640     case MAX_EXPR:
1641     case ABS_EXPR:
1642     case FFS_EXPR:
1643     case LSHIFT_EXPR:
1644     case RSHIFT_EXPR:
1645     case LROTATE_EXPR:
1646     case RROTATE_EXPR:
1647     case BIT_IOR_EXPR:
1648     case BIT_XOR_EXPR:
1649     case BIT_AND_EXPR:
1650     case BIT_ANDTC_EXPR:
1651     case BIT_NOT_EXPR:
1652     case TRUTH_ANDIF_EXPR:
1653     case TRUTH_ORIF_EXPR:
1654     case TRUTH_AND_EXPR:
1655     case TRUTH_OR_EXPR:
1656     case TRUTH_XOR_EXPR:
1657     case TRUTH_NOT_EXPR:
1658     case LT_EXPR:
1659     case LE_EXPR:
1660     case GT_EXPR:
1661     case GE_EXPR:
1662     case EQ_EXPR:
1663     case NE_EXPR:
1664     case COMPLEX_EXPR:
1665     case CONJ_EXPR:
1666     case REALPART_EXPR:
1667     case IMAGPART_EXPR:
1668     case LABEL_EXPR:
1669     case COMPONENT_REF:
1670       return FALSE;
1671
1672     case COMPOUND_EXPR:
1673       return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1674                               TREE_OPERAND (source_tree, 1), NULL,
1675                               scalar_arg);
1676
1677     case MODIFY_EXPR:
1678       return ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1679                               TREE_OPERAND (source_tree, 0), NULL,
1680                               scalar_arg);
1681
1682     case CONVERT_EXPR:
1683     case NOP_EXPR:
1684     case NON_LVALUE_EXPR:
1685     case PLUS_EXPR:
1686       if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1687         return TRUE;
1688
1689       ffecom_tree_canonize_ptr_ (&source_decl, &source_offset,
1690                                  source_tree);
1691       source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1692       break;
1693
1694     case COND_EXPR:
1695       return
1696         ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1697                          TREE_OPERAND (source_tree, 1), NULL,
1698                          scalar_arg)
1699           || ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1700                               TREE_OPERAND (source_tree, 2), NULL,
1701                               scalar_arg);
1702
1703
1704     case ADDR_EXPR:
1705       ffecom_tree_canonize_ref_ (&source_decl, &source_offset,
1706                                  &source_size,
1707                                  TREE_OPERAND (source_tree, 0));
1708       break;
1709
1710     case PARM_DECL:
1711       if (TREE_CODE (TREE_TYPE (source_tree)) != POINTER_TYPE)
1712         return TRUE;
1713
1714       source_decl = source_tree;
1715       source_offset = size_zero_node;
1716       source_size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (source_tree)));
1717       break;
1718
1719     case SAVE_EXPR:
1720     case REFERENCE_EXPR:
1721     case PREDECREMENT_EXPR:
1722     case PREINCREMENT_EXPR:
1723     case POSTDECREMENT_EXPR:
1724     case POSTINCREMENT_EXPR:
1725     case INDIRECT_REF:
1726     case ARRAY_REF:
1727     case CALL_EXPR:
1728     default:
1729       return TRUE;
1730     }
1731
1732   /* Come here when source_decl, source_offset, and source_size filled
1733      in appropriately.  */
1734
1735   if (source_decl == NULL_TREE)
1736     return FALSE;               /* No decl involved, so no overlap. */
1737
1738   if (source_decl != dest_decl)
1739     return FALSE;               /* Different decl, no overlap. */
1740
1741   if (TREE_CODE (dest_size) == ERROR_MARK)
1742     return TRUE;                /* Assignment into entire assumed-size
1743                                    array?  Shouldn't happen.... */
1744
1745   t = ffecom_2 (LE_EXPR, integer_type_node,
1746                 ffecom_2 (PLUS_EXPR, TREE_TYPE (dest_offset),
1747                           dest_offset,
1748                           convert (TREE_TYPE (dest_offset),
1749                                    dest_size)),
1750                 convert (TREE_TYPE (dest_offset),
1751                          source_offset));
1752
1753   if (integer_onep (t))
1754     return FALSE;               /* Destination precedes source. */
1755
1756   if (!scalar_arg
1757       || (source_size == NULL_TREE)
1758       || (TREE_CODE (source_size) == ERROR_MARK)
1759       || integer_zerop (source_size))
1760     return TRUE;                /* No way to tell if dest follows source. */
1761
1762   t = ffecom_2 (LE_EXPR, integer_type_node,
1763                 ffecom_2 (PLUS_EXPR, TREE_TYPE (source_offset),
1764                           source_offset,
1765                           convert (TREE_TYPE (source_offset),
1766                                    source_size)),
1767                 convert (TREE_TYPE (source_offset),
1768                          dest_offset));
1769
1770   if (integer_onep (t))
1771     return FALSE;               /* Destination follows source. */
1772
1773   return TRUE;          /* Destination and source overlap. */
1774 }
1775 #endif
1776
1777 /* Check whether dest might overlap any of a list of arguments or is
1778    in a COMMON area the callee might know about (and thus modify).  */
1779
1780 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1781 static bool
1782 ffecom_args_overlapping_ (tree dest_tree, ffebld dest UNUSED,
1783                           tree args, tree callee_commons,
1784                           bool scalar_args)
1785 {
1786   tree arg;
1787   tree dest_decl;
1788   tree dest_offset;
1789   tree dest_size;
1790
1791   ffecom_tree_canonize_ref_ (&dest_decl, &dest_offset, &dest_size,
1792                              dest_tree);
1793
1794   if (dest_decl == NULL_TREE)
1795     return FALSE;               /* Seems unlikely! */
1796
1797   /* If the decl cannot be determined reliably, or if its in COMMON
1798      and the callee isn't known to not futz with COMMON via other
1799      means, overlap might happen.  */
1800
1801   if ((TREE_CODE (dest_decl) == ERROR_MARK)
1802       || ((callee_commons != NULL_TREE)
1803           && TREE_PUBLIC (dest_decl)))
1804     return TRUE;
1805
1806   for (; args != NULL_TREE; args = TREE_CHAIN (args))
1807     {
1808       if (((arg = TREE_VALUE (args)) != NULL_TREE)
1809           && ffecom_overlap_ (dest_decl, dest_offset, dest_size,
1810                               arg, NULL, scalar_args))
1811         return TRUE;
1812     }
1813
1814   return FALSE;
1815 }
1816 #endif
1817
1818 /* Build a string for a variable name as used by NAMELIST.  This means that
1819    if we're using the f2c library, we build an uppercase string, since
1820    f2c does this.  */
1821
1822 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1823 static tree
1824 ffecom_build_f2c_string_ (int i, const char *s)
1825 {
1826   if (!ffe_is_f2c_library ())
1827     return build_string (i, s);
1828
1829   {
1830     char *tmp;
1831     const char *p;
1832     char *q;
1833     char space[34];
1834     tree t;
1835
1836     if (((size_t) i) > ARRAY_SIZE (space))
1837       tmp = malloc_new_ks (malloc_pool_image (), "f2c_string", i);
1838     else
1839       tmp = &space[0];
1840
1841     for (p = s, q = tmp; *p != '\0'; ++p, ++q)
1842       *q = ffesrc_toupper (*p);
1843     *q = '\0';
1844
1845     t = build_string (i, tmp);
1846
1847     if (((size_t) i) > ARRAY_SIZE (space))
1848       malloc_kill_ks (malloc_pool_image (), tmp, i);
1849
1850     return t;
1851   }
1852 }
1853
1854 #endif
1855 /* Returns CALL_EXPR or equivalent with given type (pass NULL_TREE for
1856    type to just get whatever the function returns), handling the
1857    f2c value-returning convention, if required, by prepending
1858    to the arglist a pointer to a temporary to receive the return value.  */
1859
1860 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1861 static tree
1862 ffecom_call_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1863               tree type, tree args, tree dest_tree,
1864               ffebld dest, bool *dest_used, tree callee_commons,
1865               bool scalar_args, tree hook)
1866 {
1867   tree item;
1868   tree tempvar;
1869
1870   if (dest_used != NULL)
1871     *dest_used = FALSE;
1872
1873   if (is_f2c_complex)
1874     {
1875       if ((dest_used == NULL)
1876           || (dest == NULL)
1877           || (ffeinfo_basictype (ffebld_info (dest))
1878               != FFEINFO_basictypeCOMPLEX)
1879           || (ffeinfo_kindtype (ffebld_info (dest)) != kt)
1880           || ((type != NULL_TREE) && (TREE_TYPE (dest_tree) != type))
1881           || ffecom_args_overlapping_ (dest_tree, dest, args,
1882                                        callee_commons,
1883                                        scalar_args))
1884         {
1885 #ifdef HOHO
1886           tempvar = ffecom_make_tempvar (ffecom_tree_type
1887                                          [FFEINFO_basictypeCOMPLEX][kt],
1888                                          FFETARGET_charactersizeNONE,
1889                                          -1);
1890 #else
1891           tempvar = hook;
1892           assert (tempvar);
1893 #endif
1894         }
1895       else
1896         {
1897           *dest_used = TRUE;
1898           tempvar = dest_tree;
1899           type = NULL_TREE;
1900         }
1901
1902       item
1903         = build_tree_list (NULL_TREE,
1904                            ffecom_1 (ADDR_EXPR,
1905                                      build_pointer_type (TREE_TYPE (tempvar)),
1906                                      tempvar));
1907       TREE_CHAIN (item) = args;
1908
1909       item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1910                         item, NULL_TREE);
1911
1912       if (tempvar != dest_tree)
1913         item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item, tempvar);
1914     }
1915   else
1916     item = ffecom_3s (CALL_EXPR, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn,
1917                       args, NULL_TREE);
1918
1919   if ((type != NULL_TREE) && (TREE_TYPE (item) != type))
1920     item = ffecom_convert_narrow_ (type, item);
1921
1922   return item;
1923 }
1924 #endif
1925
1926 /* Given two arguments, transform them and make a call to the given
1927    function via ffecom_call_.  */
1928
1929 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1930 static tree
1931 ffecom_call_binop_ (tree fn, ffeinfoKindtype kt, bool is_f2c_complex,
1932                     tree type, ffebld left, ffebld right,
1933                     tree dest_tree, ffebld dest, bool *dest_used,
1934                     tree callee_commons, bool scalar_args, tree hook)
1935 {
1936   tree left_tree;
1937   tree right_tree;
1938   tree left_length;
1939   tree right_length;
1940
1941   left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
1942   right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
1943
1944   left_tree = build_tree_list (NULL_TREE, left_tree);
1945   right_tree = build_tree_list (NULL_TREE, right_tree);
1946   TREE_CHAIN (left_tree) = right_tree;
1947
1948   if (left_length != NULL_TREE)
1949     {
1950       left_length = build_tree_list (NULL_TREE, left_length);
1951       TREE_CHAIN (right_tree) = left_length;
1952     }
1953
1954   if (right_length != NULL_TREE)
1955     {
1956       right_length = build_tree_list (NULL_TREE, right_length);
1957       if (left_length != NULL_TREE)
1958         TREE_CHAIN (left_length) = right_length;
1959       else
1960         TREE_CHAIN (right_tree) = right_length;
1961     }
1962
1963   return ffecom_call_ (fn, kt, is_f2c_complex, type, left_tree,
1964                        dest_tree, dest, dest_used, callee_commons,
1965                        scalar_args, hook);
1966 }
1967 #endif
1968
1969 /* Return ptr/length args for char subexpression
1970
1971    Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
1972    subexpressions by constructing the appropriate trees for the ptr-to-
1973    character-text and length-of-character-text arguments in a calling
1974    sequence.
1975
1976    Note that if with_null is TRUE, and the expression is an opCONTER,
1977    a null byte is appended to the string.  */
1978
1979 #if FFECOM_targetCURRENT == FFECOM_targetGCC
1980 static void
1981 ffecom_char_args_x_ (tree *xitem, tree *length, ffebld expr, bool with_null)
1982 {
1983   tree item;
1984   tree high;
1985   ffetargetCharacter1 val;
1986   ffetargetCharacterSize newlen;
1987
1988   switch (ffebld_op (expr))
1989     {
1990     case FFEBLD_opCONTER:
1991       val = ffebld_constant_character1 (ffebld_conter (expr));
1992       newlen = ffetarget_length_character1 (val);
1993       if (with_null)
1994         {
1995           /* Begin FFETARGET-NULL-KLUDGE.  */
1996           if (newlen != 0)
1997             ++newlen;
1998         }
1999       *length = build_int_2 (newlen, 0);
2000       TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2001       high = build_int_2 (newlen, 0);
2002       TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
2003       item = build_string (newlen,
2004                            ffetarget_text_character1 (val));
2005       /* End FFETARGET-NULL-KLUDGE.  */
2006       TREE_TYPE (item)
2007         = build_type_variant
2008           (build_array_type
2009            (char_type_node,
2010             build_range_type
2011             (ffecom_f2c_ftnlen_type_node,
2012              ffecom_f2c_ftnlen_one_node,
2013              high)),
2014            1, 0);
2015       TREE_CONSTANT (item) = 1;
2016       TREE_STATIC (item) = 1;
2017       item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
2018                        item);
2019       break;
2020
2021     case FFEBLD_opSYMTER:
2022       {
2023         ffesymbol s = ffebld_symter (expr);
2024
2025         item = ffesymbol_hook (s).decl_tree;
2026         if (item == NULL_TREE)
2027           {
2028             s = ffecom_sym_transform_ (s);
2029             item = ffesymbol_hook (s).decl_tree;
2030           }
2031         if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
2032           {
2033             if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
2034               *length = ffesymbol_hook (s).length_tree;
2035             else
2036               {
2037                 *length = build_int_2 (ffesymbol_size (s), 0);
2038                 TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2039               }
2040           }
2041         else if (item == error_mark_node)
2042           *length = error_mark_node;
2043         else
2044           /* FFEINFO_kindFUNCTION.  */
2045           *length = NULL_TREE;
2046         if (!ffesymbol_hook (s).addr
2047             && (item != error_mark_node))
2048           item = ffecom_1 (ADDR_EXPR,
2049                            build_pointer_type (TREE_TYPE (item)),
2050                            item);
2051       }
2052       break;
2053
2054     case FFEBLD_opARRAYREF:
2055       {
2056         ffecom_char_args_ (&item, length, ffebld_left (expr));
2057
2058         if (item == error_mark_node || *length == error_mark_node)
2059           {
2060             item = *length = error_mark_node;
2061             break;
2062           }
2063
2064         item = ffecom_arrayref_ (item, expr, 1);
2065       }
2066       break;
2067
2068     case FFEBLD_opSUBSTR:
2069       {
2070         ffebld start;
2071         ffebld end;
2072         ffebld thing = ffebld_right (expr);
2073         tree start_tree;
2074         tree end_tree;
2075         char *char_name;
2076         ffebld left_symter;
2077         tree array;
2078
2079         assert (ffebld_op (thing) == FFEBLD_opITEM);
2080         start = ffebld_head (thing);
2081         thing = ffebld_trail (thing);
2082         assert (ffebld_trail (thing) == NULL);
2083         end = ffebld_head (thing);
2084
2085         /* Determine name for pretty-printing range-check errors.  */
2086         for (left_symter = ffebld_left (expr);
2087              left_symter && ffebld_op (left_symter) == FFEBLD_opARRAYREF;
2088              left_symter = ffebld_left (left_symter))
2089           ;
2090         if (ffebld_op (left_symter) == FFEBLD_opSYMTER)
2091           char_name = ffesymbol_text (ffebld_symter (left_symter));
2092         else
2093           char_name = "[expr?]";
2094
2095         ffecom_char_args_ (&item, length, ffebld_left (expr));
2096
2097         if (item == error_mark_node || *length == error_mark_node)
2098           {
2099             item = *length = error_mark_node;
2100             break;
2101           }
2102
2103         array = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item)));
2104
2105         /* ~~~~Handle INTEGER*8 start/end, a la FFEBLD_opARRAYREF.  */
2106
2107         if (start == NULL)
2108           {
2109             if (end == NULL)
2110               ;
2111             else
2112               {
2113                 end_tree = ffecom_expr (end);
2114                 if (flag_bounds_check)
2115                   end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2116                                                       char_name);
2117                 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2118                                     end_tree);
2119
2120                 if (end_tree == error_mark_node)
2121                   {
2122                     item = *length = error_mark_node;
2123                     break;
2124                   }
2125
2126                 *length = end_tree;
2127               }
2128           }
2129         else
2130           {
2131             start_tree = ffecom_expr (start);
2132             if (flag_bounds_check)
2133               start_tree = ffecom_subscript_check_ (array, start_tree, 0, 0,
2134                                                     char_name);
2135             start_tree = convert (ffecom_f2c_ftnlen_type_node,
2136                                   start_tree);
2137
2138             if (start_tree == error_mark_node)
2139               {
2140                 item = *length = error_mark_node;
2141                 break;
2142               }
2143
2144             start_tree = ffecom_save_tree (start_tree);
2145
2146             item = ffecom_2 (PLUS_EXPR, TREE_TYPE (item),
2147                              item,
2148                              ffecom_2 (MINUS_EXPR,
2149                                        TREE_TYPE (start_tree),
2150                                        start_tree,
2151                                        ffecom_f2c_ftnlen_one_node));
2152
2153             if (end == NULL)
2154               {
2155                 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2156                                     ffecom_f2c_ftnlen_one_node,
2157                                     ffecom_2 (MINUS_EXPR,
2158                                               ffecom_f2c_ftnlen_type_node,
2159                                               *length,
2160                                               start_tree));
2161               }
2162             else
2163               {
2164                 end_tree = ffecom_expr (end);
2165                 if (flag_bounds_check)
2166                   end_tree = ffecom_subscript_check_ (array, end_tree, 1, 0,
2167                                                       char_name);
2168                 end_tree = convert (ffecom_f2c_ftnlen_type_node,
2169                                     end_tree);
2170
2171                 if (end_tree == error_mark_node)
2172                   {
2173                     item = *length = error_mark_node;
2174                     break;
2175                   }
2176
2177                 *length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
2178                                     ffecom_f2c_ftnlen_one_node,
2179                                     ffecom_2 (MINUS_EXPR,
2180                                               ffecom_f2c_ftnlen_type_node,
2181                                               end_tree, start_tree));
2182               }
2183           }
2184       }
2185       break;
2186
2187     case FFEBLD_opFUNCREF:
2188       {
2189         ffesymbol s = ffebld_symter (ffebld_left (expr));
2190         tree tempvar;
2191         tree args;
2192         ffetargetCharacterSize size = ffeinfo_size (ffebld_info (expr));
2193         ffecomGfrt ix;
2194
2195         if (size == FFETARGET_charactersizeNONE)
2196           /* ~~Kludge alert!  This should someday be fixed. */
2197           size = 24;
2198
2199         *length = build_int_2 (size, 0);
2200         TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2201
2202         if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
2203             == FFEINFO_whereINTRINSIC)
2204           {
2205             if (size == 1)
2206               {
2207                 /* Invocation of an intrinsic returning CHARACTER*1.  */
2208                 item = ffecom_expr_intrinsic_ (expr, NULL_TREE,
2209                                                NULL, NULL);
2210                 break;
2211               }
2212             ix = ffeintrin_gfrt_direct (ffebld_symter_implementation (ffebld_left (expr)));
2213             assert (ix != FFECOM_gfrt);
2214             item = ffecom_gfrt_tree_ (ix);
2215           }
2216         else
2217           {
2218             ix = FFECOM_gfrt;
2219             item = ffesymbol_hook (s).decl_tree;
2220             if (item == NULL_TREE)
2221               {
2222                 s = ffecom_sym_transform_ (s);
2223                 item = ffesymbol_hook (s).decl_tree;
2224               }
2225             if (item == error_mark_node)
2226               {
2227                 item = *length = error_mark_node;
2228                 break;
2229               }
2230
2231             if (!ffesymbol_hook (s).addr)
2232               item = ffecom_1_fn (item);
2233           }
2234
2235 #ifdef HOHO
2236         tempvar = ffecom_push_tempvar (char_type_node, size, -1, TRUE);
2237 #else
2238         tempvar = ffebld_nonter_hook (expr);
2239         assert (tempvar);
2240 #endif
2241         tempvar = ffecom_1 (ADDR_EXPR,
2242                             build_pointer_type (TREE_TYPE (tempvar)),
2243                             tempvar);
2244
2245         args = build_tree_list (NULL_TREE, tempvar);
2246
2247         if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)       /* Sfunc args by value. */
2248           TREE_CHAIN (args) = ffecom_list_expr (ffebld_right (expr));
2249         else
2250           {
2251             TREE_CHAIN (args) = build_tree_list (NULL_TREE, *length);
2252             if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
2253               {
2254                 TREE_CHAIN (TREE_CHAIN (args))
2255                   = ffecom_arglist_expr_ (ffecom_gfrt_args_ (ix),
2256                                           ffebld_right (expr));
2257               }
2258             else
2259               {
2260                 TREE_CHAIN (TREE_CHAIN (args))
2261                   = ffecom_list_ptr_to_expr (ffebld_right (expr));
2262               }
2263           }
2264
2265         item = ffecom_3s (CALL_EXPR,
2266                           TREE_TYPE (TREE_TYPE (TREE_TYPE (item))),
2267                           item, args, NULL_TREE);
2268         item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), item,
2269                          tempvar);
2270       }
2271       break;
2272
2273     case FFEBLD_opCONVERT:
2274
2275       ffecom_char_args_ (&item, length, ffebld_left (expr));
2276
2277       if (item == error_mark_node || *length == error_mark_node)
2278         {
2279           item = *length = error_mark_node;
2280           break;
2281         }
2282
2283       if ((ffebld_size_known (ffebld_left (expr))
2284            == FFETARGET_charactersizeNONE)
2285           || (ffebld_size_known (ffebld_left (expr)) < (ffebld_size (expr))))
2286         {                       /* Possible blank-padding needed, copy into
2287                                    temporary. */
2288           tree tempvar;
2289           tree args;
2290           tree newlen;
2291
2292 #ifdef HOHO
2293           tempvar = ffecom_make_tempvar (char_type_node,
2294                                          ffebld_size (expr), -1);
2295 #else
2296           tempvar = ffebld_nonter_hook (expr);
2297           assert (tempvar);
2298 #endif
2299           tempvar = ffecom_1 (ADDR_EXPR,
2300                               build_pointer_type (TREE_TYPE (tempvar)),
2301                               tempvar);
2302
2303           newlen = build_int_2 (ffebld_size (expr), 0);
2304           TREE_TYPE (newlen) = ffecom_f2c_ftnlen_type_node;
2305
2306           args = build_tree_list (NULL_TREE, tempvar);
2307           TREE_CHAIN (args) = build_tree_list (NULL_TREE, item);
2308           TREE_CHAIN (TREE_CHAIN (args)) = build_tree_list (NULL_TREE, newlen);
2309           TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (args)))
2310             = build_tree_list (NULL_TREE, *length);
2311
2312           item = ffecom_call_gfrt (FFECOM_gfrtCOPY, args, NULL_TREE);
2313           TREE_SIDE_EFFECTS (item) = 1;
2314           item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar), fold (item),
2315                            tempvar);
2316           *length = newlen;
2317         }
2318       else
2319         {                       /* Just truncate the length. */
2320           *length = build_int_2 (ffebld_size (expr), 0);
2321           TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
2322         }
2323       break;
2324
2325     default:
2326       assert ("bad op for single char arg expr" == NULL);
2327       item = NULL_TREE;
2328       break;
2329     }
2330
2331   *xitem = item;
2332 }
2333 #endif
2334
2335 /* Check the size of the type to be sure it doesn't overflow the
2336    "portable" capacities of the compiler back end.  `dummy' types
2337    can generally overflow the normal sizes as long as the computations
2338    themselves don't overflow.  A particular target of the back end
2339    must still enforce its size requirements, though, and the back
2340    end takes care of this in stor-layout.c.  */
2341
2342 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2343 static tree
2344 ffecom_check_size_overflow_ (ffesymbol s, tree type, bool dummy)
2345 {
2346   if (TREE_CODE (type) == ERROR_MARK)
2347     return type;
2348
2349   if (TYPE_SIZE (type) == NULL_TREE)
2350     return type;
2351
2352   if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
2353     return type;
2354
2355   if ((tree_int_cst_sgn (TYPE_SIZE (type)) < 0)
2356       || (!dummy && (((TREE_INT_CST_HIGH (TYPE_SIZE (type)) != 0))
2357                      || TREE_OVERFLOW (TYPE_SIZE (type)))))
2358     {
2359       ffebad_start (FFEBAD_ARRAY_LARGE);
2360       ffebad_string (ffesymbol_text (s));
2361       ffebad_here (0, ffesymbol_where_line (s), ffesymbol_where_column (s));
2362       ffebad_finish ();
2363
2364       return error_mark_node;
2365     }
2366
2367   return type;
2368 }
2369 #endif
2370
2371 /* Builds a length argument (PARM_DECL).  Also wraps type in an array type
2372    where the dimension info is (1:size) where <size> is ffesymbol_size(s) if
2373    known, length_arg if not known (FFETARGET_charactersizeNONE).  */
2374
2375 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2376 static tree
2377 ffecom_char_enhance_arg_ (tree *xtype, ffesymbol s)
2378 {
2379   ffetargetCharacterSize sz = ffesymbol_size (s);
2380   tree highval;
2381   tree tlen;
2382   tree type = *xtype;
2383
2384   if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
2385     tlen = NULL_TREE;           /* A statement function, no length passed. */
2386   else
2387     {
2388       if (ffesymbol_where (s) == FFEINFO_whereDUMMY)
2389         tlen = ffecom_get_invented_identifier ("__g77_length_%s",
2390                                                ffesymbol_text (s));
2391       else
2392         tlen = ffecom_get_invented_identifier ("__g77_%s", "length");
2393       tlen = build_decl (PARM_DECL, tlen, ffecom_f2c_ftnlen_type_node);
2394 #if BUILT_FOR_270
2395       DECL_ARTIFICIAL (tlen) = 1;
2396 #endif
2397     }
2398
2399   if (sz == FFETARGET_charactersizeNONE)
2400     {
2401       assert (tlen != NULL_TREE);
2402       highval = variable_size (tlen);
2403     }
2404   else
2405     {
2406       highval = build_int_2 (sz, 0);
2407       TREE_TYPE (highval) = ffecom_f2c_ftnlen_type_node;
2408     }
2409
2410   type = build_array_type (type,
2411                            build_range_type (ffecom_f2c_ftnlen_type_node,
2412                                              ffecom_f2c_ftnlen_one_node,
2413                                              highval));
2414
2415   *xtype = type;
2416   return tlen;
2417 }
2418
2419 #endif
2420 /* ffecom_concat_list_gather_ -- Gather list of concatenated string exprs
2421
2422    ffecomConcatList_ catlist;
2423    ffebld expr;  // expr of CHARACTER basictype.
2424    ffetargetCharacterSize max;  // max chars to gather or _...NONE if no max
2425    catlist = ffecom_concat_list_gather_(catlist,expr,max);
2426
2427    Scans expr for character subexpressions, updates and returns catlist
2428    accordingly.  */
2429
2430 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2431 static ffecomConcatList_
2432 ffecom_concat_list_gather_ (ffecomConcatList_ catlist, ffebld expr,
2433                             ffetargetCharacterSize max)
2434 {
2435   ffetargetCharacterSize sz;
2436
2437 recurse:                        /* :::::::::::::::::::: */
2438
2439   if (expr == NULL)
2440     return catlist;
2441
2442   if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen >= max))
2443     return catlist;             /* Don't append any more items. */
2444
2445   switch (ffebld_op (expr))
2446     {
2447     case FFEBLD_opCONTER:
2448     case FFEBLD_opSYMTER:
2449     case FFEBLD_opARRAYREF:
2450     case FFEBLD_opFUNCREF:
2451     case FFEBLD_opSUBSTR:
2452     case FFEBLD_opCONVERT:      /* Callers should strip this off beforehand
2453                                    if they don't need to preserve it. */
2454       if (catlist.count == catlist.max)
2455         {                       /* Make a (larger) list. */
2456           ffebld *newx;
2457           int newmax;
2458
2459           newmax = (catlist.max == 0) ? 8 : catlist.max * 2;
2460           newx = malloc_new_ks (malloc_pool_image (), "catlist",
2461                                 newmax * sizeof (newx[0]));
2462           if (catlist.max != 0)
2463             {
2464               memcpy (newx, catlist.exprs, catlist.max * sizeof (newx[0]));
2465               malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2466                               catlist.max * sizeof (newx[0]));
2467             }
2468           catlist.max = newmax;
2469           catlist.exprs = newx;
2470         }
2471       if ((sz = ffebld_size_known (expr)) != FFETARGET_charactersizeNONE)
2472         catlist.minlen += sz;
2473       else
2474         ++catlist.minlen;       /* Not true for F90; can be 0 length. */
2475       if ((sz = ffebld_size_max (expr)) == FFETARGET_charactersizeNONE)
2476         catlist.maxlen = sz;
2477       else
2478         catlist.maxlen += sz;
2479       if ((max != FFETARGET_charactersizeNONE) && (catlist.minlen > max))
2480         {                       /* This item overlaps (or is beyond) the end
2481                                    of the destination. */
2482           switch (ffebld_op (expr))
2483             {
2484             case FFEBLD_opCONTER:
2485             case FFEBLD_opSYMTER:
2486             case FFEBLD_opARRAYREF:
2487             case FFEBLD_opFUNCREF:
2488             case FFEBLD_opSUBSTR:
2489               /* ~~Do useful truncations here. */
2490               break;
2491
2492             default:
2493               assert ("op changed or inconsistent switches!" == NULL);
2494               break;
2495             }
2496         }
2497       catlist.exprs[catlist.count++] = expr;
2498       return catlist;
2499
2500     case FFEBLD_opPAREN:
2501       expr = ffebld_left (expr);
2502       goto recurse;             /* :::::::::::::::::::: */
2503
2504     case FFEBLD_opCONCATENATE:
2505       catlist = ffecom_concat_list_gather_ (catlist, ffebld_left (expr), max);
2506       expr = ffebld_right (expr);
2507       goto recurse;             /* :::::::::::::::::::: */
2508
2509 #if 0                           /* Breaks passing small actual arg to larger
2510                                    dummy arg of sfunc */
2511     case FFEBLD_opCONVERT:
2512       expr = ffebld_left (expr);
2513       {
2514         ffetargetCharacterSize cmax;
2515
2516         cmax = catlist.len + ffebld_size_known (expr);
2517
2518         if ((max == FFETARGET_charactersizeNONE) || (max > cmax))
2519           max = cmax;
2520       }
2521       goto recurse;             /* :::::::::::::::::::: */
2522 #endif
2523
2524     case FFEBLD_opANY:
2525       return catlist;
2526
2527     default:
2528       assert ("bad op in _gather_" == NULL);
2529       return catlist;
2530     }
2531 }
2532
2533 #endif
2534 /* ffecom_concat_list_kill_ -- Kill list of concatenated string exprs
2535
2536    ffecomConcatList_ catlist;
2537    ffecom_concat_list_kill_(catlist);
2538
2539    Anything allocated within the list info is deallocated.  */
2540
2541 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2542 static void
2543 ffecom_concat_list_kill_ (ffecomConcatList_ catlist)
2544 {
2545   if (catlist.max != 0)
2546     malloc_kill_ks (malloc_pool_image (), catlist.exprs,
2547                     catlist.max * sizeof (catlist.exprs[0]));
2548 }
2549
2550 #endif
2551 /* Make list of concatenated string exprs.
2552
2553    Returns a flattened list of concatenated subexpressions given a
2554    tree of such expressions.  */
2555
2556 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2557 static ffecomConcatList_
2558 ffecom_concat_list_new_ (ffebld expr, ffetargetCharacterSize max)
2559 {
2560   ffecomConcatList_ catlist;
2561
2562   catlist.maxlen = catlist.minlen = catlist.max = catlist.count = 0;
2563   return ffecom_concat_list_gather_ (catlist, expr, max);
2564 }
2565
2566 #endif
2567
2568 /* Provide some kind of useful info on member of aggregate area,
2569    since current g77/gcc technology does not provide debug info
2570    on these members.  */
2571
2572 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2573 static void
2574 ffecom_debug_kludge_ (tree aggr, const char *aggr_type, ffesymbol member,
2575                       tree member_type UNUSED, ffetargetOffset offset)
2576 {
2577   tree value;
2578   tree decl;
2579   int len;
2580   char *buff;
2581   char space[120];
2582 #if 0
2583   tree type_id;
2584
2585   for (type_id = member_type;
2586        TREE_CODE (type_id) != IDENTIFIER_NODE;
2587        )
2588     {
2589       switch (TREE_CODE (type_id))
2590         {
2591         case INTEGER_TYPE:
2592         case REAL_TYPE:
2593           type_id = TYPE_NAME (type_id);
2594           break;
2595
2596         case ARRAY_TYPE:
2597         case COMPLEX_TYPE:
2598           type_id = TREE_TYPE (type_id);
2599           break;
2600
2601         default:
2602           assert ("no IDENTIFIER_NODE for type!" == NULL);
2603           type_id = error_mark_node;
2604           break;
2605         }
2606     }
2607 #endif
2608
2609   if (ffecom_transform_only_dummies_
2610       || !ffe_is_debug_kludge ())
2611     return;     /* Can't do this yet, maybe later. */
2612
2613   len = 60
2614     + strlen (aggr_type)
2615     + IDENTIFIER_LENGTH (DECL_NAME (aggr));
2616 #if 0
2617     + IDENTIFIER_LENGTH (type_id);
2618 #endif
2619
2620   if (((size_t) len) >= ARRAY_SIZE (space))
2621     buff = malloc_new_ks (malloc_pool_image (), "debug_kludge", len + 1);
2622   else
2623     buff = &space[0];
2624
2625   sprintf (&buff[0], "At (%s) `%s' plus %ld bytes",
2626            aggr_type,
2627            IDENTIFIER_POINTER (DECL_NAME (aggr)),
2628            (long int) offset);
2629
2630   value = build_string (len, buff);
2631   TREE_TYPE (value)
2632     = build_type_variant (build_array_type (char_type_node,
2633                                             build_range_type
2634                                             (integer_type_node,
2635                                              integer_one_node,
2636                                              build_int_2 (strlen (buff), 0))),
2637                           1, 0);
2638   decl = build_decl (VAR_DECL,
2639                      ffecom_get_identifier_ (ffesymbol_text (member)),
2640                      TREE_TYPE (value));
2641   TREE_CONSTANT (decl) = 1;
2642   TREE_STATIC (decl) = 1;
2643   DECL_INITIAL (decl) = error_mark_node;
2644   DECL_IN_SYSTEM_HEADER (decl) = 1;     /* Don't let -Wunused complain. */
2645   decl = start_decl (decl, FALSE);
2646   finish_decl (decl, value, FALSE);
2647
2648   if (buff != &space[0])
2649     malloc_kill_ks (malloc_pool_image (), buff, len + 1);
2650 }
2651 #endif
2652
2653 /* ffecom_do_entry_ -- Do compilation of a particular entrypoint
2654
2655    ffesymbol fn;  // the SUBROUTINE, FUNCTION, or ENTRY symbol itself
2656    int i;  // entry# for this entrypoint (used by master fn)
2657    ffecom_do_entrypoint_(s,i);
2658
2659    Makes a public entry point that calls our private master fn (already
2660    compiled).  */
2661
2662 #if FFECOM_targetCURRENT == FFECOM_targetGCC
2663 static void
2664 ffecom_do_entry_ (ffesymbol fn, int entrynum)
2665 {
2666   ffebld item;
2667   tree type;                    /* Type of function. */
2668   tree multi_retval;            /* Var holding return value (union). */
2669   tree result;                  /* Var holding result. */
2670   ffeinfoBasictype bt;
2671   ffeinfoKindtype kt;
2672   ffeglobal g;
2673   ffeglobalType gt;
2674   bool charfunc;                /* All entry points return same type
2675                                    CHARACTER. */
2676   bool cmplxfunc;               /* Use f2c way of returning COMPLEX. */
2677   bool multi;                   /* Master fn has multiple return types. */
2678   bool altreturning = FALSE;    /* This entry point has alternate returns. */
2679   int yes;
2680   int old_lineno = lineno;
2681   char *old_input_filename = input_filename;
2682
2683   input_filename = ffesymbol_where_filename (fn);
2684   lineno = ffesymbol_where_filelinenum (fn);
2685
2686   /* c-parse.y indeed does call suspend_momentary and not only ignores the
2687      return value, but also never calls resume_momentary, when starting an
2688      outer function (see "fndef:", "setspecs:", and so on).  So g77 does the
2689      same thing.  It shouldn't be a problem since start_function calls
2690      temporary_allocation, but it might be necessary.  If it causes a problem
2691      here, then maybe there's a bug lurking in gcc.  NOTE: This identical
2692      comment appears twice in thist file.  */
2693
2694   suspend_momentary ();
2695
2696   ffecom_doing_entry_ = TRUE;   /* Don't bother with array dimensions. */
2697
2698   switch (ffecom_primary_entry_kind_)
2699     {
2700     case FFEINFO_kindFUNCTION:
2701
2702       /* Determine actual return type for function. */
2703
2704       gt = FFEGLOBAL_typeFUNC;
2705       bt = ffesymbol_basictype (fn);
2706       kt = ffesymbol_kindtype (fn);
2707       if (bt == FFEINFO_basictypeNONE)
2708         {
2709           ffeimplic_establish_symbol (fn);
2710           if (ffesymbol_funcresult (fn) != NULL)
2711             ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
2712           bt = ffesymbol_basictype (fn);
2713           kt = ffesymbol_kindtype (fn);
2714         }
2715
2716       if (bt == FFEINFO_basictypeCHARACTER)
2717         charfunc = TRUE, cmplxfunc = FALSE;
2718       else if ((bt == FFEINFO_basictypeCOMPLEX)
2719                && ffesymbol_is_f2c (fn))
2720         charfunc = FALSE, cmplxfunc = TRUE;
2721       else
2722         charfunc = cmplxfunc = FALSE;
2723
2724       if (charfunc)
2725         type = ffecom_tree_fun_type_void;
2726       else if (ffesymbol_is_f2c (fn))
2727         type = ffecom_tree_fun_type[bt][kt];
2728       else
2729         type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
2730
2731       if ((type == NULL_TREE)
2732           || (TREE_TYPE (type) == NULL_TREE))
2733         type = ffecom_tree_fun_type_void;       /* _sym_exec_transition. */
2734
2735       multi = (ffecom_master_bt_ == FFEINFO_basictypeNONE);
2736       break;
2737
2738     case FFEINFO_kindSUBROUTINE:
2739       gt = FFEGLOBAL_typeSUBR;
2740       bt = FFEINFO_basictypeNONE;
2741       kt = FFEINFO_kindtypeNONE;
2742       if (ffecom_is_altreturning_)
2743         {                       /* Am _I_ altreturning? */
2744           for (item = ffesymbol_dummyargs (fn);
2745                item != NULL;
2746                item = ffebld_trail (item))
2747             {
2748               if (ffebld_op (ffebld_head (item)) == FFEBLD_opSTAR)
2749                 {
2750                   altreturning = TRUE;
2751                   break;
2752                 }
2753             }
2754           if (altreturning)
2755             type = ffecom_tree_subr_type;
2756           else
2757             type = ffecom_tree_fun_type_void;
2758         }
2759       else
2760         type = ffecom_tree_fun_type_void;
2761       charfunc = FALSE;
2762       cmplxfunc = FALSE;
2763       multi = FALSE;
2764       break;
2765
2766     default:
2767       assert ("say what??" == NULL);
2768       /* Fall through. */
2769     case FFEINFO_kindANY:
2770       gt = FFEGLOBAL_typeANY;
2771       bt = FFEINFO_basictypeNONE;
2772       kt = FFEINFO_kindtypeNONE;
2773       type = error_mark_node;
2774       charfunc = FALSE;
2775       cmplxfunc = FALSE;
2776       multi = FALSE;
2777       break;
2778     }
2779
2780   /* build_decl uses the current lineno and input_filename to set the decl
2781      source info.  So, I've putzed with ffestd and ffeste code to update that
2782      source info to point to the appropriate statement just before calling
2783      ffecom_do_entrypoint (which calls this fn).  */
2784
2785   start_function (ffecom_get_external_identifier_ (fn),
2786                   type,
2787                   0,            /* nested/inline */
2788                   1);           /* TREE_PUBLIC */
2789
2790   if (((g = ffesymbol_global (fn)) != NULL)
2791       && ((ffeglobal_type (g) == gt)
2792           || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
2793     {
2794       ffeglobal_set_hook (g, current_function_decl);
2795     }
2796
2797   /* Reset args in master arg list so they get retransitioned. */
2798
2799   for (item = ffecom_master_arglist_;
2800        item != NULL;
2801        item = ffebld_trail (item))
2802     {
2803       ffebld arg;
2804       ffesymbol s;
2805
2806       arg = ffebld_head (item);
2807       if (ffebld_op (arg) != FFEBLD_opSYMTER)
2808         continue;               /* Alternate return or some such thing. */
2809       s = ffebld_symter (arg);
2810       ffesymbol_hook (s).decl_tree = NULL_TREE;
2811       ffesymbol_hook (s).length_tree = NULL_TREE;
2812     }
2813
2814   /* Build dummy arg list for this entry point. */
2815
2816   yes = suspend_momentary ();
2817
2818   if (charfunc || cmplxfunc)
2819     {                           /* Prepend arg for where result goes. */
2820       tree type;
2821       tree length;
2822
2823       if (charfunc)
2824         type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
2825       else
2826         type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
2827
2828       result = ffecom_get_invented_identifier ("__g77_%s", "result");
2829
2830       /* Make length arg _and_ enhance type info for CHAR arg itself.  */
2831
2832       if (charfunc)
2833         length = ffecom_char_enhance_arg_ (&type, fn);
2834       else
2835         length = NULL_TREE;     /* Not ref'd if !charfunc. */
2836
2837       type = build_pointer_type (type);
2838       result = build_decl (PARM_DECL, result, type);
2839
2840       push_parm_decl (result);
2841       ffecom_func_result_ = result;
2842
2843       if (charfunc)
2844         {
2845           push_parm_decl (length);
2846           ffecom_func_length_ = length;
2847         }
2848     }
2849   else
2850     result = DECL_RESULT (current_function_decl);
2851
2852   ffecom_push_dummy_decls_ (ffesymbol_dummyargs (fn), FALSE);
2853
2854   resume_momentary (yes);
2855
2856   store_parm_decls (0);
2857
2858   ffecom_start_compstmt ();
2859   /* Disallow temp vars at this level.  */
2860   current_binding_level->prep_state = 2;
2861
2862   /* Make local var to hold return type for multi-type master fn. */
2863
2864   if (multi)
2865     {
2866       yes = suspend_momentary ();
2867
2868       multi_retval = ffecom_get_invented_identifier ("__g77_%s",
2869                                                      "multi_retval");
2870       multi_retval = build_decl (VAR_DECL, multi_retval,
2871                                  ffecom_multi_type_node_);
2872       multi_retval = start_decl (multi_retval, FALSE);
2873       finish_decl (multi_retval, NULL_TREE, FALSE);
2874
2875       resume_momentary (yes);
2876     }
2877   else
2878     multi_retval = NULL_TREE;   /* Not actually ref'd if !multi. */
2879
2880   /* Here we emit the actual code for the entry point. */
2881
2882   {
2883     ffebld list;
2884     ffebld arg;
2885     ffesymbol s;
2886     tree arglist = NULL_TREE;
2887     tree *plist = &arglist;
2888     tree prepend;
2889     tree call;
2890     tree actarg;
2891     tree master_fn;
2892
2893     /* Prepare actual arg list based on master arg list. */
2894
2895     for (list = ffecom_master_arglist_;
2896          list != NULL;
2897          list = ffebld_trail (list))
2898       {
2899         arg = ffebld_head (list);
2900         if (ffebld_op (arg) != FFEBLD_opSYMTER)
2901           continue;
2902         s = ffebld_symter (arg);
2903         if (ffesymbol_hook (s).decl_tree == NULL_TREE
2904             || ffesymbol_hook (s).decl_tree == error_mark_node)
2905           actarg = null_pointer_node;   /* We don't have this arg. */
2906         else
2907           actarg = ffesymbol_hook (s).decl_tree;
2908         *plist = build_tree_list (NULL_TREE, actarg);
2909         plist = &TREE_CHAIN (*plist);
2910       }
2911
2912     /* This code appends the length arguments for character
2913        variables/arrays.  */
2914
2915     for (list = ffecom_master_arglist_;
2916          list != NULL;
2917          list = ffebld_trail (list))
2918       {
2919         arg = ffebld_head (list);
2920         if (ffebld_op (arg) != FFEBLD_opSYMTER)
2921           continue;
2922         s = ffebld_symter (arg);
2923         if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
2924           continue;             /* Only looking for CHARACTER arguments. */
2925         if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
2926           continue;             /* Only looking for variables and arrays. */
2927         if (ffesymbol_hook (s).length_tree == NULL_TREE
2928             || ffesymbol_hook (s).length_tree == error_mark_node)
2929           actarg = ffecom_f2c_ftnlen_zero_node; /* We don't have this arg. */
2930         else
2931           actarg = ffesymbol_hook (s).length_tree;
2932         *plist = build_tree_list (NULL_TREE, actarg);
2933         plist = &TREE_CHAIN (*plist);
2934       }
2935
2936     /* Prepend character-value return info to actual arg list. */
2937
2938     if (charfunc)
2939       {
2940         prepend = build_tree_list (NULL_TREE, ffecom_func_result_);
2941         TREE_CHAIN (prepend)
2942           = build_tree_list (NULL_TREE, ffecom_func_length_);
2943         TREE_CHAIN (TREE_CHAIN (prepend)) = arglist;
2944         arglist = prepend;
2945       }
2946
2947     /* Prepend multi-type return value to actual arg list. */
2948
2949     if (multi)
2950       {
2951         prepend
2952           = build_tree_list (NULL_TREE,
2953                              ffecom_1 (ADDR_EXPR,
2954                               build_pointer_type (TREE_TYPE (multi_retval)),
2955                                        multi_retval));
2956         TREE_CHAIN (prepend) = arglist;
2957         arglist = prepend;
2958       }
2959
2960     /* Prepend my entry-point number to the actual arg list. */
2961
2962     prepend = build_tree_list (NULL_TREE, build_int_2 (entrynum, 0));
2963     TREE_CHAIN (prepend) = arglist;
2964     arglist = prepend;
2965
2966     /* Build the call to the master function. */
2967
2968     master_fn = ffecom_1_fn (ffecom_previous_function_decl_);
2969     call = ffecom_3s (CALL_EXPR,
2970                       TREE_TYPE (TREE_TYPE (TREE_TYPE (master_fn))),
2971                       master_fn, arglist, NULL_TREE);
2972
2973     /* Decide whether the master function is a function or subroutine, and
2974        handle the return value for my entry point. */
2975
2976     if (charfunc || ((ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
2977                      && !altreturning))
2978       {
2979         expand_expr_stmt (call);
2980         expand_null_return ();
2981       }
2982     else if (multi && cmplxfunc)
2983       {
2984         expand_expr_stmt (call);
2985         result
2986           = ffecom_1 (INDIRECT_REF,
2987                       TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
2988                       result);
2989         result = ffecom_modify (NULL_TREE, result,
2990                                 ffecom_2 (COMPONENT_REF, TREE_TYPE (result),
2991                                           multi_retval,
2992                                           ffecom_multi_fields_[bt][kt]));
2993         expand_expr_stmt (result);
2994         expand_null_return ();
2995       }
2996     else if (multi)
2997       {
2998         expand_expr_stmt (call);
2999         result
3000           = ffecom_modify (NULL_TREE, result,
3001                            convert (TREE_TYPE (result),
3002                                     ffecom_2 (COMPONENT_REF,
3003                                               ffecom_tree_type[bt][kt],
3004                                               multi_retval,
3005                                               ffecom_multi_fields_[bt][kt])));
3006         expand_return (result);
3007       }
3008     else if (cmplxfunc)
3009       {
3010         result
3011           = ffecom_1 (INDIRECT_REF,
3012                       TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (result))),
3013                       result);
3014         result = ffecom_modify (NULL_TREE, result, call);
3015         expand_expr_stmt (result);
3016         expand_null_return ();
3017       }
3018     else
3019       {
3020         result = ffecom_modify (NULL_TREE,
3021                                 result,
3022                                 convert (TREE_TYPE (result),
3023                                          call));
3024         expand_return (result);
3025       }
3026
3027     clear_momentary ();
3028   }
3029
3030   ffecom_end_compstmt ();
3031
3032   finish_function (0);
3033
3034   lineno = old_lineno;
3035   input_filename = old_input_filename;
3036
3037   ffecom_doing_entry_ = FALSE;
3038 }
3039
3040 #endif
3041 /* Transform expr into gcc tree with possible destination
3042
3043    Recursive descent on expr while making corresponding tree nodes and
3044    attaching type info and such.  If destination supplied and compatible
3045    with temporary that would be made in certain cases, temporary isn't
3046    made, destination used instead, and dest_used flag set TRUE.  */
3047
3048 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3049 static tree
3050 ffecom_expr_ (ffebld expr, tree dest_tree, ffebld dest,
3051               bool *dest_used, bool assignp, bool widenp)
3052 {
3053   tree item;
3054   tree list;
3055   tree args;
3056   ffeinfoBasictype bt;
3057   ffeinfoKindtype kt;
3058   tree t;
3059   tree dt;                      /* decl_tree for an ffesymbol. */
3060   tree tree_type, tree_type_x;
3061   tree left, right;
3062   ffesymbol s;
3063   enum tree_code code;
3064
3065   assert (expr != NULL);
3066
3067   if (dest_used != NULL)
3068     *dest_used = FALSE;
3069
3070   bt = ffeinfo_basictype (ffebld_info (expr));
3071   kt = ffeinfo_kindtype (ffebld_info (expr));
3072   tree_type = ffecom_tree_type[bt][kt];
3073
3074   /* Widen integral arithmetic as desired while preserving signedness.  */
3075   tree_type_x = NULL_TREE;
3076   if (widenp && tree_type
3077       && GET_MODE_CLASS (TYPE_MODE (tree_type)) == MODE_INT
3078       && TYPE_PRECISION (tree_type) < TYPE_PRECISION (sizetype))
3079     tree_type_x = (TREE_UNSIGNED (tree_type) ? usizetype : ssizetype);
3080
3081   switch (ffebld_op (expr))
3082     {
3083     case FFEBLD_opACCTER:
3084       {
3085         ffebitCount i;
3086         ffebit bits = ffebld_accter_bits (expr);
3087         ffetargetOffset source_offset = 0;
3088         ffetargetOffset dest_offset = ffebld_accter_pad (expr);
3089         tree purpose;
3090
3091         assert (dest_offset == 0
3092                 || (bt == FFEINFO_basictypeCHARACTER
3093                     && kt == FFEINFO_kindtypeCHARACTER1));
3094
3095         list = item = NULL;
3096         for (;;)
3097           {
3098             ffebldConstantUnion cu;
3099             ffebitCount length;
3100             bool value;
3101             ffebldConstantArray ca = ffebld_accter (expr);
3102
3103             ffebit_test (bits, source_offset, &value, &length);
3104             if (length == 0)
3105               break;
3106
3107             if (value)
3108               {
3109                 for (i = 0; i < length; ++i)
3110                   {
3111                     cu = ffebld_constantarray_get (ca, bt, kt,
3112                                                    source_offset + i);
3113
3114                     t = ffecom_constantunion (&cu, bt, kt, tree_type);
3115
3116                     if (i == 0
3117                         && dest_offset != 0)
3118                       purpose = build_int_2 (dest_offset, 0);
3119                     else
3120                       purpose = NULL_TREE;
3121
3122                     if (list == NULL_TREE)
3123                       list = item = build_tree_list (purpose, t);
3124                     else
3125                       {
3126                         TREE_CHAIN (item) = build_tree_list (purpose, t);
3127                         item = TREE_CHAIN (item);
3128                       }
3129                   }
3130               }
3131             source_offset += length;
3132             dest_offset += length;
3133           }
3134       }
3135
3136       item = build_int_2 ((ffebld_accter_size (expr)
3137                            + ffebld_accter_pad (expr)) - 1, 0);
3138       ffebit_kill (ffebld_accter_bits (expr));
3139       TREE_TYPE (item) = ffecom_integer_type_node;
3140       item
3141         = build_array_type
3142           (tree_type,
3143            build_range_type (ffecom_integer_type_node,
3144                              ffecom_integer_zero_node,
3145                              item));
3146       list = build (CONSTRUCTOR, item, NULL_TREE, list);
3147       TREE_CONSTANT (list) = 1;
3148       TREE_STATIC (list) = 1;
3149       return list;
3150
3151     case FFEBLD_opARRTER:
3152       {
3153         ffetargetOffset i;
3154
3155         list = NULL_TREE;
3156         if (ffebld_arrter_pad (expr) == 0)
3157           item = NULL_TREE;
3158         else
3159           {
3160             assert (bt == FFEINFO_basictypeCHARACTER
3161                     && kt == FFEINFO_kindtypeCHARACTER1);
3162
3163             /* Becomes PURPOSE first time through loop.  */
3164             item = build_int_2 (ffebld_arrter_pad (expr), 0);
3165           }
3166
3167         for (i = 0; i < ffebld_arrter_size (expr); ++i)
3168           {
3169             ffebldConstantUnion cu
3170             = ffebld_constantarray_get (ffebld_arrter (expr), bt, kt, i);
3171
3172             t = ffecom_constantunion (&cu, bt, kt, tree_type);
3173
3174             if (list == NULL_TREE)
3175               /* Assume item is PURPOSE first time through loop.  */
3176               list = item = build_tree_list (item, t);
3177             else
3178               {
3179                 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
3180                 item = TREE_CHAIN (item);
3181               }
3182           }
3183       }
3184
3185       item = build_int_2 ((ffebld_arrter_size (expr)
3186                           + ffebld_arrter_pad (expr)) - 1, 0);
3187       TREE_TYPE (item) = ffecom_integer_type_node;
3188       item
3189         = build_array_type
3190           (tree_type,
3191            build_range_type (ffecom_integer_type_node,
3192                              ffecom_integer_zero_node,
3193                              item));
3194       list = build (CONSTRUCTOR, item, NULL_TREE, list);
3195       TREE_CONSTANT (list) = 1;
3196       TREE_STATIC (list) = 1;
3197       return list;
3198
3199     case FFEBLD_opCONTER:
3200       assert (ffebld_conter_pad (expr) == 0);
3201       item
3202         = ffecom_constantunion (&ffebld_constant_union (ffebld_conter (expr)),
3203                                 bt, kt, tree_type);
3204       return item;
3205
3206     case FFEBLD_opSYMTER:
3207       if ((ffebld_symter_generic (expr) != FFEINTRIN_genNONE)
3208           || (ffebld_symter_specific (expr) != FFEINTRIN_specNONE))
3209         return ffecom_ptr_to_expr (expr);       /* Same as %REF(intrinsic). */
3210       s = ffebld_symter (expr);
3211       t = ffesymbol_hook (s).decl_tree;
3212
3213       if (assignp)
3214         {                       /* ASSIGN'ed-label expr. */
3215           if (ffe_is_ugly_assign ())
3216             {
3217               /* User explicitly wants ASSIGN'ed variables to be at the same
3218                  memory address as the variables when used in non-ASSIGN
3219                  contexts.  That can make old, arcane, non-standard code
3220                  work, but don't try to do it when a pointer wouldn't fit
3221                  in the normal variable (take other approach, and warn,
3222                  instead).  */
3223
3224               if (t == NULL_TREE)
3225                 {
3226                   s = ffecom_sym_transform_ (s);
3227                   t = ffesymbol_hook (s).decl_tree;
3228                   assert (t != NULL_TREE);
3229                 }
3230
3231               if (t == error_mark_node)
3232                 return t;
3233
3234               if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
3235                   >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
3236                 {
3237                   if (ffesymbol_hook (s).addr)
3238                     t = ffecom_1 (INDIRECT_REF,
3239                                   TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3240                   return t;
3241                 }
3242
3243               if (ffesymbol_hook (s).assign_tree == NULL_TREE)
3244                 {
3245                   ffebad_start_msg ("ASSIGN'ed label cannot fit into `%A' at %0 -- using wider sibling",
3246                                     FFEBAD_severityWARNING);
3247                   ffebad_string (ffesymbol_text (s));
3248                   ffebad_here (0, ffesymbol_where_line (s),
3249                                ffesymbol_where_column (s));
3250                   ffebad_finish ();
3251                 }
3252             }
3253
3254           /* Don't use the normal variable's tree for ASSIGN, though mark
3255              it as in the system header (housekeeping).  Use an explicit,
3256              specially created sibling that is known to be wide enough
3257              to hold pointers to labels.  */
3258
3259           if (t != NULL_TREE
3260               && TREE_CODE (t) == VAR_DECL)
3261             DECL_IN_SYSTEM_HEADER (t) = 1;      /* Don't let -Wunused complain. */
3262
3263           t = ffesymbol_hook (s).assign_tree;
3264           if (t == NULL_TREE)
3265             {
3266               s = ffecom_sym_transform_assign_ (s);
3267               t = ffesymbol_hook (s).assign_tree;
3268               assert (t != NULL_TREE);
3269             }
3270         }
3271       else
3272         {
3273           if (t == NULL_TREE)
3274             {
3275               s = ffecom_sym_transform_ (s);
3276               t = ffesymbol_hook (s).decl_tree;
3277               assert (t != NULL_TREE);
3278             }
3279           if (ffesymbol_hook (s).addr)
3280             t = ffecom_1 (INDIRECT_REF,
3281                           TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (t))), t);
3282         }
3283       return t;
3284
3285     case FFEBLD_opARRAYREF:
3286       return ffecom_arrayref_ (NULL_TREE, expr, 0);
3287
3288     case FFEBLD_opUPLUS:
3289       left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3290       return ffecom_1 (NOP_EXPR, tree_type, left);
3291
3292     case FFEBLD_opPAREN:
3293       /* ~~~Make sure Fortran rules respected here */
3294       left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3295       return ffecom_1 (NOP_EXPR, tree_type, left);
3296
3297     case FFEBLD_opUMINUS:
3298       left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3299       if (tree_type_x) 
3300         {
3301           tree_type = tree_type_x;
3302           left = convert (tree_type, left);
3303         }
3304       return ffecom_1 (NEGATE_EXPR, tree_type, left);
3305
3306     case FFEBLD_opADD:
3307       left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3308       right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3309       if (tree_type_x) 
3310         {
3311           tree_type = tree_type_x;
3312           left = convert (tree_type, left);
3313           right = convert (tree_type, right);
3314         }
3315       return ffecom_2 (PLUS_EXPR, tree_type, left, right);
3316
3317     case FFEBLD_opSUBTRACT:
3318       left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3319       right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3320       if (tree_type_x) 
3321         {
3322           tree_type = tree_type_x;
3323           left = convert (tree_type, left);
3324           right = convert (tree_type, right);
3325         }
3326       return ffecom_2 (MINUS_EXPR, tree_type, left, right);
3327
3328     case FFEBLD_opMULTIPLY:
3329       left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3330       right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3331       if (tree_type_x) 
3332         {
3333           tree_type = tree_type_x;
3334           left = convert (tree_type, left);
3335           right = convert (tree_type, right);
3336         }
3337       return ffecom_2 (MULT_EXPR, tree_type, left, right);
3338
3339     case FFEBLD_opDIVIDE:
3340       left = ffecom_expr_ (ffebld_left (expr), NULL, NULL, NULL, FALSE, widenp);
3341       right = ffecom_expr_ (ffebld_right (expr), NULL, NULL, NULL, FALSE, widenp);
3342       if (tree_type_x) 
3343         {
3344           tree_type = tree_type_x;
3345           left = convert (tree_type, left);
3346           right = convert (tree_type, right);
3347         }
3348       return ffecom_tree_divide_ (tree_type, left, right,
3349                                   dest_tree, dest, dest_used,
3350                                   ffebld_nonter_hook (expr));
3351
3352     case FFEBLD_opPOWER:
3353       {
3354         ffebld left = ffebld_left (expr);
3355         ffebld right = ffebld_right (expr);
3356         ffecomGfrt code;
3357         ffeinfoKindtype rtkt;
3358         ffeinfoKindtype ltkt;
3359
3360         switch (ffeinfo_basictype (ffebld_info (right)))
3361           {
3362           case FFEINFO_basictypeINTEGER:
3363             if (1 || optimize)
3364               {
3365                 item = ffecom_expr_power_integer_ (expr);
3366                 if (item != NULL_TREE)
3367                   return item;
3368               }
3369
3370             rtkt = FFEINFO_kindtypeINTEGER1;
3371             switch (ffeinfo_basictype (ffebld_info (left)))
3372               {
3373               case FFEINFO_basictypeINTEGER:
3374                 if ((ffeinfo_kindtype (ffebld_info (left))
3375                     == FFEINFO_kindtypeINTEGER4)
3376                     || (ffeinfo_kindtype (ffebld_info (right))
3377                         == FFEINFO_kindtypeINTEGER4))
3378                   {
3379                     code = FFECOM_gfrtPOW_QQ;
3380                     ltkt = FFEINFO_kindtypeINTEGER4;
3381                     rtkt = FFEINFO_kindtypeINTEGER4;
3382                   }
3383                 else
3384                   {
3385                     code = FFECOM_gfrtPOW_II;
3386                     ltkt = FFEINFO_kindtypeINTEGER1;
3387                   }
3388                 break;
3389
3390               case FFEINFO_basictypeREAL:
3391                 if (ffeinfo_kindtype (ffebld_info (left))
3392                     == FFEINFO_kindtypeREAL1)
3393                   {
3394                     code = FFECOM_gfrtPOW_RI;
3395                     ltkt = FFEINFO_kindtypeREAL1;
3396                   }
3397                 else
3398                   {
3399                     code = FFECOM_gfrtPOW_DI;
3400                     ltkt = FFEINFO_kindtypeREAL2;
3401                   }
3402                 break;
3403
3404               case FFEINFO_basictypeCOMPLEX:
3405                 if (ffeinfo_kindtype (ffebld_info (left))
3406                     == FFEINFO_kindtypeREAL1)
3407                   {
3408                     code = FFECOM_gfrtPOW_CI;   /* Overlapping result okay. */
3409                     ltkt = FFEINFO_kindtypeREAL1;
3410                   }
3411                 else
3412                   {
3413                     code = FFECOM_gfrtPOW_ZI;   /* Overlapping result okay. */
3414                     ltkt = FFEINFO_kindtypeREAL2;
3415                   }
3416                 break;
3417
3418               default:
3419                 assert ("bad pow_*i" == NULL);
3420                 code = FFECOM_gfrtPOW_CI;       /* Overlapping result okay. */
3421                 ltkt = FFEINFO_kindtypeREAL1;
3422                 break;
3423               }
3424             if (ffeinfo_kindtype (ffebld_info (left)) != ltkt)
3425               left = ffeexpr_convert (left, NULL, NULL,
3426                                       ffeinfo_basictype (ffebld_info (left)),
3427                                       ltkt, 0,
3428                                       FFETARGET_charactersizeNONE,
3429                                       FFEEXPR_contextLET);
3430             if (ffeinfo_kindtype (ffebld_info (right)) != rtkt)
3431               right = ffeexpr_convert (right, NULL, NULL,
3432                                        FFEINFO_basictypeINTEGER,
3433                                        rtkt, 0,
3434                                        FFETARGET_charactersizeNONE,
3435                                        FFEEXPR_contextLET);
3436             break;
3437
3438           case FFEINFO_basictypeREAL:
3439             if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3440               left = ffeexpr_convert (left, NULL, NULL, FFEINFO_basictypeREAL,
3441                                       FFEINFO_kindtypeREALDOUBLE, 0,
3442                                       FFETARGET_charactersizeNONE,
3443                                       FFEEXPR_contextLET);
3444             if (ffeinfo_kindtype (ffebld_info (right))
3445                 == FFEINFO_kindtypeREAL1)
3446               right = ffeexpr_convert (right, NULL, NULL,
3447                                        FFEINFO_basictypeREAL,
3448                                        FFEINFO_kindtypeREALDOUBLE, 0,
3449                                        FFETARGET_charactersizeNONE,
3450                                        FFEEXPR_contextLET);
3451             code = FFECOM_gfrtPOW_DD;
3452             break;
3453
3454           case FFEINFO_basictypeCOMPLEX:
3455             if (ffeinfo_kindtype (ffebld_info (left)) == FFEINFO_kindtypeREAL1)
3456               left = ffeexpr_convert (left, NULL, NULL,
3457                                       FFEINFO_basictypeCOMPLEX,
3458                                       FFEINFO_kindtypeREALDOUBLE, 0,
3459                                       FFETARGET_charactersizeNONE,
3460                                       FFEEXPR_contextLET);
3461             if (ffeinfo_kindtype (ffebld_info (right))
3462                 == FFEINFO_kindtypeREAL1)
3463               right = ffeexpr_convert (right, NULL, NULL,
3464                                        FFEINFO_basictypeCOMPLEX,
3465                                        FFEINFO_kindtypeREALDOUBLE, 0,
3466                                        FFETARGET_charactersizeNONE,
3467                                        FFEEXPR_contextLET);
3468             code = FFECOM_gfrtPOW_ZZ;   /* Overlapping result okay. */
3469             break;
3470
3471           default:
3472             assert ("bad pow_x*" == NULL);
3473             code = FFECOM_gfrtPOW_II;
3474             break;
3475           }
3476         return ffecom_call_binop_ (ffecom_gfrt_tree_ (code),
3477                                    ffecom_gfrt_kindtype (code),
3478                                    (ffe_is_f2c_library ()
3479                                     && ffecom_gfrt_complex_[code]),
3480                                    tree_type, left, right,
3481                                    dest_tree, dest, dest_used,
3482                                    NULL_TREE, FALSE,
3483                                    ffebld_nonter_hook (expr));
3484       }
3485
3486     case FFEBLD_opNOT:
3487       switch (bt)
3488         {
3489         case FFEINFO_basictypeLOGICAL:
3490           item = ffecom_truth_value_invert (ffecom_expr (ffebld_left (expr)));
3491           return convert (tree_type, item);
3492
3493         case FFEINFO_basictypeINTEGER:
3494           return ffecom_1 (BIT_NOT_EXPR, tree_type,
3495                            ffecom_expr (ffebld_left (expr)));
3496
3497         default:
3498           assert ("NOT bad basictype" == NULL);
3499           /* Fall through. */
3500         case FFEINFO_basictypeANY:
3501           return error_mark_node;
3502         }
3503       break;
3504
3505     case FFEBLD_opFUNCREF:
3506       assert (ffeinfo_basictype (ffebld_info (expr))
3507               != FFEINFO_basictypeCHARACTER);
3508       /* Fall through.   */
3509     case FFEBLD_opSUBRREF:
3510       if (ffeinfo_where (ffebld_info (ffebld_left (expr)))
3511           == FFEINFO_whereINTRINSIC)
3512         {                       /* Invocation of an intrinsic. */
3513           item = ffecom_expr_intrinsic_ (expr, dest_tree, dest,
3514                                          dest_used);
3515           return item;
3516         }
3517       s = ffebld_symter (ffebld_left (expr));
3518       dt = ffesymbol_hook (s).decl_tree;
3519       if (dt == NULL_TREE)
3520         {
3521           s = ffecom_sym_transform_ (s);
3522           dt = ffesymbol_hook (s).decl_tree;
3523         }
3524       if (dt == error_mark_node)
3525         return dt;
3526
3527       if (ffesymbol_hook (s).addr)
3528         item = dt;
3529       else
3530         item = ffecom_1_fn (dt);
3531
3532       if (ffesymbol_where (s) == FFEINFO_whereCONSTANT)
3533         args = ffecom_list_expr (ffebld_right (expr));
3534       else
3535         args = ffecom_list_ptr_to_expr (ffebld_right (expr));
3536
3537       if (args == error_mark_node)
3538         return error_mark_node;
3539
3540       item = ffecom_call_ (item, kt,
3541                            ffesymbol_is_f2c (s)
3542                            && (bt == FFEINFO_basictypeCOMPLEX)
3543                            && (ffesymbol_where (s)
3544                                != FFEINFO_whereCONSTANT),
3545                            tree_type,
3546                            args,
3547                            dest_tree, dest, dest_used,
3548                            error_mark_node, FALSE,
3549                            ffebld_nonter_hook (expr));
3550       TREE_SIDE_EFFECTS (item) = 1;
3551       return item;
3552
3553     case FFEBLD_opAND:
3554       switch (bt)
3555         {
3556         case FFEINFO_basictypeLOGICAL:
3557           item
3558             = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3559                        ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3560                      ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3561           return convert (tree_type, item);
3562
3563         case FFEINFO_basictypeINTEGER:
3564           return ffecom_2 (BIT_AND_EXPR, tree_type,
3565                            ffecom_expr (ffebld_left (expr)),
3566                            ffecom_expr (ffebld_right (expr)));
3567
3568         default:
3569           assert ("AND bad basictype" == NULL);
3570           /* Fall through. */
3571         case FFEINFO_basictypeANY:
3572           return error_mark_node;
3573         }
3574       break;
3575
3576     case FFEBLD_opOR:
3577       switch (bt)
3578         {
3579         case FFEINFO_basictypeLOGICAL:
3580           item
3581             = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
3582                        ffecom_truth_value (ffecom_expr (ffebld_left (expr))),
3583                      ffecom_truth_value (ffecom_expr (ffebld_right (expr))));
3584           return convert (tree_type, item);
3585
3586         case FFEINFO_basictypeINTEGER:
3587           return ffecom_2 (BIT_IOR_EXPR, tree_type,
3588                            ffecom_expr (ffebld_left (expr)),
3589                            ffecom_expr (ffebld_right (expr)));
3590
3591         default:
3592           assert ("OR bad basictype" == NULL);
3593           /* Fall through. */
3594         case FFEINFO_basictypeANY:
3595           return error_mark_node;
3596         }
3597       break;
3598
3599     case FFEBLD_opXOR:
3600     case FFEBLD_opNEQV:
3601       switch (bt)
3602         {
3603         case FFEINFO_basictypeLOGICAL:
3604           item
3605             = ffecom_2 (NE_EXPR, integer_type_node,
3606                         ffecom_expr (ffebld_left (expr)),
3607                         ffecom_expr (ffebld_right (expr)));
3608           return convert (tree_type, ffecom_truth_value (item));
3609
3610         case FFEINFO_basictypeINTEGER:
3611           return ffecom_2 (BIT_XOR_EXPR, tree_type,
3612                            ffecom_expr (ffebld_left (expr)),
3613                            ffecom_expr (ffebld_right (expr)));
3614
3615         default:
3616           assert ("XOR/NEQV bad basictype" == NULL);
3617           /* Fall through. */
3618         case FFEINFO_basictypeANY:
3619           return error_mark_node;
3620         }
3621       break;
3622
3623     case FFEBLD_opEQV:
3624       switch (bt)
3625         {
3626         case FFEINFO_basictypeLOGICAL:
3627           item
3628             = ffecom_2 (EQ_EXPR, integer_type_node,
3629                         ffecom_expr (ffebld_left (expr)),
3630                         ffecom_expr (ffebld_right (expr)));
3631           return convert (tree_type, ffecom_truth_value (item));
3632
3633         case FFEINFO_basictypeINTEGER:
3634           return
3635             ffecom_1 (BIT_NOT_EXPR, tree_type,
3636                       ffecom_2 (BIT_XOR_EXPR, tree_type,
3637                                 ffecom_expr (ffebld_left (expr)),
3638                                 ffecom_expr (ffebld_right (expr))));
3639
3640         default:
3641           assert ("EQV bad basictype" == NULL);
3642           /* Fall through. */
3643         case FFEINFO_basictypeANY:
3644           return error_mark_node;
3645         }
3646       break;
3647
3648     case FFEBLD_opCONVERT:
3649       if (ffebld_op (ffebld_left (expr)) == FFEBLD_opANY)
3650         return error_mark_node;
3651
3652       switch (bt)
3653         {
3654         case FFEINFO_basictypeLOGICAL:
3655         case FFEINFO_basictypeINTEGER:
3656         case FFEINFO_basictypeREAL:
3657           return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3658
3659         case FFEINFO_basictypeCOMPLEX:
3660           switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3661             {
3662             case FFEINFO_basictypeINTEGER:
3663             case FFEINFO_basictypeLOGICAL:
3664             case FFEINFO_basictypeREAL:
3665               item = ffecom_expr (ffebld_left (expr));
3666               if (item == error_mark_node)
3667                 return error_mark_node;
3668               /* convert() takes care of converting to the subtype first,
3669                  at least in gcc-2.7.2. */
3670               item = convert (tree_type, item);
3671               return item;
3672
3673             case FFEINFO_basictypeCOMPLEX:
3674               return convert (tree_type, ffecom_expr (ffebld_left (expr)));
3675
3676             default:
3677               assert ("CONVERT COMPLEX bad basictype" == NULL);
3678               /* Fall through. */
3679             case FFEINFO_basictypeANY:
3680               return error_mark_node;
3681             }
3682           break;
3683
3684         default:
3685           assert ("CONVERT bad basictype" == NULL);
3686           /* Fall through. */
3687         case FFEINFO_basictypeANY:
3688           return error_mark_node;
3689         }
3690       break;
3691
3692     case FFEBLD_opLT:
3693       code = LT_EXPR;
3694       goto relational;          /* :::::::::::::::::::: */
3695
3696     case FFEBLD_opLE:
3697       code = LE_EXPR;
3698       goto relational;          /* :::::::::::::::::::: */
3699
3700     case FFEBLD_opEQ:
3701       code = EQ_EXPR;
3702       goto relational;          /* :::::::::::::::::::: */
3703
3704     case FFEBLD_opNE:
3705       code = NE_EXPR;
3706       goto relational;          /* :::::::::::::::::::: */
3707
3708     case FFEBLD_opGT:
3709       code = GT_EXPR;
3710       goto relational;          /* :::::::::::::::::::: */
3711
3712     case FFEBLD_opGE:
3713       code = GE_EXPR;
3714
3715     relational:         /* :::::::::::::::::::: */
3716       switch (ffeinfo_basictype (ffebld_info (ffebld_left (expr))))
3717         {
3718         case FFEINFO_basictypeLOGICAL:
3719         case FFEINFO_basictypeINTEGER:
3720         case FFEINFO_basictypeREAL:
3721           item = ffecom_2 (code, integer_type_node,
3722                            ffecom_expr (ffebld_left (expr)),
3723                            ffecom_expr (ffebld_right (expr)));
3724           return convert (tree_type, item);
3725
3726         case FFEINFO_basictypeCOMPLEX:
3727           assert (code == EQ_EXPR || code == NE_EXPR);
3728           {
3729             tree real_type;
3730             tree arg1 = ffecom_expr (ffebld_left (expr));
3731             tree arg2 = ffecom_expr (ffebld_right (expr));
3732
3733             if (arg1 == error_mark_node || arg2 == error_mark_node)
3734               return error_mark_node;
3735
3736             arg1 = ffecom_save_tree (arg1);
3737             arg2 = ffecom_save_tree (arg2);
3738
3739             if (TREE_CODE (TREE_TYPE (arg1)) == COMPLEX_TYPE)
3740               {
3741                 real_type = TREE_TYPE (TREE_TYPE (arg1));
3742                 assert (real_type == TREE_TYPE (TREE_TYPE (arg2)));
3743               }
3744             else
3745               {
3746                 real_type = TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg1)));
3747                 assert (real_type == TREE_TYPE (TYPE_FIELDS (TREE_TYPE (arg2))));
3748               }
3749
3750             item
3751               = ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
3752                           ffecom_2 (EQ_EXPR, integer_type_node,
3753                                   ffecom_1 (REALPART_EXPR, real_type, arg1),
3754                                  ffecom_1 (REALPART_EXPR, real_type, arg2)),
3755                           ffecom_2 (EQ_EXPR, integer_type_node,
3756                                   ffecom_1 (IMAGPART_EXPR, real_type, arg1),
3757                                     ffecom_1 (IMAGPART_EXPR, real_type,
3758                                               arg2)));
3759             if (code == EQ_EXPR)
3760               item = ffecom_truth_value (item);
3761             else
3762               item = ffecom_truth_value_invert (item);
3763             return convert (tree_type, item);
3764           }
3765
3766         case FFEINFO_basictypeCHARACTER:
3767           {
3768             ffebld left = ffebld_left (expr);
3769             ffebld right = ffebld_right (expr);
3770             tree left_tree;
3771             tree right_tree;
3772             tree left_length;
3773             tree right_length;
3774
3775             /* f2c run-time functions do the implicit blank-padding for us,
3776                so we don't usually have to implement blank-padding ourselves.
3777                (The exception is when we pass an argument to a separately
3778                compiled statement function -- if we know the arg is not the
3779                same length as the dummy, we must truncate or extend it.  If
3780                we "inline" statement functions, that necessity goes away as
3781                well.)
3782
3783                Strip off the CONVERT operators that blank-pad.  (Truncation by
3784                CONVERT shouldn't happen here, but it can happen in
3785                assignments.) */
3786
3787             while (ffebld_op (left) == FFEBLD_opCONVERT)
3788               left = ffebld_left (left);
3789             while (ffebld_op (right) == FFEBLD_opCONVERT)
3790               right = ffebld_left (right);
3791
3792             left_tree = ffecom_arg_ptr_to_expr (left, &left_length);
3793             right_tree = ffecom_arg_ptr_to_expr (right, &right_length);
3794
3795             if (left_tree == error_mark_node || left_length == error_mark_node
3796                 || right_tree == error_mark_node
3797                 || right_length == error_mark_node)
3798               return error_mark_node;
3799
3800             if ((ffebld_size_known (left) == 1)
3801                 && (ffebld_size_known (right) == 1))
3802               {
3803                 left_tree
3804                   = ffecom_1 (INDIRECT_REF,
3805                       TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3806                               left_tree);
3807                 right_tree
3808                   = ffecom_1 (INDIRECT_REF,
3809                      TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3810                               right_tree);
3811
3812                 item
3813                   = ffecom_2 (code, integer_type_node,
3814                               ffecom_2 (ARRAY_REF,
3815                       TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (left_tree))),
3816                                         left_tree,
3817                                         integer_one_node),
3818                               ffecom_2 (ARRAY_REF,
3819                      TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (right_tree))),
3820                                         right_tree,
3821                                         integer_one_node));
3822               }
3823             else
3824               {
3825                 item = build_tree_list (NULL_TREE, left_tree);
3826                 TREE_CHAIN (item) = build_tree_list (NULL_TREE, right_tree);
3827                 TREE_CHAIN (TREE_CHAIN (item)) = build_tree_list (NULL_TREE,
3828                                                                left_length);
3829                 TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
3830                   = build_tree_list (NULL_TREE, right_length);
3831                 item = ffecom_call_gfrt (FFECOM_gfrtCMP, item, NULL_TREE);
3832                 item = ffecom_2 (code, integer_type_node,
3833                                  item,
3834                                  convert (TREE_TYPE (item),
3835                                           integer_zero_node));
3836               }
3837             item = convert (tree_type, item);
3838           }
3839
3840           return item;
3841
3842         default:
3843           assert ("relational bad basictype" == NULL);
3844           /* Fall through. */
3845         case FFEINFO_basictypeANY:
3846           return error_mark_node;
3847         }
3848       break;
3849
3850     case FFEBLD_opPERCENT_LOC:
3851       item = ffecom_arg_ptr_to_expr (ffebld_left (expr), &list);
3852       return convert (tree_type, item);
3853
3854     case FFEBLD_opITEM:
3855     case FFEBLD_opSTAR:
3856     case FFEBLD_opBOUNDS:
3857     case FFEBLD_opREPEAT:
3858     case FFEBLD_opLABTER:
3859     case FFEBLD_opLABTOK:
3860     case FFEBLD_opIMPDO:
3861     case FFEBLD_opCONCATENATE:
3862     case FFEBLD_opSUBSTR:
3863     default:
3864       assert ("bad op" == NULL);
3865       /* Fall through. */
3866     case FFEBLD_opANY:
3867       return error_mark_node;
3868     }
3869
3870 #if 1
3871   assert ("didn't think anything got here anymore!!" == NULL);
3872 #else
3873   switch (ffebld_arity (expr))
3874     {
3875     case 2:
3876       TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3877       TREE_OPERAND (item, 1) = ffecom_expr (ffebld_right (expr));
3878       if (TREE_OPERAND (item, 0) == error_mark_node
3879           || TREE_OPERAND (item, 1) == error_mark_node)
3880         return error_mark_node;
3881       break;
3882
3883     case 1:
3884       TREE_OPERAND (item, 0) = ffecom_expr (ffebld_left (expr));
3885       if (TREE_OPERAND (item, 0) == error_mark_node)
3886         return error_mark_node;
3887       break;
3888
3889     default:
3890       break;
3891     }
3892
3893   return fold (item);
3894 #endif
3895 }
3896
3897 #endif
3898 /* Returns the tree that does the intrinsic invocation.
3899
3900    Note: this function applies only to intrinsics returning
3901    CHARACTER*1 or non-CHARACTER results, and to intrinsic
3902    subroutines.  */
3903
3904 #if FFECOM_targetCURRENT == FFECOM_targetGCC
3905 static tree
3906 ffecom_expr_intrinsic_ (ffebld expr, tree dest_tree,
3907                         ffebld dest, bool *dest_used)
3908 {
3909   tree expr_tree;
3910   tree saved_expr1;             /* For those who need it. */
3911   tree saved_expr2;             /* For those who need it. */
3912   ffeinfoBasictype bt;
3913   ffeinfoKindtype kt;
3914   tree tree_type;
3915   tree arg1_type;
3916   tree real_type;               /* REAL type corresponding to COMPLEX. */
3917   tree tempvar;
3918   ffebld list = ffebld_right (expr);    /* List of (some) args. */
3919   ffebld arg1;                  /* For handy reference. */
3920   ffebld arg2;
3921   ffebld arg3;
3922   ffeintrinImp codegen_imp;
3923   ffecomGfrt gfrt;
3924
3925   assert (ffebld_op (ffebld_left (expr)) == FFEBLD_opSYMTER);
3926
3927   if (dest_used != NULL)
3928     *dest_used = FALSE;
3929
3930   bt = ffeinfo_basictype (ffebld_info (expr));
3931   kt = ffeinfo_kindtype (ffebld_info (expr));
3932   tree_type = ffecom_tree_type[bt][kt];
3933
3934   if (list != NULL)
3935     {
3936       arg1 = ffebld_head (list);
3937       if (arg1 != NULL && ffebld_op (arg1) == FFEBLD_opANY)
3938         return error_mark_node;
3939       if ((list = ffebld_trail (list)) != NULL)
3940         {
3941           arg2 = ffebld_head (list);
3942           if (arg2 != NULL && ffebld_op (arg2) == FFEBLD_opANY)
3943             return error_mark_node;
3944           if ((list = ffebld_trail (list)) != NULL)
3945             {
3946               arg3 = ffebld_head (list);
3947               if (arg3 != NULL && ffebld_op (arg3) == FFEBLD_opANY)
3948                 return error_mark_node;
3949             }
3950           else
3951             arg3 = NULL;
3952         }
3953       else
3954         arg2 = arg3 = NULL;
3955     }
3956   else
3957     arg1 = arg2 = arg3 = NULL;
3958
3959   /* <list> ends up at the opITEM of the 3rd arg, or NULL if there are < 3
3960      args.  This is used by the MAX/MIN expansions. */
3961
3962   if (arg1 != NULL)
3963     arg1_type = ffecom_tree_type
3964       [ffeinfo_basictype (ffebld_info (arg1))]
3965       [ffeinfo_kindtype (ffebld_info (arg1))];
3966   else
3967     arg1_type = NULL_TREE;      /* Really not needed, but might catch bugs
3968                                    here. */
3969
3970   /* There are several ways for each of the cases in the following switch
3971      statements to exit (from simplest to use to most complicated):
3972
3973      break;  (when expr_tree == NULL)
3974
3975      A standard call is made to the specific intrinsic just as if it had been
3976      passed in as a dummy procedure and called as any old procedure.  This
3977      method can produce slower code but in some cases it's the easiest way for
3978      now.  However, if a (presumably faster) direct call is available,
3979      that is used, so this is the easiest way in many more cases now.
3980
3981      gfrt = FFECOM_gfrtWHATEVER;
3982      break;
3983
3984      gfrt contains the gfrt index of a library function to call, passing the
3985      argument(s) by value rather than by reference.  Used when a more
3986      careful choice of library function is needed than that provided
3987      by the vanilla `break;'.
3988
3989      return expr_tree;
3990
3991      The expr_tree has been completely set up and is ready to be returned
3992      as is.  No further actions are taken.  Use this when the tree is not
3993      in the simple form for one of the arity_n labels.   */
3994
3995   /* For info on how the switch statement cases were written, see the files
3996      enclosed in comments below the switch statement. */
3997
3998   codegen_imp = ffebld_symter_implementation (ffebld_left (expr));
3999   gfrt = ffeintrin_gfrt_direct (codegen_imp);
4000   if (gfrt == FFECOM_gfrt)
4001     gfrt = ffeintrin_gfrt_indirect (codegen_imp);
4002
4003   switch (codegen_imp)
4004     {
4005     case FFEINTRIN_impABS:
4006     case FFEINTRIN_impCABS:
4007     case FFEINTRIN_impCDABS:
4008     case FFEINTRIN_impDABS:
4009     case FFEINTRIN_impIABS:
4010       if (ffeinfo_basictype (ffebld_info (arg1))
4011           == FFEINFO_basictypeCOMPLEX)
4012         {
4013           if (kt == FFEINFO_kindtypeREAL1)
4014             gfrt = FFECOM_gfrtCABS;
4015           else if (kt == FFEINFO_kindtypeREAL2)
4016             gfrt = FFECOM_gfrtCDABS;
4017           break;
4018         }
4019       return ffecom_1 (ABS_EXPR, tree_type,
4020                        convert (tree_type, ffecom_expr (arg1)));
4021
4022     case FFEINTRIN_impACOS:
4023     case FFEINTRIN_impDACOS:
4024       break;
4025
4026     case FFEINTRIN_impAIMAG:
4027     case FFEINTRIN_impDIMAG:
4028     case FFEINTRIN_impIMAGPART:
4029       if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4030         arg1_type = TREE_TYPE (arg1_type);
4031       else
4032         arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4033
4034       return
4035         convert (tree_type,
4036                  ffecom_1 (IMAGPART_EXPR, arg1_type,
4037                            ffecom_expr (arg1)));
4038
4039     case FFEINTRIN_impAINT:
4040     case FFEINTRIN_impDINT:
4041 #if 0
4042       /* ~~Someday implement FIX_TRUNC_EXPR yielding same type as arg.  */
4043       return ffecom_1 (FIX_TRUNC_EXPR, tree_type, ffecom_expr (arg1));
4044 #else /* in the meantime, must use floor to avoid range problems with ints */
4045       /* r__1 = r1 >= 0 ? floor(r1) : -floor(-r1); */
4046       saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4047       return
4048         convert (tree_type,
4049                  ffecom_3 (COND_EXPR, double_type_node,
4050                            ffecom_truth_value
4051                            (ffecom_2 (GE_EXPR, integer_type_node,
4052                                       saved_expr1,
4053                                       convert (arg1_type,
4054                                                ffecom_float_zero_))),
4055                            ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4056                                              build_tree_list (NULL_TREE,
4057                                                   convert (double_type_node,
4058                                                            saved_expr1)),
4059                                              NULL_TREE),
4060                            ffecom_1 (NEGATE_EXPR, double_type_node,
4061                                      ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4062                                                  build_tree_list (NULL_TREE,
4063                                                   convert (double_type_node,
4064                                                       ffecom_1 (NEGATE_EXPR,
4065                                                                 arg1_type,
4066                                                                saved_expr1))),
4067                                                        NULL_TREE)
4068                                      ))
4069                  );
4070 #endif
4071
4072     case FFEINTRIN_impANINT:
4073     case FFEINTRIN_impDNINT:
4074 #if 0                           /* This way of doing it won't handle real
4075                                    numbers of large magnitudes. */
4076       saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4077       expr_tree = convert (tree_type,
4078                            convert (integer_type_node,
4079                                     ffecom_3 (COND_EXPR, tree_type,
4080                                               ffecom_truth_value
4081                                               (ffecom_2 (GE_EXPR,
4082                                                          integer_type_node,
4083                                                          saved_expr1,
4084                                                        ffecom_float_zero_)),
4085                                               ffecom_2 (PLUS_EXPR,
4086                                                         tree_type,
4087                                                         saved_expr1,
4088                                                         ffecom_float_half_),
4089                                               ffecom_2 (MINUS_EXPR,
4090                                                         tree_type,
4091                                                         saved_expr1,
4092                                                      ffecom_float_half_))));
4093       return expr_tree;
4094 #else /* So we instead call floor. */
4095       /* r__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1) */
4096       saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4097       return
4098         convert (tree_type,
4099                  ffecom_3 (COND_EXPR, double_type_node,
4100                            ffecom_truth_value
4101                            (ffecom_2 (GE_EXPR, integer_type_node,
4102                                       saved_expr1,
4103                                       convert (arg1_type,
4104                                                ffecom_float_zero_))),
4105                            ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4106                                              build_tree_list (NULL_TREE,
4107                                                   convert (double_type_node,
4108                                                            ffecom_2 (PLUS_EXPR,
4109                                                                      arg1_type,
4110                                                                      saved_expr1,
4111                                                                      convert (arg1_type,
4112                                                                               ffecom_float_half_)))),
4113                                              NULL_TREE),
4114                            ffecom_1 (NEGATE_EXPR, double_type_node,
4115                                      ffecom_call_gfrt (FFECOM_gfrtL_FLOOR,
4116                                                        build_tree_list (NULL_TREE,
4117                                                                         convert (double_type_node,
4118                                                                                  ffecom_2 (MINUS_EXPR,
4119                                                                                            arg1_type,
4120                                                                                            convert (arg1_type,
4121                                                                                                     ffecom_float_half_),
4122                                                                                            saved_expr1))),
4123                                                        NULL_TREE))
4124                            )
4125                  );
4126 #endif
4127
4128     case FFEINTRIN_impASIN:
4129     case FFEINTRIN_impDASIN:
4130     case FFEINTRIN_impATAN:
4131     case FFEINTRIN_impDATAN:
4132     case FFEINTRIN_impATAN2:
4133     case FFEINTRIN_impDATAN2:
4134       break;
4135
4136     case FFEINTRIN_impCHAR:
4137     case FFEINTRIN_impACHAR:
4138 #ifdef HOHO
4139       tempvar = ffecom_make_tempvar (char_type_node, 1, -1);
4140 #else
4141       tempvar = ffebld_nonter_hook (expr);
4142       assert (tempvar);
4143 #endif
4144       {
4145         tree tmv = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (tempvar)));
4146
4147         expr_tree = ffecom_modify (tmv,
4148                                    ffecom_2 (ARRAY_REF, tmv, tempvar,
4149                                              integer_one_node),
4150                                    convert (tmv, ffecom_expr (arg1)));
4151       }
4152       expr_tree = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (tempvar),
4153                             expr_tree,
4154                             tempvar);
4155       expr_tree = ffecom_1 (ADDR_EXPR,
4156                             build_pointer_type (TREE_TYPE (expr_tree)),
4157                             expr_tree);
4158       return expr_tree;
4159
4160     case FFEINTRIN_impCMPLX:
4161     case FFEINTRIN_impDCMPLX:
4162       if (arg2 == NULL)
4163         return
4164           convert (tree_type, ffecom_expr (arg1));
4165
4166       real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4167       return
4168         ffecom_2 (COMPLEX_EXPR, tree_type,
4169                   convert (real_type, ffecom_expr (arg1)),
4170                   convert (real_type,
4171                            ffecom_expr (arg2)));
4172
4173     case FFEINTRIN_impCOMPLEX:
4174       return
4175         ffecom_2 (COMPLEX_EXPR, tree_type,
4176                   ffecom_expr (arg1),
4177                   ffecom_expr (arg2));
4178
4179     case FFEINTRIN_impCONJG:
4180     case FFEINTRIN_impDCONJG:
4181       {
4182         tree arg1_tree;
4183
4184         real_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
4185         arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4186         return
4187           ffecom_2 (COMPLEX_EXPR, tree_type,
4188                     ffecom_1 (REALPART_EXPR, real_type, arg1_tree),
4189                     ffecom_1 (NEGATE_EXPR, real_type,
4190                               ffecom_1 (IMAGPART_EXPR, real_type, arg1_tree)));
4191       }
4192
4193     case FFEINTRIN_impCOS:
4194     case FFEINTRIN_impCCOS:
4195     case FFEINTRIN_impCDCOS:
4196     case FFEINTRIN_impDCOS:
4197       if (bt == FFEINFO_basictypeCOMPLEX)
4198         {
4199           if (kt == FFEINFO_kindtypeREAL1)
4200             gfrt = FFECOM_gfrtCCOS;     /* Overlapping result okay. */
4201           else if (kt == FFEINFO_kindtypeREAL2)
4202             gfrt = FFECOM_gfrtCDCOS;    /* Overlapping result okay. */
4203         }
4204       break;
4205
4206     case FFEINTRIN_impCOSH:
4207     case FFEINTRIN_impDCOSH:
4208       break;
4209
4210     case FFEINTRIN_impDBLE:
4211     case FFEINTRIN_impDFLOAT:
4212     case FFEINTRIN_impDREAL:
4213     case FFEINTRIN_impFLOAT:
4214     case FFEINTRIN_impIDINT:
4215     case FFEINTRIN_impIFIX:
4216     case FFEINTRIN_impINT2:
4217     case FFEINTRIN_impINT8:
4218     case FFEINTRIN_impINT:
4219     case FFEINTRIN_impLONG:
4220     case FFEINTRIN_impREAL:
4221     case FFEINTRIN_impSHORT:
4222     case FFEINTRIN_impSNGL:
4223       return convert (tree_type, ffecom_expr (arg1));
4224
4225     case FFEINTRIN_impDIM:
4226     case FFEINTRIN_impDDIM:
4227     case FFEINTRIN_impIDIM:
4228       saved_expr1 = ffecom_save_tree (convert (tree_type,
4229                                                ffecom_expr (arg1)));
4230       saved_expr2 = ffecom_save_tree (convert (tree_type,
4231                                                ffecom_expr (arg2)));
4232       return
4233         ffecom_3 (COND_EXPR, tree_type,
4234                   ffecom_truth_value
4235                   (ffecom_2 (GT_EXPR, integer_type_node,
4236                              saved_expr1,
4237                              saved_expr2)),
4238                   ffecom_2 (MINUS_EXPR, tree_type,
4239                             saved_expr1,
4240                             saved_expr2),
4241                   convert (tree_type, ffecom_float_zero_));
4242
4243     case FFEINTRIN_impDPROD:
4244       return
4245         ffecom_2 (MULT_EXPR, tree_type,
4246                   convert (tree_type, ffecom_expr (arg1)),
4247                   convert (tree_type, ffecom_expr (arg2)));
4248
4249     case FFEINTRIN_impEXP:
4250     case FFEINTRIN_impCDEXP:
4251     case FFEINTRIN_impCEXP:
4252     case FFEINTRIN_impDEXP:
4253       if (bt == FFEINFO_basictypeCOMPLEX)
4254         {
4255           if (kt == FFEINFO_kindtypeREAL1)
4256             gfrt = FFECOM_gfrtCEXP;     /* Overlapping result okay. */
4257           else if (kt == FFEINFO_kindtypeREAL2)
4258             gfrt = FFECOM_gfrtCDEXP;    /* Overlapping result okay. */
4259         }
4260       break;
4261
4262     case FFEINTRIN_impICHAR:
4263     case FFEINTRIN_impIACHAR:
4264 #if 0                           /* The simple approach. */
4265       ffecom_char_args_ (&expr_tree, &saved_expr1 /* Ignored */ , arg1);
4266       expr_tree
4267         = ffecom_1 (INDIRECT_REF,
4268                     TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4269                     expr_tree);
4270       expr_tree
4271         = ffecom_2 (ARRAY_REF,
4272                     TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
4273                     expr_tree,
4274                     integer_one_node);
4275       return convert (tree_type, expr_tree);
4276 #else /* The more interesting (and more optimal) approach. */
4277       expr_tree = ffecom_intrinsic_ichar_ (tree_type, arg1, &saved_expr1);
4278       expr_tree = ffecom_3 (COND_EXPR, tree_type,
4279                             saved_expr1,
4280                             expr_tree,
4281                             convert (tree_type, integer_zero_node));
4282       return expr_tree;
4283 #endif
4284
4285     case FFEINTRIN_impINDEX:
4286       break;
4287
4288     case FFEINTRIN_impLEN:
4289 #if 0
4290       break;                                    /* The simple approach. */
4291 #else
4292       return ffecom_intrinsic_len_ (arg1);      /* The more optimal approach. */
4293 #endif
4294
4295     case FFEINTRIN_impLGE:
4296     case FFEINTRIN_impLGT:
4297     case FFEINTRIN_impLLE:
4298     case FFEINTRIN_impLLT:
4299       break;
4300
4301     case FFEINTRIN_impLOG:
4302     case FFEINTRIN_impALOG:
4303     case FFEINTRIN_impCDLOG:
4304     case FFEINTRIN_impCLOG:
4305     case FFEINTRIN_impDLOG:
4306       if (bt == FFEINFO_basictypeCOMPLEX)
4307         {
4308           if (kt == FFEINFO_kindtypeREAL1)
4309             gfrt = FFECOM_gfrtCLOG;     /* Overlapping result okay. */
4310           else if (kt == FFEINFO_kindtypeREAL2)
4311             gfrt = FFECOM_gfrtCDLOG;    /* Overlapping result okay. */
4312         }
4313       break;
4314
4315     case FFEINTRIN_impLOG10:
4316     case FFEINTRIN_impALOG10:
4317     case FFEINTRIN_impDLOG10:
4318       if (gfrt != FFECOM_gfrt)
4319         break;  /* Already picked one, stick with it. */
4320
4321       if (kt == FFEINFO_kindtypeREAL1)
4322         gfrt = FFECOM_gfrtALOG10;
4323       else if (kt == FFEINFO_kindtypeREAL2)
4324         gfrt = FFECOM_gfrtDLOG10;
4325       break;
4326
4327     case FFEINTRIN_impMAX:
4328     case FFEINTRIN_impAMAX0:
4329     case FFEINTRIN_impAMAX1:
4330     case FFEINTRIN_impDMAX1:
4331     case FFEINTRIN_impMAX0:
4332     case FFEINTRIN_impMAX1:
4333       if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4334         arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4335       else
4336         arg1_type = tree_type;
4337       expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4338                             convert (arg1_type, ffecom_expr (arg1)),
4339                             convert (arg1_type, ffecom_expr (arg2)));
4340       for (; list != NULL; list = ffebld_trail (list))
4341         {
4342           if ((ffebld_head (list) == NULL)
4343               || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4344             continue;
4345           expr_tree = ffecom_2 (MAX_EXPR, arg1_type,
4346                                 expr_tree,
4347                                 convert (arg1_type,
4348                                          ffecom_expr (ffebld_head (list))));
4349         }
4350       return convert (tree_type, expr_tree);
4351
4352     case FFEINTRIN_impMIN:
4353     case FFEINTRIN_impAMIN0:
4354     case FFEINTRIN_impAMIN1:
4355     case FFEINTRIN_impDMIN1:
4356     case FFEINTRIN_impMIN0:
4357     case FFEINTRIN_impMIN1:
4358       if (bt != ffeinfo_basictype (ffebld_info (arg1)))
4359         arg1_type = ffecom_widest_expr_type_ (ffebld_right (expr));
4360       else
4361         arg1_type = tree_type;
4362       expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4363                             convert (arg1_type, ffecom_expr (arg1)),
4364                             convert (arg1_type, ffecom_expr (arg2)));
4365       for (; list != NULL; list = ffebld_trail (list))
4366         {
4367           if ((ffebld_head (list) == NULL)
4368               || (ffebld_op (ffebld_head (list)) == FFEBLD_opANY))
4369             continue;
4370           expr_tree = ffecom_2 (MIN_EXPR, arg1_type,
4371                                 expr_tree,
4372                                 convert (arg1_type,
4373                                          ffecom_expr (ffebld_head (list))));
4374         }
4375       return convert (tree_type, expr_tree);
4376
4377     case FFEINTRIN_impMOD:
4378     case FFEINTRIN_impAMOD:
4379     case FFEINTRIN_impDMOD:
4380       if (bt != FFEINFO_basictypeREAL)
4381         return ffecom_2 (TRUNC_MOD_EXPR, tree_type,
4382                          convert (tree_type, ffecom_expr (arg1)),
4383                          convert (tree_type, ffecom_expr (arg2)));
4384
4385       if (kt == FFEINFO_kindtypeREAL1)
4386         gfrt = FFECOM_gfrtAMOD;
4387       else if (kt == FFEINFO_kindtypeREAL2)
4388         gfrt = FFECOM_gfrtDMOD;
4389       break;
4390
4391     case FFEINTRIN_impNINT:
4392     case FFEINTRIN_impIDNINT:
4393 #if 0
4394       /* ~~Ideally FIX_ROUND_EXPR would be implemented, but it ain't yet.  */
4395       return ffecom_1 (FIX_ROUND_EXPR, tree_type, ffecom_expr (arg1));
4396 #else
4397       /* i__1 = r1 >= 0 ? floor(r1 + .5) : -floor(.5 - r1); */
4398       saved_expr1 = ffecom_save_tree (ffecom_expr (arg1));
4399       return
4400         convert (ffecom_integer_type_node,
4401                  ffecom_3 (COND_EXPR, arg1_type,
4402                            ffecom_truth_value
4403                            (ffecom_2 (GE_EXPR, integer_type_node,
4404                                       saved_expr1,
4405                                       convert (arg1_type,
4406                                                ffecom_float_zero_))),
4407                            ffecom_2 (PLUS_EXPR, arg1_type,
4408                                      saved_expr1,
4409                                      convert (arg1_type,
4410                                               ffecom_float_half_)),
4411                            ffecom_2 (MINUS_EXPR, arg1_type,
4412                                      saved_expr1,
4413                                      convert (arg1_type,
4414                                               ffecom_float_half_))));
4415 #endif
4416
4417     case FFEINTRIN_impSIGN:
4418     case FFEINTRIN_impDSIGN:
4419     case FFEINTRIN_impISIGN:
4420       {
4421         tree arg2_tree = ffecom_expr (arg2);
4422
4423         saved_expr1
4424           = ffecom_save_tree
4425           (ffecom_1 (ABS_EXPR, tree_type,
4426                      convert (tree_type,
4427                               ffecom_expr (arg1))));
4428         expr_tree
4429           = ffecom_3 (COND_EXPR, tree_type,
4430                       ffecom_truth_value
4431                       (ffecom_2 (GE_EXPR, integer_type_node,
4432                                  arg2_tree,
4433                                  convert (TREE_TYPE (arg2_tree),
4434                                           integer_zero_node))),
4435                       saved_expr1,
4436                       ffecom_1 (NEGATE_EXPR, tree_type, saved_expr1));
4437         /* Make sure SAVE_EXPRs get referenced early enough. */
4438         expr_tree
4439           = ffecom_2 (COMPOUND_EXPR, tree_type,
4440                       convert (void_type_node, saved_expr1),
4441                       expr_tree);
4442       }
4443       return expr_tree;
4444
4445     case FFEINTRIN_impSIN:
4446     case FFEINTRIN_impCDSIN:
4447     case FFEINTRIN_impCSIN:
4448     case FFEINTRIN_impDSIN:
4449       if (bt == FFEINFO_basictypeCOMPLEX)
4450         {
4451           if (kt == FFEINFO_kindtypeREAL1)
4452             gfrt = FFECOM_gfrtCSIN;     /* Overlapping result okay. */
4453           else if (kt == FFEINFO_kindtypeREAL2)
4454             gfrt = FFECOM_gfrtCDSIN;    /* Overlapping result okay. */
4455         }
4456       break;
4457
4458     case FFEINTRIN_impSINH:
4459     case FFEINTRIN_impDSINH:
4460       break;
4461
4462     case FFEINTRIN_impSQRT:
4463     case FFEINTRIN_impCDSQRT:
4464     case FFEINTRIN_impCSQRT:
4465     case FFEINTRIN_impDSQRT:
4466       if (bt == FFEINFO_basictypeCOMPLEX)
4467         {
4468           if (kt == FFEINFO_kindtypeREAL1)
4469             gfrt = FFECOM_gfrtCSQRT;    /* Overlapping result okay. */
4470           else if (kt == FFEINFO_kindtypeREAL2)
4471             gfrt = FFECOM_gfrtCDSQRT;   /* Overlapping result okay. */
4472         }
4473       break;
4474
4475     case FFEINTRIN_impTAN:
4476     case FFEINTRIN_impDTAN:
4477     case FFEINTRIN_impTANH:
4478     case FFEINTRIN_impDTANH:
4479       break;
4480
4481     case FFEINTRIN_impREALPART:
4482       if (TREE_CODE (arg1_type) == COMPLEX_TYPE)
4483         arg1_type = TREE_TYPE (arg1_type);
4484       else
4485         arg1_type = TREE_TYPE (TYPE_FIELDS (arg1_type));
4486
4487       return
4488         convert (tree_type,
4489                  ffecom_1 (REALPART_EXPR, arg1_type,
4490                            ffecom_expr (arg1)));
4491
4492     case FFEINTRIN_impIAND:
4493     case FFEINTRIN_impAND:
4494       return ffecom_2 (BIT_AND_EXPR, tree_type,
4495                        convert (tree_type,
4496                                 ffecom_expr (arg1)),
4497                        convert (tree_type,
4498                                 ffecom_expr (arg2)));
4499
4500     case FFEINTRIN_impIOR:
4501     case FFEINTRIN_impOR:
4502       return ffecom_2 (BIT_IOR_EXPR, tree_type,
4503                        convert (tree_type,
4504                                 ffecom_expr (arg1)),
4505                        convert (tree_type,
4506                                 ffecom_expr (arg2)));
4507
4508     case FFEINTRIN_impIEOR:
4509     case FFEINTRIN_impXOR:
4510       return ffecom_2 (BIT_XOR_EXPR, tree_type,
4511                        convert (tree_type,
4512                                 ffecom_expr (arg1)),
4513                        convert (tree_type,
4514                                 ffecom_expr (arg2)));
4515
4516     case FFEINTRIN_impLSHIFT:
4517       return ffecom_2 (LSHIFT_EXPR, tree_type,
4518                        ffecom_expr (arg1),
4519                        convert (integer_type_node,
4520                                 ffecom_expr (arg2)));
4521
4522     case FFEINTRIN_impRSHIFT:
4523       return ffecom_2 (RSHIFT_EXPR, tree_type,
4524                        ffecom_expr (arg1),
4525                        convert (integer_type_node,
4526                                 ffecom_expr (arg2)));
4527
4528     case FFEINTRIN_impNOT:
4529       return ffecom_1 (BIT_NOT_EXPR, tree_type, ffecom_expr (arg1));
4530
4531     case FFEINTRIN_impBIT_SIZE:
4532       return convert (tree_type, TYPE_SIZE (arg1_type));
4533
4534     case FFEINTRIN_impBTEST:
4535       {
4536         ffetargetLogical1 true;
4537         ffetargetLogical1 false;
4538         tree true_tree;
4539         tree false_tree;
4540
4541         ffetarget_logical1 (&true, TRUE);
4542         ffetarget_logical1 (&false, FALSE);
4543         if (true == 1)
4544           true_tree = convert (tree_type, integer_one_node);
4545         else
4546           true_tree = convert (tree_type, build_int_2 (true, 0));
4547         if (false == 0)
4548           false_tree = convert (tree_type, integer_zero_node);
4549         else
4550           false_tree = convert (tree_type, build_int_2 (false, 0));
4551
4552         return
4553           ffecom_3 (COND_EXPR, tree_type,
4554                     ffecom_truth_value
4555                     (ffecom_2 (EQ_EXPR, integer_type_node,
4556                                ffecom_2 (BIT_AND_EXPR, arg1_type,
4557                                          ffecom_expr (arg1),
4558                                          ffecom_2 (LSHIFT_EXPR, arg1_type,
4559                                                    convert (arg1_type,
4560                                                           integer_one_node),
4561                                                    convert (integer_type_node,
4562                                                             ffecom_expr (arg2)))),
4563                                convert (arg1_type,
4564                                         integer_zero_node))),
4565                     false_tree,
4566                     true_tree);
4567       }
4568
4569     case FFEINTRIN_impIBCLR:
4570       return
4571         ffecom_2 (BIT_AND_EXPR, tree_type,
4572                   ffecom_expr (arg1),
4573                   ffecom_1 (BIT_NOT_EXPR, tree_type,
4574                             ffecom_2 (LSHIFT_EXPR, tree_type,
4575                                       convert (tree_type,
4576                                                integer_one_node),
4577                                       convert (integer_type_node,
4578                                                ffecom_expr (arg2)))));
4579
4580     case FFEINTRIN_impIBITS:
4581       {
4582         tree arg3_tree = ffecom_save_tree (convert (integer_type_node,
4583                                                     ffecom_expr (arg3)));
4584         tree uns_type
4585         = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4586
4587         expr_tree
4588           = ffecom_2 (BIT_AND_EXPR, tree_type,
4589                       ffecom_2 (RSHIFT_EXPR, tree_type,
4590                                 ffecom_expr (arg1),
4591                                 convert (integer_type_node,
4592                                          ffecom_expr (arg2))),
4593                       convert (tree_type,
4594                                ffecom_2 (RSHIFT_EXPR, uns_type,
4595                                          ffecom_1 (BIT_NOT_EXPR,
4596                                                    uns_type,
4597                                                    convert (uns_type,
4598                                                         integer_zero_node)),
4599                                          ffecom_2 (MINUS_EXPR,
4600                                                    integer_type_node,
4601                                                    TYPE_SIZE (uns_type),
4602                                                    arg3_tree))));
4603 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4604         expr_tree
4605           = ffecom_3 (COND_EXPR, tree_type,
4606                       ffecom_truth_value
4607                       (ffecom_2 (NE_EXPR, integer_type_node,
4608                                  arg3_tree,
4609                                  integer_zero_node)),
4610                       expr_tree,
4611                       convert (tree_type, integer_zero_node));
4612 #endif
4613       }
4614       return expr_tree;
4615
4616     case FFEINTRIN_impIBSET:
4617       return
4618         ffecom_2 (BIT_IOR_EXPR, tree_type,
4619                   ffecom_expr (arg1),
4620                   ffecom_2 (LSHIFT_EXPR, tree_type,
4621                             convert (tree_type, integer_one_node),
4622                             convert (integer_type_node,
4623                                      ffecom_expr (arg2))));
4624
4625     case FFEINTRIN_impISHFT:
4626       {
4627         tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4628         tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4629                                                     ffecom_expr (arg2)));
4630         tree uns_type
4631         = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4632
4633         expr_tree
4634           = ffecom_3 (COND_EXPR, tree_type,
4635                       ffecom_truth_value
4636                       (ffecom_2 (GE_EXPR, integer_type_node,
4637                                  arg2_tree,
4638                                  integer_zero_node)),
4639                       ffecom_2 (LSHIFT_EXPR, tree_type,
4640                                 arg1_tree,
4641                                 arg2_tree),
4642                       convert (tree_type,
4643                                ffecom_2 (RSHIFT_EXPR, uns_type,
4644                                          convert (uns_type, arg1_tree),
4645                                          ffecom_1 (NEGATE_EXPR,
4646                                                    integer_type_node,
4647                                                    arg2_tree))));
4648 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4649         expr_tree
4650           = ffecom_3 (COND_EXPR, tree_type,
4651                       ffecom_truth_value
4652                       (ffecom_2 (NE_EXPR, integer_type_node,
4653                                  arg2_tree,
4654                                  TYPE_SIZE (uns_type))),
4655                       expr_tree,
4656                       convert (tree_type, integer_zero_node));
4657 #endif
4658         /* Make sure SAVE_EXPRs get referenced early enough. */
4659         expr_tree
4660           = ffecom_2 (COMPOUND_EXPR, tree_type,
4661                       convert (void_type_node, arg1_tree),
4662                       ffecom_2 (COMPOUND_EXPR, tree_type,
4663                                 convert (void_type_node, arg2_tree),
4664                                 expr_tree));
4665       }
4666       return expr_tree;
4667
4668     case FFEINTRIN_impISHFTC:
4669       {
4670         tree arg1_tree = ffecom_save_tree (ffecom_expr (arg1));
4671         tree arg2_tree = ffecom_save_tree (convert (integer_type_node,
4672                                                     ffecom_expr (arg2)));
4673         tree arg3_tree = (arg3 == NULL) ? TYPE_SIZE (tree_type)
4674         : ffecom_save_tree (convert (integer_type_node, ffecom_expr (arg3)));
4675         tree shift_neg;
4676         tree shift_pos;
4677         tree mask_arg1;
4678         tree masked_arg1;
4679         tree uns_type
4680         = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
4681
4682         mask_arg1
4683           = ffecom_2 (LSHIFT_EXPR, tree_type,
4684                       ffecom_1 (BIT_NOT_EXPR, tree_type,
4685                                 convert (tree_type, integer_zero_node)),
4686                       arg3_tree);
4687 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4688         mask_arg1
4689           = ffecom_3 (COND_EXPR, tree_type,
4690                       ffecom_truth_value
4691                       (ffecom_2 (NE_EXPR, integer_type_node,
4692                                  arg3_tree,
4693                                  TYPE_SIZE (uns_type))),
4694                       mask_arg1,
4695                       convert (tree_type, integer_zero_node));
4696 #endif
4697         mask_arg1 = ffecom_save_tree (mask_arg1);
4698         masked_arg1
4699           = ffecom_2 (BIT_AND_EXPR, tree_type,
4700                       arg1_tree,
4701                       ffecom_1 (BIT_NOT_EXPR, tree_type,
4702                                 mask_arg1));
4703         masked_arg1 = ffecom_save_tree (masked_arg1);
4704         shift_neg
4705           = ffecom_2 (BIT_IOR_EXPR, tree_type,
4706                       convert (tree_type,
4707                                ffecom_2 (RSHIFT_EXPR, uns_type,
4708                                          convert (uns_type, masked_arg1),
4709                                          ffecom_1 (NEGATE_EXPR,
4710                                                    integer_type_node,
4711                                                    arg2_tree))),
4712                       ffecom_2 (LSHIFT_EXPR, tree_type,
4713                                 arg1_tree,
4714                                 ffecom_2 (PLUS_EXPR, integer_type_node,
4715                                           arg2_tree,
4716                                           arg3_tree)));
4717         shift_pos
4718           = ffecom_2 (BIT_IOR_EXPR, tree_type,
4719                       ffecom_2 (LSHIFT_EXPR, tree_type,
4720                                 arg1_tree,
4721                                 arg2_tree),
4722                       convert (tree_type,
4723                                ffecom_2 (RSHIFT_EXPR, uns_type,
4724                                          convert (uns_type, masked_arg1),
4725                                          ffecom_2 (MINUS_EXPR,
4726                                                    integer_type_node,
4727                                                    arg3_tree,
4728                                                    arg2_tree))));
4729         expr_tree
4730           = ffecom_3 (COND_EXPR, tree_type,
4731                       ffecom_truth_value
4732                       (ffecom_2 (LT_EXPR, integer_type_node,
4733                                  arg2_tree,
4734                                  integer_zero_node)),
4735                       shift_neg,
4736                       shift_pos);
4737         expr_tree
4738           = ffecom_2 (BIT_IOR_EXPR, tree_type,
4739                       ffecom_2 (BIT_AND_EXPR, tree_type,
4740                                 mask_arg1,
4741                                 arg1_tree),
4742                       ffecom_2 (BIT_AND_EXPR, tree_type,
4743                                 ffecom_1 (BIT_NOT_EXPR, tree_type,
4744                                           mask_arg1),
4745                                 expr_tree));
4746         expr_tree
4747           = ffecom_3 (COND_EXPR, tree_type,
4748                       ffecom_truth_value
4749                       (ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
4750                                  ffecom_2 (EQ_EXPR, integer_type_node,
4751                                            ffecom_1 (ABS_EXPR,
4752                                                      integer_type_node,
4753                                                      arg2_tree),
4754                                            arg3_tree),
4755                                  ffecom_2 (EQ_EXPR, integer_type_node,
4756                                            arg2_tree,
4757                                            integer_zero_node))),
4758                       arg1_tree,
4759                       expr_tree);
4760         /* Make sure SAVE_EXPRs get referenced early enough. */
4761         expr_tree
4762           = ffecom_2 (COMPOUND_EXPR, tree_type,
4763                       convert (void_type_node, arg1_tree),
4764                       ffecom_2 (COMPOUND_EXPR, tree_type,
4765                                 convert (void_type_node, arg2_tree),
4766                                 ffecom_2 (COMPOUND_EXPR, tree_type,
4767                                           convert (void_type_node,
4768                                                    mask_arg1),
4769                                           ffecom_2 (COMPOUND_EXPR, tree_type,
4770                                                     convert (void_type_node,
4771                                                              masked_arg1),
4772                                                     expr_tree))));
4773         expr_tree
4774           = ffecom_2 (COMPOUND_EXPR, tree_type,
4775                       convert (void_type_node,
4776                                arg3_tree),
4777                       expr_tree);
4778       }
4779       return expr_tree;
4780
4781     case FFEINTRIN_impLOC:
4782       {
4783         tree arg1_tree = ffecom_expr (arg1);
4784
4785         expr_tree
4786           = convert (tree_type,
4787                      ffecom_1 (ADDR_EXPR,
4788                                build_pointer_type (TREE_TYPE (arg1_tree)),
4789                                arg1_tree));
4790       }
4791       return expr_tree;
4792
4793     case FFEINTRIN_impMVBITS:
4794       {
4795         tree arg1_tree;
4796         tree arg2_tree;
4797         tree arg3_tree;
4798         ffebld arg4 = ffebld_head (ffebld_trail (list));
4799         tree arg4_tree;
4800         tree arg4_type;
4801         ffebld arg5 = ffebld_head (ffebld_trail (ffebld_trail (list)));
4802         tree arg5_tree;
4803         tree prep_arg1;
4804         tree prep_arg4;
4805         tree arg5_plus_arg3;
4806
4807         arg2_tree = convert (integer_type_node,
4808                              ffecom_expr (arg2));
4809         arg3_tree = ffecom_save_tree (convert (integer_type_node,
4810                                                ffecom_expr (arg3)));
4811         arg4_tree = ffecom_expr_rw (NULL_TREE, arg4);
4812         arg4_type = TREE_TYPE (arg4_tree);
4813
4814         arg1_tree = ffecom_save_tree (convert (arg4_type,
4815                                                ffecom_expr (arg1)));
4816
4817         arg5_tree = ffecom_save_tree (convert (integer_type_node,
4818                                                ffecom_expr (arg5)));
4819
4820         prep_arg1
4821           = ffecom_2 (LSHIFT_EXPR, arg4_type,
4822                       ffecom_2 (BIT_AND_EXPR, arg4_type,
4823                                 ffecom_2 (RSHIFT_EXPR, arg4_type,
4824                                           arg1_tree,
4825                                           arg2_tree),
4826                                 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4827                                           ffecom_2 (LSHIFT_EXPR, arg4_type,
4828                                                     ffecom_1 (BIT_NOT_EXPR,
4829                                                               arg4_type,
4830                                                               convert
4831                                                               (arg4_type,
4832                                                         integer_zero_node)),
4833                                                     arg3_tree))),
4834                       arg5_tree);
4835         arg5_plus_arg3
4836           = ffecom_save_tree (ffecom_2 (PLUS_EXPR, arg4_type,
4837                                         arg5_tree,
4838                                         arg3_tree));
4839         prep_arg4
4840           = ffecom_2 (LSHIFT_EXPR, arg4_type,
4841                       ffecom_1 (BIT_NOT_EXPR, arg4_type,
4842                                 convert (arg4_type,
4843                                          integer_zero_node)),
4844                       arg5_plus_arg3);
4845 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4846         prep_arg4
4847           = ffecom_3 (COND_EXPR, arg4_type,
4848                       ffecom_truth_value
4849                       (ffecom_2 (NE_EXPR, integer_type_node,
4850                                  arg5_plus_arg3,
4851                                  convert (TREE_TYPE (arg5_plus_arg3),
4852                                           TYPE_SIZE (arg4_type)))),
4853                       prep_arg4,
4854                       convert (arg4_type, integer_zero_node));
4855 #endif
4856         prep_arg4
4857           = ffecom_2 (BIT_AND_EXPR, arg4_type,
4858                       arg4_tree,
4859                       ffecom_2 (BIT_IOR_EXPR, arg4_type,
4860                                 prep_arg4,
4861                                 ffecom_1 (BIT_NOT_EXPR, arg4_type,
4862                                           ffecom_2 (LSHIFT_EXPR, arg4_type,
4863                                                     ffecom_1 (BIT_NOT_EXPR,
4864                                                               arg4_type,
4865                                                               convert
4866                                                               (arg4_type,
4867                                                         integer_zero_node)),
4868                                                     arg5_tree))));
4869         prep_arg1
4870           = ffecom_2 (BIT_IOR_EXPR, arg4_type,
4871                       prep_arg1,
4872                       prep_arg4);
4873 #if !defined(TREE_SHIFT_FULLWIDTH) || !TREE_SHIFT_FULLWIDTH
4874         prep_arg1
4875           = ffecom_3 (COND_EXPR, arg4_type,
4876                       ffecom_truth_value
4877                       (ffecom_2 (NE_EXPR, integer_type_node,
4878                                  arg3_tree,
4879                                  convert (TREE_TYPE (arg3_tree),
4880                                           integer_zero_node))),
4881                       prep_arg1,
4882                       arg4_tree);
4883         prep_arg1
4884           = ffecom_3 (COND_EXPR, arg4_type,
4885                       ffecom_truth_value
4886                       (ffecom_2 (NE_EXPR, integer_type_node,
4887                                  arg3_tree,
4888                                  convert (TREE_TYPE (arg3_tree),
4889                                           TYPE_SIZE (arg4_type)))),
4890                       prep_arg1,
4891                       arg1_tree);
4892 #endif
4893         expr_tree
4894           = ffecom_2s (MODIFY_EXPR, void_type_node,
4895                        arg4_tree,
4896                        prep_arg1);
4897         /* Make sure SAVE_EXPRs get referenced early enough. */
4898         expr_tree
4899           = ffecom_2 (COMPOUND_EXPR, void_type_node,
4900                       arg1_tree,
4901                       ffecom_2 (COMPOUND_EXPR, void_type_node,
4902                                 arg3_tree,
4903                                 ffecom_2 (COMPOUND_EXPR, void_type_node,
4904                                           arg5_tree,
4905                                           ffecom_2 (COMPOUND_EXPR, void_type_node,
4906                                                     arg5_plus_arg3,
4907                                                     expr_tree))));
4908         expr_tree
4909           = ffecom_2 (COMPOUND_EXPR, void_type_node,
4910                       arg4_tree,
4911                       expr_tree);
4912
4913       }
4914       return expr_tree;
4915
4916     case FFEINTRIN_impDERF:
4917     case FFEINTRIN_impERF:
4918     case FFEINTRIN_impDERFC:
4919     case FFEINTRIN_impERFC:
4920       break;
4921
4922     case FFEINTRIN_impIARGC:
4923       /* extern int xargc; i__1 = xargc - 1; */
4924       expr_tree = ffecom_2 (MINUS_EXPR, TREE_TYPE (ffecom_tree_xargc_),
4925                             ffecom_tree_xargc_,
4926                             convert (TREE_TYPE (ffecom_tree_xargc_),
4927                                      integer_one_node));
4928       return expr_tree;
4929
4930     case FFEINTRIN_impSIGNAL_func:
4931     case FFEINTRIN_impSIGNAL_subr:
4932       {
4933         tree arg1_tree;
4934         tree arg2_tree;
4935         tree arg3_tree;
4936
4937         arg1_tree = convert (ffecom_f2c_integer_type_node,
4938                              ffecom_expr (arg1));
4939         arg1_tree = ffecom_1 (ADDR_EXPR,
4940                               build_pointer_type (TREE_TYPE (arg1_tree)),
4941                               arg1_tree);
4942
4943         /* Pass procedure as a pointer to it, anything else by value.  */
4944         if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4945           arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4946         else
4947           arg2_tree = ffecom_ptr_to_expr (arg2);
4948         arg2_tree = convert (TREE_TYPE (null_pointer_node),
4949                              arg2_tree);
4950
4951         if (arg3 != NULL)
4952           arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
4953         else
4954           arg3_tree = NULL_TREE;
4955
4956         arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
4957         arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
4958         TREE_CHAIN (arg1_tree) = arg2_tree;
4959
4960         expr_tree
4961           = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
4962                           ffecom_gfrt_kindtype (gfrt),
4963                           FALSE,
4964                           ((codegen_imp == FFEINTRIN_impSIGNAL_subr) ?
4965                            NULL_TREE :
4966                            tree_type),
4967                           arg1_tree,
4968                           NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
4969                           ffebld_nonter_hook (expr));
4970
4971         if (arg3_tree != NULL_TREE)
4972           expr_tree
4973             = ffecom_modify (NULL_TREE, arg3_tree,
4974                              convert (TREE_TYPE (arg3_tree),
4975                                       expr_tree));
4976       }
4977       return expr_tree;
4978
4979     case FFEINTRIN_impALARM:
4980       {
4981         tree arg1_tree;
4982         tree arg2_tree;
4983         tree arg3_tree;
4984
4985         arg1_tree = convert (ffecom_f2c_integer_type_node,
4986                              ffecom_expr (arg1));
4987         arg1_tree = ffecom_1 (ADDR_EXPR,
4988                               build_pointer_type (TREE_TYPE (arg1_tree)),
4989                               arg1_tree);
4990
4991         /* Pass procedure as a pointer to it, anything else by value.  */
4992         if (ffeinfo_kind (ffebld_info (arg2)) == FFEINFO_kindENTITY)
4993           arg2_tree = convert (integer_type_node, ffecom_expr (arg2));
4994         else
4995           arg2_tree = ffecom_ptr_to_expr (arg2);
4996         arg2_tree = convert (TREE_TYPE (null_pointer_node),
4997                              arg2_tree);
4998
4999         if (arg3 != NULL)
5000           arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5001         else
5002           arg3_tree = NULL_TREE;
5003
5004         arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5005         arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5006         TREE_CHAIN (arg1_tree) = arg2_tree;
5007
5008         expr_tree
5009           = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5010                           ffecom_gfrt_kindtype (gfrt),
5011                           FALSE,
5012                           NULL_TREE,
5013                           arg1_tree,
5014                           NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5015                           ffebld_nonter_hook (expr));
5016
5017         if (arg3_tree != NULL_TREE)
5018           expr_tree
5019             = ffecom_modify (NULL_TREE, arg3_tree,
5020                              convert (TREE_TYPE (arg3_tree),
5021                                       expr_tree));
5022       }
5023       return expr_tree;
5024
5025     case FFEINTRIN_impCHDIR_subr:
5026     case FFEINTRIN_impFDATE_subr:
5027     case FFEINTRIN_impFGET_subr:
5028     case FFEINTRIN_impFPUT_subr:
5029     case FFEINTRIN_impGETCWD_subr:
5030     case FFEINTRIN_impHOSTNM_subr:
5031     case FFEINTRIN_impSYSTEM_subr:
5032     case FFEINTRIN_impUNLINK_subr:
5033       {
5034         tree arg1_len = integer_zero_node;
5035         tree arg1_tree;
5036         tree arg2_tree;
5037
5038         arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5039
5040         if (arg2 != NULL)
5041           arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5042         else
5043           arg2_tree = NULL_TREE;
5044
5045         arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5046         arg1_len = build_tree_list (NULL_TREE, arg1_len);
5047         TREE_CHAIN (arg1_tree) = arg1_len;
5048
5049         expr_tree
5050           = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5051                           ffecom_gfrt_kindtype (gfrt),
5052                           FALSE,
5053                           NULL_TREE,
5054                           arg1_tree,
5055                           NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5056                           ffebld_nonter_hook (expr));
5057
5058         if (arg2_tree != NULL_TREE)
5059           expr_tree
5060             = ffecom_modify (NULL_TREE, arg2_tree,
5061                              convert (TREE_TYPE (arg2_tree),
5062                                       expr_tree));
5063       }
5064       return expr_tree;
5065
5066     case FFEINTRIN_impEXIT:
5067       if (arg1 != NULL)
5068         break;
5069
5070       expr_tree = build_tree_list (NULL_TREE,
5071                                    ffecom_1 (ADDR_EXPR,
5072                                              build_pointer_type
5073                                              (ffecom_integer_type_node),
5074                                              integer_zero_node));
5075
5076       return
5077         ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5078                       ffecom_gfrt_kindtype (gfrt),
5079                       FALSE,
5080                       void_type_node,
5081                       expr_tree,
5082                       NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5083                       ffebld_nonter_hook (expr));
5084
5085     case FFEINTRIN_impFLUSH:
5086       if (arg1 == NULL)
5087         gfrt = FFECOM_gfrtFLUSH;
5088       else
5089         gfrt = FFECOM_gfrtFLUSH1;
5090       break;
5091
5092     case FFEINTRIN_impCHMOD_subr:
5093     case FFEINTRIN_impLINK_subr:
5094     case FFEINTRIN_impRENAME_subr:
5095     case FFEINTRIN_impSYMLNK_subr:
5096       {
5097         tree arg1_len = integer_zero_node;
5098         tree arg1_tree;
5099         tree arg2_len = integer_zero_node;
5100         tree arg2_tree;
5101         tree arg3_tree;
5102
5103         arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5104         arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5105         if (arg3 != NULL)
5106           arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5107         else
5108           arg3_tree = NULL_TREE;
5109
5110         arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5111         arg1_len = build_tree_list (NULL_TREE, arg1_len);
5112         arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5113         arg2_len = build_tree_list (NULL_TREE, arg2_len);
5114         TREE_CHAIN (arg1_tree) = arg2_tree;
5115         TREE_CHAIN (arg2_tree) = arg1_len;
5116         TREE_CHAIN (arg1_len) = arg2_len;
5117         expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5118                                   ffecom_gfrt_kindtype (gfrt),
5119                                   FALSE,
5120                                   NULL_TREE,
5121                                   arg1_tree,
5122                                   NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5123                                   ffebld_nonter_hook (expr));
5124         if (arg3_tree != NULL_TREE)
5125           expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5126                                      convert (TREE_TYPE (arg3_tree),
5127                                               expr_tree));
5128       }
5129       return expr_tree;
5130
5131     case FFEINTRIN_impLSTAT_subr:
5132     case FFEINTRIN_impSTAT_subr:
5133       {
5134         tree arg1_len = integer_zero_node;
5135         tree arg1_tree;
5136         tree arg2_tree;
5137         tree arg3_tree;
5138
5139         arg1_tree = ffecom_arg_ptr_to_expr (arg1, &arg1_len);
5140
5141         arg2_tree = ffecom_ptr_to_expr (arg2);
5142
5143         if (arg3 != NULL)
5144           arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5145         else
5146           arg3_tree = NULL_TREE;
5147
5148         arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5149         arg1_len = build_tree_list (NULL_TREE, arg1_len);
5150         arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5151         TREE_CHAIN (arg1_tree) = arg2_tree;
5152         TREE_CHAIN (arg2_tree) = arg1_len;
5153         expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5154                                   ffecom_gfrt_kindtype (gfrt),
5155                                   FALSE,
5156                                   NULL_TREE,
5157                                   arg1_tree,
5158                                   NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5159                                   ffebld_nonter_hook (expr));
5160         if (arg3_tree != NULL_TREE)
5161           expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5162                                      convert (TREE_TYPE (arg3_tree),
5163                                               expr_tree));
5164       }
5165       return expr_tree;
5166
5167     case FFEINTRIN_impFGETC_subr:
5168     case FFEINTRIN_impFPUTC_subr:
5169       {
5170         tree arg1_tree;
5171         tree arg2_tree;
5172         tree arg2_len = integer_zero_node;
5173         tree arg3_tree;
5174
5175         arg1_tree = convert (ffecom_f2c_integer_type_node,
5176                              ffecom_expr (arg1));
5177         arg1_tree = ffecom_1 (ADDR_EXPR,
5178                               build_pointer_type (TREE_TYPE (arg1_tree)),
5179                               arg1_tree);
5180
5181         arg2_tree = ffecom_arg_ptr_to_expr (arg2, &arg2_len);
5182         arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5183
5184         arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5185         arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5186         arg2_len = build_tree_list (NULL_TREE, arg2_len);
5187         TREE_CHAIN (arg1_tree) = arg2_tree;
5188         TREE_CHAIN (arg2_tree) = arg2_len;
5189
5190         expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5191                                   ffecom_gfrt_kindtype (gfrt),
5192                                   FALSE,
5193                                   NULL_TREE,
5194                                   arg1_tree,
5195                                   NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5196                                   ffebld_nonter_hook (expr));
5197         expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5198                                    convert (TREE_TYPE (arg3_tree),
5199                                             expr_tree));
5200       }
5201       return expr_tree;
5202
5203     case FFEINTRIN_impFSTAT_subr:
5204       {
5205         tree arg1_tree;
5206         tree arg2_tree;
5207         tree arg3_tree;
5208
5209         arg1_tree = convert (ffecom_f2c_integer_type_node,
5210                              ffecom_expr (arg1));
5211         arg1_tree = ffecom_1 (ADDR_EXPR,
5212                               build_pointer_type (TREE_TYPE (arg1_tree)),
5213                               arg1_tree);
5214
5215         arg2_tree = convert (ffecom_f2c_ptr_to_integer_type_node,
5216                              ffecom_ptr_to_expr (arg2));
5217
5218         if (arg3 == NULL)
5219           arg3_tree = NULL_TREE;
5220         else
5221           arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5222
5223         arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5224         arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5225         TREE_CHAIN (arg1_tree) = arg2_tree;
5226         expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5227                                   ffecom_gfrt_kindtype (gfrt),
5228                                   FALSE,
5229                                   NULL_TREE,
5230                                   arg1_tree,
5231                                   NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5232                                   ffebld_nonter_hook (expr));
5233         if (arg3_tree != NULL_TREE) {
5234           expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5235                                      convert (TREE_TYPE (arg3_tree),
5236                                               expr_tree));
5237         }
5238       }
5239       return expr_tree;
5240
5241     case FFEINTRIN_impKILL_subr:
5242       {
5243         tree arg1_tree;
5244         tree arg2_tree;
5245         tree arg3_tree;
5246
5247         arg1_tree = convert (ffecom_f2c_integer_type_node,
5248                              ffecom_expr (arg1));
5249         arg1_tree = ffecom_1 (ADDR_EXPR,
5250                               build_pointer_type (TREE_TYPE (arg1_tree)),
5251                               arg1_tree);
5252
5253         arg2_tree = convert (ffecom_f2c_integer_type_node,
5254                              ffecom_expr (arg2));
5255         arg2_tree = ffecom_1 (ADDR_EXPR,
5256                               build_pointer_type (TREE_TYPE (arg2_tree)),
5257                               arg2_tree);
5258
5259         if (arg3 == NULL)
5260           arg3_tree = NULL_TREE;
5261         else
5262           arg3_tree = ffecom_expr_w (NULL_TREE, arg3);
5263
5264         arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5265         arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5266         TREE_CHAIN (arg1_tree) = arg2_tree;
5267         expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5268                                   ffecom_gfrt_kindtype (gfrt),
5269                                   FALSE,
5270                                   NULL_TREE,
5271                                   arg1_tree,
5272                                   NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5273                                   ffebld_nonter_hook (expr));
5274         if (arg3_tree != NULL_TREE) {
5275           expr_tree = ffecom_modify (NULL_TREE, arg3_tree,
5276                                      convert (TREE_TYPE (arg3_tree),
5277                                               expr_tree));
5278         }
5279       }
5280       return expr_tree;
5281
5282     case FFEINTRIN_impCTIME_subr:
5283     case FFEINTRIN_impTTYNAM_subr:
5284       {
5285         tree arg1_len = integer_zero_node;
5286         tree arg1_tree;
5287         tree arg2_tree;
5288
5289         arg1_tree = ffecom_arg_ptr_to_expr (arg2, &arg1_len);
5290
5291         arg2_tree = convert (((codegen_imp == FFEINTRIN_impCTIME_subr) ?
5292                               ffecom_f2c_longint_type_node :
5293                               ffecom_f2c_integer_type_node),
5294                              ffecom_expr (arg1));
5295         arg2_tree = ffecom_1 (ADDR_EXPR,
5296                               build_pointer_type (TREE_TYPE (arg2_tree)),
5297                               arg2_tree);
5298
5299         arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5300         arg1_len = build_tree_list (NULL_TREE, arg1_len);
5301         arg2_tree = build_tree_list (NULL_TREE, arg2_tree);
5302         TREE_CHAIN (arg1_len) = arg2_tree;
5303         TREE_CHAIN (arg1_tree) = arg1_len;
5304
5305         expr_tree
5306           = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5307                           ffecom_gfrt_kindtype (gfrt),
5308                           FALSE,
5309                           NULL_TREE,
5310                           arg1_tree,
5311                           NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5312                           ffebld_nonter_hook (expr));
5313         TREE_SIDE_EFFECTS (expr_tree) = 1;
5314       }
5315       return expr_tree;
5316
5317     case FFEINTRIN_impIRAND:
5318     case FFEINTRIN_impRAND:
5319       /* Arg defaults to 0 (normal random case) */
5320       {
5321         tree arg1_tree;
5322
5323         if (arg1 == NULL)
5324           arg1_tree = ffecom_integer_zero_node;
5325         else
5326           arg1_tree = ffecom_expr (arg1);
5327         arg1_tree = convert (ffecom_f2c_integer_type_node,
5328                              arg1_tree);
5329         arg1_tree = ffecom_1 (ADDR_EXPR,
5330                               build_pointer_type (TREE_TYPE (arg1_tree)),
5331                               arg1_tree);
5332         arg1_tree = build_tree_list (NULL_TREE, arg1_tree);
5333
5334         expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5335                                   ffecom_gfrt_kindtype (gfrt),
5336                                   FALSE,
5337                                   ((codegen_imp == FFEINTRIN_impIRAND) ?
5338                                    ffecom_f2c_integer_type_node :
5339                                    ffecom_f2c_real_type_node),
5340                                   arg1_tree,
5341                                   dest_tree, dest, dest_used,
5342                                   NULL_TREE, TRUE,
5343                                   ffebld_nonter_hook (expr));
5344       }
5345       return expr_tree;
5346
5347     case FFEINTRIN_impFTELL_subr:
5348     case FFEINTRIN_impUMASK_subr:
5349       {
5350         tree arg1_tree;
5351         tree arg2_tree;
5352
5353         arg1_tree = convert (ffecom_f2c_integer_type_node,
5354                              ffecom_expr (arg1));
5355         arg1_tree = ffecom_1 (ADDR_EXPR,
5356                               build_pointer_type (TREE_TYPE (arg1_tree)),
5357                               arg1_tree);
5358
5359         if (arg2 == NULL)
5360           arg2_tree = NULL_TREE;
5361         else
5362           arg2_tree = ffecom_expr_w (NULL_TREE, arg2);
5363
5364         expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5365                                   ffecom_gfrt_kindtype (gfrt),
5366                                   FALSE,
5367                                   NULL_TREE,
5368                                   build_tree_list (NULL_TREE, arg1_tree),
5369                                   NULL_TREE, NULL, NULL, NULL_TREE,
5370                                   TRUE,
5371                                   ffebld_nonter_hook (expr));
5372         if (arg2_tree != NULL_TREE) {
5373           expr_tree = ffecom_modify (NULL_TREE, arg2_tree,
5374                                      convert (TREE_TYPE (arg2_tree),
5375                                               expr_tree));
5376         }
5377       }
5378       return expr_tree;
5379
5380     case FFEINTRIN_impCPU_TIME:
5381     case FFEINTRIN_impSECOND_subr:
5382       {
5383         tree arg1_tree;
5384
5385         arg1_tree = ffecom_expr_w (NULL_TREE, arg1);
5386
5387         expr_tree
5388           = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5389                           ffecom_gfrt_kindtype (gfrt),
5390                           FALSE,
5391                           NULL_TREE,
5392                           NULL_TREE,
5393                           NULL_TREE, NULL, NULL, NULL_TREE, TRUE,
5394                           ffebld_nonter_hook (expr));
5395
5396         expr_tree
5397           = ffecom_modify (NULL_TREE, arg1_tree,
5398                            convert (TREE_TYPE (arg1_tree),
5399                                     expr_tree));
5400       }
5401       return expr_tree;
5402
5403     case FFEINTRIN_impDTIME_subr:
5404     case FFEINTRIN_impETIME_subr:
5405       {
5406         tree arg1_tree;
5407         tree result_tree;
5408
5409         result_tree = ffecom_expr_w (NULL_TREE, arg2);
5410
5411         arg1_tree = ffecom_ptr_to_expr (arg1);
5412
5413         expr_tree = ffecom_call_ (ffecom_gfrt_tree_ (gfrt),
5414                                   ffecom_gfrt_kindtype (gfrt),
5415                                   FALSE,
5416                                   NULL_TREE,
5417                                   build_tree_list (NULL_TREE, arg1_tree),
5418                                   NULL_TREE, NULL, NULL, NULL_TREE,
5419                                   TRUE,
5420                                   ffebld_nonter_hook (expr));
5421         expr_tree = ffecom_modify (NULL_TREE, result_tree,
5422                                    convert (TREE_TYPE (result_tree),
5423                                             expr_tree));
5424       }
5425       return expr_tree;
5426
5427       /* Straightforward calls of libf2c routines: */
5428     case FFEINTRIN_impABORT:
5429     case FFEINTRIN_impACCESS:
5430     case FFEINTRIN_impBESJ0:
5431     case FFEINTRIN_impBESJ1:
5432     case FFEINTRIN_impBESJN:
5433     case FFEINTRIN_impBESY0:
5434     case FFEINTRIN_impBESY1:
5435     case FFEINTRIN_impBESYN:
5436     case FFEINTRIN_impCHDIR_func:
5437     case FFEINTRIN_impCHMOD_func:
5438     case FFEINTRIN_impDATE:
5439     case FFEINTRIN_impDATE_AND_TIME:
5440     case FFEINTRIN_impDBESJ0:
5441     case FFEINTRIN_impDBESJ1:
5442     case FFEINTRIN_impDBESJN:
5443     case FFEINTRIN_impDBESY0:
5444     case FFEINTRIN_impDBESY1:
5445     case FFEINTRIN_impDBESYN:
5446     case FFEINTRIN_impDTIME_func:
5447     case FFEINTRIN_impETIME_func:
5448     case FFEINTRIN_impFGETC_func:
5449     case FFEINTRIN_impFGET_func:
5450     case FFEINTRIN_impFNUM:
5451     case FFEINTRIN_impFPUTC_func:
5452     case FFEINTRIN_impFPUT_func:
5453     case FFEINTRIN_impFSEEK:
5454     case FFEINTRIN_impFSTAT_func:
5455     case FFEINTRIN_impFTELL_func:
5456     case FFEINTRIN_impGERROR:
5457     case FFEINTRIN_impGETARG:
5458     case FFEINTRIN_impGETCWD_func:
5459     case FFEINTRIN_impGETENV:
5460     case FFEINTRIN_impGETGID:
5461     case FFEINTRIN_impGETLOG:
5462     case FFEINTRIN_impGETPID:
5463     case FFEINTRIN_impGETUID:
5464     case FFEINTRIN_impGMTIME:
5465     case FFEINTRIN_impHOSTNM_func:
5466     case FFEINTRIN_impIDATE_unix:
5467     case FFEINTRIN_impIDATE_vxt:
5468     case FFEINTRIN_impIERRNO:
5469     case FFEINTRIN_impISATTY:
5470     case FFEINTRIN_impITIME:
5471     case FFEINTRIN_impKILL_func:
5472     case FFEINTRIN_impLINK_func:
5473     case FFEINTRIN_impLNBLNK:
5474     case FFEINTRIN_impLSTAT_func:
5475     case FFEINTRIN_impLTIME:
5476     case FFEINTRIN_impMCLOCK8:
5477     case FFEINTRIN_impMCLOCK:
5478     case FFEINTRIN_impPERROR:
5479     case FFEINTRIN_impRENAME_func:
5480     case FFEINTRIN_impSECNDS:
5481     case FFEINTRIN_impSECOND_func:
5482     case FFEINTRIN_impSLEEP:
5483     case FFEINTRIN_impSRAND:
5484     case FFEINTRIN_impSTAT_func:
5485     case FFEINTRIN_impSYMLNK_func:
5486     case FFEINTRIN_impSYSTEM_CLOCK:
5487     case FFEINTRIN_impSYSTEM_func:
5488     case FFEINTRIN_impTIME8:
5489     case FFEINTRIN_impTIME_unix:
5490     case FFEINTRIN_impTIME_vxt:
5491     case FFEINTRIN_impUMASK_func:
5492     case FFEINTRIN_impUNLINK_func:
5493       break;
5494
5495     case FFEINTRIN_impCTIME_func:       /* CHARACTER functions not handled here. */
5496     case FFEINTRIN_impFDATE_func:       /* CHARACTER functions not handled here. */
5497     case FFEINTRIN_impTTYNAM_func:      /* CHARACTER functions not handled here. */
5498     case FFEINTRIN_impNONE:
5499     case FFEINTRIN_imp:         /* Hush up gcc warning. */
5500       fprintf (stderr, "No %s implementation.\n",
5501                ffeintrin_name_implementation (ffebld_symter_implementation (ffebld_left (expr))));
5502       assert ("unimplemented intrinsic" == NULL);
5503       return error_mark_node;
5504     }
5505
5506   assert (gfrt != FFECOM_gfrt); /* Must have an implementation! */
5507
5508   expr_tree = ffecom_arglist_expr_ (ffecom_gfrt_args_ (gfrt),
5509                                     ffebld_right (expr));
5510
5511   return ffecom_call_ (ffecom_gfrt_tree_ (gfrt), ffecom_gfrt_kindtype (gfrt),
5512                        (ffe_is_f2c_library () && ffecom_gfrt_complex_[gfrt]),
5513                        tree_type,
5514                        expr_tree, dest_tree, dest, dest_used,
5515                        NULL_TREE, TRUE,
5516                        ffebld_nonter_hook (expr));
5517
5518   /* See bottom of this file for f2c transforms used to determine
5519      many of the above implementations.  The info seems to confuse
5520      Emacs's C mode indentation, which is why it's been moved to
5521      the bottom of this source file.  */
5522 }
5523
5524 #endif
5525 /* For power (exponentiation) where right-hand operand is type INTEGER,
5526    generate in-line code to do it the fast way (which, if the operand
5527    is a constant, might just mean a series of multiplies).  */
5528
5529 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5530 static tree
5531 ffecom_expr_power_integer_ (ffebld expr)
5532 {
5533   tree l = ffecom_expr (ffebld_left (expr));
5534   tree r = ffecom_expr (ffebld_right (expr));
5535   tree ltype = TREE_TYPE (l);
5536   tree rtype = TREE_TYPE (r);
5537   tree result = NULL_TREE;
5538
5539   if (l == error_mark_node
5540       || r == error_mark_node)
5541     return error_mark_node;
5542
5543   if (TREE_CODE (r) == INTEGER_CST)
5544     {
5545       int sgn = tree_int_cst_sgn (r);
5546
5547       if (sgn == 0)
5548         return convert (ltype, integer_one_node);
5549
5550       if ((TREE_CODE (ltype) == INTEGER_TYPE)
5551           && (sgn < 0))
5552         {
5553           /* Reciprocal of integer is either 0, -1, or 1, so after
5554              calculating that (which we leave to the back end to do
5555              or not do optimally), don't bother with any multiplying.  */
5556
5557           result = ffecom_tree_divide_ (ltype,
5558                                         convert (ltype, integer_one_node),
5559                                         l,
5560                                         NULL_TREE, NULL, NULL, NULL_TREE);
5561           r = ffecom_1 (NEGATE_EXPR,
5562                         rtype,
5563                         r);
5564           if ((TREE_INT_CST_LOW (r) & 1) == 0)
5565             result = ffecom_1 (ABS_EXPR, rtype,
5566                                result);
5567         }
5568
5569       /* Generate appropriate series of multiplies, preceded
5570          by divide if the exponent is negative.  */
5571
5572       l = save_expr (l);
5573
5574       if (sgn < 0)
5575         {
5576           l = ffecom_tree_divide_ (ltype,
5577                                    convert (ltype, integer_one_node),
5578                                    l,
5579                                    NULL_TREE, NULL, NULL,
5580                                    ffebld_nonter_hook (expr));
5581           r = ffecom_1 (NEGATE_EXPR, rtype, r);
5582           assert (TREE_CODE (r) == INTEGER_CST);
5583
5584           if (tree_int_cst_sgn (r) < 0)
5585             {                   /* The "most negative" number.  */
5586               r = ffecom_1 (NEGATE_EXPR, rtype,
5587                             ffecom_2 (RSHIFT_EXPR, rtype,
5588                                       r,
5589                                       integer_one_node));
5590               l = save_expr (l);
5591               l = ffecom_2 (MULT_EXPR, ltype,
5592                             l,
5593                             l);
5594             }
5595         }
5596
5597       for (;;)
5598         {
5599           if (TREE_INT_CST_LOW (r) & 1)
5600             {
5601               if (result == NULL_TREE)
5602                 result = l;
5603               else
5604                 result = ffecom_2 (MULT_EXPR, ltype,
5605                                    result,
5606                                    l);
5607             }
5608
5609           r = ffecom_2 (RSHIFT_EXPR, rtype,
5610                         r,
5611                         integer_one_node);
5612           if (integer_zerop (r))
5613             break;
5614           assert (TREE_CODE (r) == INTEGER_CST);
5615
5616           l = save_expr (l);
5617           l = ffecom_2 (MULT_EXPR, ltype,
5618                         l,
5619                         l);
5620         }
5621       return result;
5622     }
5623
5624   /* Though rhs isn't a constant, in-line code cannot be expanded
5625      while transforming dummies
5626      because the back end cannot be easily convinced to generate
5627      stores (MODIFY_EXPR), handle temporaries, and so on before
5628      all the appropriate rtx's have been generated for things like
5629      dummy args referenced in rhs -- which doesn't happen until
5630      store_parm_decls() is called (expand_function_start, I believe,
5631      does the actual rtx-stuffing of PARM_DECLs).
5632
5633      So, in this case, let the caller generate the call to the
5634      run-time-library function to evaluate the power for us.  */
5635
5636   if (ffecom_transform_only_dummies_)
5637     return NULL_TREE;
5638
5639   /* Right-hand operand not a constant, expand in-line code to figure
5640      out how to do the multiplies, &c.
5641
5642      The returned expression is expressed this way in GNU C, where l and
5643      r are the "inputs":
5644
5645      ({ typeof (r) rtmp = r;
5646         typeof (l) ltmp = l;
5647         typeof (l) result;
5648
5649         if (rtmp == 0)
5650           result = 1;
5651         else
5652           {
5653             if ((basetypeof (l) == basetypeof (int))
5654                 && (rtmp < 0))
5655               {
5656                 result = ((typeof (l)) 1) / ltmp;
5657                 if ((ltmp < 0) && (((-rtmp) & 1) == 0))
5658                   result = -result;
5659               }
5660             else
5661               {
5662                 result = 1;
5663                 if ((basetypeof (l) != basetypeof (int))
5664                     && (rtmp < 0))
5665                   {
5666                     ltmp = ((typeof (l)) 1) / ltmp;
5667                     rtmp = -rtmp;
5668                     if (rtmp < 0)
5669                       {
5670                         rtmp = -(rtmp >> 1);
5671                         ltmp *= ltmp;
5672                       }
5673                   }
5674                 for (;;)
5675                   {
5676                     if (rtmp & 1)
5677                       result *= ltmp;
5678                     if ((rtmp >>= 1) == 0)
5679                       break;
5680                     ltmp *= ltmp;
5681                   }
5682               }
5683           }
5684         result;
5685      })
5686
5687      Note that some of the above is compile-time collapsable, such as
5688      the first part of the if statements that checks the base type of
5689      l against int.  The if statements are phrased that way to suggest
5690      an easy way to generate the if/else constructs here, knowing that
5691      the back end should (and probably does) eliminate the resulting
5692      dead code (either the int case or the non-int case), something
5693      it couldn't do without the redundant phrasing, requiring explicit
5694      dead-code elimination here, which would be kind of difficult to
5695      read.  */
5696
5697   {
5698     tree rtmp;
5699     tree ltmp;
5700     tree divide;
5701     tree basetypeof_l_is_int;
5702     tree se;
5703     tree t;
5704
5705     basetypeof_l_is_int
5706       = build_int_2 ((TREE_CODE (ltype) == INTEGER_TYPE), 0);
5707
5708     se = expand_start_stmt_expr ();
5709
5710     ffecom_start_compstmt ();
5711
5712 #ifndef HAHA
5713     rtmp = ffecom_make_tempvar ("power_r", rtype,
5714                                 FFETARGET_charactersizeNONE, -1);
5715     ltmp = ffecom_make_tempvar ("power_l", ltype,
5716                                 FFETARGET_charactersizeNONE, -1);
5717     result = ffecom_make_tempvar ("power_res", ltype,
5718                                   FFETARGET_charactersizeNONE, -1);
5719     if (TREE_CODE (ltype) == COMPLEX_TYPE
5720         || TREE_CODE (ltype) == RECORD_TYPE)
5721       divide = ffecom_make_tempvar ("power_div", ltype,
5722                                     FFETARGET_charactersizeNONE, -1);
5723     else
5724       divide = NULL_TREE;
5725 #else  /* HAHA */
5726     {
5727       tree hook;
5728
5729       hook = ffebld_nonter_hook (expr);
5730       assert (hook);
5731       assert (TREE_CODE (hook) == TREE_VEC);
5732       assert (TREE_VEC_LENGTH (hook) == 4);
5733       rtmp = TREE_VEC_ELT (hook, 0);
5734       ltmp = TREE_VEC_ELT (hook, 1);
5735       result = TREE_VEC_ELT (hook, 2);
5736       divide = TREE_VEC_ELT (hook, 3);
5737       if (TREE_CODE (ltype) == COMPLEX_TYPE
5738           || TREE_CODE (ltype) == RECORD_TYPE)
5739         assert (divide);
5740       else
5741         assert (! divide);
5742     }
5743 #endif  /* HAHA */
5744
5745     expand_expr_stmt (ffecom_modify (void_type_node,
5746                                      rtmp,
5747                                      r));
5748     expand_expr_stmt (ffecom_modify (void_type_node,
5749                                      ltmp,
5750                                      l));
5751     expand_start_cond (ffecom_truth_value
5752                        (ffecom_2 (EQ_EXPR, integer_type_node,
5753                                   rtmp,
5754                                   convert (rtype, integer_zero_node))),
5755                        0);
5756     expand_expr_stmt (ffecom_modify (void_type_node,
5757                                      result,
5758                                      convert (ltype, integer_one_node)));
5759     expand_start_else ();
5760     if (! integer_zerop (basetypeof_l_is_int))
5761       {
5762         expand_start_cond (ffecom_2 (LT_EXPR, integer_type_node,
5763                                      rtmp,
5764                                      convert (rtype,
5765                                               integer_zero_node)),
5766                            0);
5767         expand_expr_stmt (ffecom_modify (void_type_node,
5768                                          result,
5769                                          ffecom_tree_divide_
5770                                          (ltype,
5771                                           convert (ltype, integer_one_node),
5772                                           ltmp,
5773                                           NULL_TREE, NULL, NULL,
5774                                           divide)));
5775         expand_start_cond (ffecom_truth_value
5776                            (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5777                                       ffecom_2 (LT_EXPR, integer_type_node,
5778                                                 ltmp,
5779                                                 convert (ltype,
5780                                                          integer_zero_node)),
5781                                       ffecom_2 (EQ_EXPR, integer_type_node,
5782                                                 ffecom_2 (BIT_AND_EXPR,
5783                                                           rtype,
5784                                                           ffecom_1 (NEGATE_EXPR,
5785                                                                     rtype,
5786                                                                     rtmp),
5787                                                           convert (rtype,
5788                                                                    integer_one_node)),
5789                                                 convert (rtype,
5790                                                          integer_zero_node)))),
5791                            0);
5792         expand_expr_stmt (ffecom_modify (void_type_node,
5793                                          result,
5794                                          ffecom_1 (NEGATE_EXPR,
5795                                                    ltype,
5796                                                    result)));
5797         expand_end_cond ();
5798         expand_start_else ();
5799       }
5800     expand_expr_stmt (ffecom_modify (void_type_node,
5801                                      result,
5802                                      convert (ltype, integer_one_node)));
5803     expand_start_cond (ffecom_truth_value
5804                        (ffecom_2 (TRUTH_ANDIF_EXPR, integer_type_node,
5805                                   ffecom_truth_value_invert
5806                                   (basetypeof_l_is_int),
5807                                   ffecom_2 (LT_EXPR, integer_type_node,
5808                                             rtmp,
5809                                             convert (rtype,
5810                                                      integer_zero_node)))),
5811                        0);
5812     expand_expr_stmt (ffecom_modify (void_type_node,
5813                                      ltmp,
5814                                      ffecom_tree_divide_
5815                                      (ltype,
5816                                       convert (ltype, integer_one_node),
5817                                       ltmp,
5818                                       NULL_TREE, NULL, NULL,
5819                                       divide)));
5820     expand_expr_stmt (ffecom_modify (void_type_node,
5821                                      rtmp,
5822                                      ffecom_1 (NEGATE_EXPR, rtype,
5823                                                rtmp)));
5824     expand_start_cond (ffecom_truth_value
5825                        (ffecom_2 (LT_EXPR, integer_type_node,
5826                                   rtmp,
5827                                   convert (rtype, integer_zero_node))),
5828                        0);
5829     expand_expr_stmt (ffecom_modify (void_type_node,
5830                                      rtmp,
5831                                      ffecom_1 (NEGATE_EXPR, rtype,
5832                                                ffecom_2 (RSHIFT_EXPR,
5833                                                          rtype,
5834                                                          rtmp,
5835                                                          integer_one_node))));
5836     expand_expr_stmt (ffecom_modify (void_type_node,
5837                                      ltmp,
5838                                      ffecom_2 (MULT_EXPR, ltype,
5839                                                ltmp,
5840                                                ltmp)));
5841     expand_end_cond ();
5842     expand_end_cond ();
5843     expand_start_loop (1);
5844     expand_start_cond (ffecom_truth_value
5845                        (ffecom_2 (BIT_AND_EXPR, rtype,
5846                                   rtmp,
5847                                   convert (rtype, integer_one_node))),
5848                        0);
5849     expand_expr_stmt (ffecom_modify (void_type_node,
5850                                      result,
5851                                      ffecom_2 (MULT_EXPR, ltype,
5852                                                result,
5853                                                ltmp)));
5854     expand_end_cond ();
5855     expand_exit_loop_if_false (NULL,
5856                                ffecom_truth_value
5857                                (ffecom_modify (rtype,
5858                                                rtmp,
5859                                                ffecom_2 (RSHIFT_EXPR,
5860                                                          rtype,
5861                                                          rtmp,
5862                                                          integer_one_node))));
5863     expand_expr_stmt (ffecom_modify (void_type_node,
5864                                      ltmp,
5865                                      ffecom_2 (MULT_EXPR, ltype,
5866                                                ltmp,
5867                                                ltmp)));
5868     expand_end_loop ();
5869     expand_end_cond ();
5870     if (!integer_zerop (basetypeof_l_is_int))
5871       expand_end_cond ();
5872     expand_expr_stmt (result);
5873
5874     t = ffecom_end_compstmt ();
5875
5876     result = expand_end_stmt_expr (se);
5877
5878     /* This code comes from c-parse.in, after its expand_end_stmt_expr.  */
5879
5880     if (TREE_CODE (t) == BLOCK)
5881       {
5882         /* Make a BIND_EXPR for the BLOCK already made.  */
5883         result = build (BIND_EXPR, TREE_TYPE (result),
5884                         NULL_TREE, result, t);
5885         /* Remove the block from the tree at this point.
5886            It gets put back at the proper place
5887            when the BIND_EXPR is expanded.  */
5888         delete_block (t);
5889       }
5890     else
5891       result = t;
5892   }
5893
5894   return result;
5895 }
5896
5897 #endif
5898 /* ffecom_expr_transform_ -- Transform symbols in expr
5899
5900    ffebld expr;  // FFE expression.
5901    ffecom_expr_transform_ (expr);
5902
5903    Recursive descent on expr while transforming any untransformed SYMTERs.  */
5904
5905 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5906 static void
5907 ffecom_expr_transform_ (ffebld expr)
5908 {
5909   tree t;
5910   ffesymbol s;
5911
5912 tail_recurse:                   /* :::::::::::::::::::: */
5913
5914   if (expr == NULL)
5915     return;
5916
5917   switch (ffebld_op (expr))
5918     {
5919     case FFEBLD_opSYMTER:
5920       s = ffebld_symter (expr);
5921       t = ffesymbol_hook (s).decl_tree;
5922       if ((t == NULL_TREE)
5923           && ((ffesymbol_kind (s) != FFEINFO_kindNONE)
5924               || ((ffesymbol_where (s) != FFEINFO_whereNONE)
5925                   && (ffesymbol_where (s) != FFEINFO_whereINTRINSIC))))
5926         {
5927           s = ffecom_sym_transform_ (s);
5928           t = ffesymbol_hook (s).decl_tree;     /* Sfunc expr non-dummy,
5929                                                    DIMENSION expr? */
5930         }
5931       break;                    /* Ok if (t == NULL) here. */
5932
5933     case FFEBLD_opITEM:
5934       ffecom_expr_transform_ (ffebld_head (expr));
5935       expr = ffebld_trail (expr);
5936       goto tail_recurse;        /* :::::::::::::::::::: */
5937
5938     default:
5939       break;
5940     }
5941
5942   switch (ffebld_arity (expr))
5943     {
5944     case 2:
5945       ffecom_expr_transform_ (ffebld_left (expr));
5946       expr = ffebld_right (expr);
5947       goto tail_recurse;        /* :::::::::::::::::::: */
5948
5949     case 1:
5950       expr = ffebld_left (expr);
5951       goto tail_recurse;        /* :::::::::::::::::::: */
5952
5953     default:
5954       break;
5955     }
5956
5957   return;
5958 }
5959
5960 #endif
5961 /* Make a type based on info in live f2c.h file.  */
5962
5963 #if FFECOM_targetCURRENT == FFECOM_targetGCC
5964 static void
5965 ffecom_f2c_make_type_ (tree *type, int tcode, const char *name)
5966 {
5967   switch (tcode)
5968     {
5969     case FFECOM_f2ccodeCHAR:
5970       *type = make_signed_type (CHAR_TYPE_SIZE);
5971       break;
5972
5973     case FFECOM_f2ccodeSHORT:
5974       *type = make_signed_type (SHORT_TYPE_SIZE);
5975       break;
5976
5977     case FFECOM_f2ccodeINT:
5978       *type = make_signed_type (INT_TYPE_SIZE);
5979       break;
5980
5981     case FFECOM_f2ccodeLONG:
5982       *type = make_signed_type (LONG_TYPE_SIZE);
5983       break;
5984
5985     case FFECOM_f2ccodeLONGLONG:
5986       *type = make_signed_type (LONG_LONG_TYPE_SIZE);
5987       break;
5988
5989     case FFECOM_f2ccodeCHARPTR:
5990       *type = build_pointer_type (DEFAULT_SIGNED_CHAR
5991                                   ? signed_char_type_node
5992                                   : unsigned_char_type_node);
5993       break;
5994
5995     case FFECOM_f2ccodeFLOAT:
5996       *type = make_node (REAL_TYPE);
5997       TYPE_PRECISION (*type) = FLOAT_TYPE_SIZE;
5998       layout_type (*type);
5999       break;
6000
6001     case FFECOM_f2ccodeDOUBLE:
6002       *type = make_node (REAL_TYPE);
6003       TYPE_PRECISION (*type) = DOUBLE_TYPE_SIZE;
6004       layout_type (*type);
6005       break;
6006
6007     case FFECOM_f2ccodeLONGDOUBLE:
6008       *type = make_node (REAL_TYPE);
6009       TYPE_PRECISION (*type) = LONG_DOUBLE_TYPE_SIZE;
6010       layout_type (*type);
6011       break;
6012
6013     case FFECOM_f2ccodeTWOREALS:
6014       *type = ffecom_make_complex_type_ (ffecom_f2c_real_type_node);
6015       break;
6016
6017     case FFECOM_f2ccodeTWODOUBLEREALS:
6018       *type = ffecom_make_complex_type_ (ffecom_f2c_doublereal_type_node);
6019       break;
6020
6021     default:
6022       assert ("unexpected FFECOM_f2ccodeXYZZY!" == NULL);
6023       *type = error_mark_node;
6024       return;
6025     }
6026
6027   pushdecl (build_decl (TYPE_DECL,
6028                         ffecom_get_invented_identifier ("__g77_f2c_%s", name),
6029                         *type));
6030 }
6031
6032 #endif
6033 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6034 /* Set the f2c list-directed-I/O code for whatever (integral) type has the
6035    given size.  */
6036
6037 static void
6038 ffecom_f2c_set_lio_code_ (ffeinfoBasictype bt, int size,
6039                           int code)
6040 {
6041   int j;
6042   tree t;
6043
6044   for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
6045     if ((t = ffecom_tree_type[bt][j]) != NULL_TREE
6046         && compare_tree_int (TYPE_SIZE (t), size) == 0)
6047       {
6048         assert (code != -1);
6049         ffecom_f2c_typecode_[bt][j] = code;
6050         code = -1;
6051       }
6052 }
6053
6054 #endif
6055 /* Finish up globals after doing all program units in file
6056
6057    Need to handle only uninitialized COMMON areas.  */
6058
6059 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6060 static ffeglobal
6061 ffecom_finish_global_ (ffeglobal global)
6062 {
6063   tree cbtype;
6064   tree cbt;
6065   tree size;
6066
6067   if (ffeglobal_type (global) != FFEGLOBAL_typeCOMMON)
6068       return global;
6069
6070   if (ffeglobal_common_init (global))
6071       return global;
6072
6073   cbt = ffeglobal_hook (global);
6074   if ((cbt == NULL_TREE)
6075       || !ffeglobal_common_have_size (global))
6076     return global;              /* No need to make common, never ref'd. */
6077
6078   suspend_momentary ();
6079
6080   DECL_EXTERNAL (cbt) = 0;
6081
6082   /* Give the array a size now.  */
6083
6084   size = build_int_2 ((ffeglobal_common_size (global)
6085                       + ffeglobal_common_pad (global)) - 1,
6086                       0);
6087
6088   cbtype = TREE_TYPE (cbt);
6089   TYPE_DOMAIN (cbtype) = build_range_type (integer_type_node,
6090                                            integer_zero_node,
6091                                            size);
6092   if (!TREE_TYPE (size))
6093     TREE_TYPE (size) = TYPE_DOMAIN (cbtype);
6094   layout_type (cbtype);
6095
6096   cbt = start_decl (cbt, FALSE);
6097   assert (cbt == ffeglobal_hook (global));
6098
6099   finish_decl (cbt, NULL_TREE, FALSE);
6100
6101   return global;
6102 }
6103
6104 #endif
6105 /* Finish up any untransformed symbols.  */
6106
6107 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6108 static ffesymbol
6109 ffecom_finish_symbol_transform_ (ffesymbol s)
6110 {
6111   if ((s == NULL) || (TREE_CODE (current_function_decl) == ERROR_MARK))
6112     return s;
6113
6114   /* It's easy to know to transform an untransformed symbol, to make sure
6115      we put out debugging info for it.  But COMMON variables, unlike
6116      EQUIVALENCE ones, aren't given declarations in addition to the
6117      tree expressions that specify offsets, because COMMON variables
6118      can be referenced in the outer scope where only dummy arguments
6119      (PARM_DECLs) should really be seen.  To be safe, just don't do any
6120      VAR_DECLs for COMMON variables when we transform them for real
6121      use, and therefore we do all the VAR_DECL creating here.  */
6122
6123   if (ffesymbol_hook (s).decl_tree == NULL_TREE)
6124     {
6125       if (ffesymbol_kind (s) != FFEINFO_kindNONE
6126           || (ffesymbol_where (s) != FFEINFO_whereNONE
6127               && ffesymbol_where (s) != FFEINFO_whereINTRINSIC
6128               && ffesymbol_where (s) != FFEINFO_whereDUMMY))
6129         /* Not transformed, and not CHARACTER*(*), and not a dummy
6130            argument, which can happen only if the entry point names
6131            it "rides in on" are all invalidated for other reasons.  */
6132         s = ffecom_sym_transform_ (s);
6133     }
6134
6135   if ((ffesymbol_where (s) == FFEINFO_whereCOMMON)
6136       && (ffesymbol_hook (s).decl_tree != error_mark_node))
6137     {
6138       int yes = suspend_momentary ();
6139
6140       /* This isn't working, at least for dbxout.  The .s file looks
6141          okay to me (burley), but in gdb 4.9 at least, the variables
6142          appear to reside somewhere outside of the common area, so
6143          it doesn't make sense to mislead anyone by generating the info
6144          on those variables until this is fixed.  NOTE: Same problem
6145          with EQUIVALENCE, sadly...see similar #if later.  */
6146       ffecom_member_phase2_ (ffesymbol_storage (ffesymbol_common (s)),
6147                              ffesymbol_storage (s));
6148
6149       resume_momentary (yes);
6150     }
6151
6152   return s;
6153 }
6154
6155 #endif
6156 /* Append underscore(s) to name before calling get_identifier.  "us"
6157    is nonzero if the name already contains an underscore and thus
6158    needs two underscores appended.  */
6159
6160 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6161 static tree
6162 ffecom_get_appended_identifier_ (char us, const char *name)
6163 {
6164   int i;
6165   char *newname;
6166   tree id;
6167
6168   newname = xmalloc ((i = strlen (name)) + 1
6169                      + ffe_is_underscoring ()
6170                      + us);
6171   memcpy (newname, name, i);
6172   newname[i] = '_';
6173   newname[i + us] = '_';
6174   newname[i + 1 + us] = '\0';
6175   id = get_identifier (newname);
6176
6177   free (newname);
6178
6179   return id;
6180 }
6181
6182 #endif
6183 /* Decide whether to append underscore to name before calling
6184    get_identifier.  */
6185
6186 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6187 static tree
6188 ffecom_get_external_identifier_ (ffesymbol s)
6189 {
6190   char us;
6191   const char *name = ffesymbol_text (s);
6192
6193   /* If name is a built-in name, just return it as is.  */
6194
6195   if (!ffe_is_underscoring ()
6196       || (strcmp (name, FFETARGET_nameBLANK_COMMON) == 0)
6197 #if FFETARGET_isENFORCED_MAIN_NAME
6198       || (strcmp (name, FFETARGET_nameENFORCED_NAME) == 0)
6199 #else
6200       || (strcmp (name, FFETARGET_nameUNNAMED_MAIN) == 0)
6201 #endif
6202       || (strcmp (name, FFETARGET_nameUNNAMED_BLOCK_DATA) == 0))
6203     return get_identifier (name);
6204
6205   us = ffe_is_second_underscore ()
6206     ? (strchr (name, '_') != NULL)
6207       : 0;
6208
6209   return ffecom_get_appended_identifier_ (us, name);
6210 }
6211
6212 #endif
6213 /* Decide whether to append underscore to internal name before calling
6214    get_identifier.
6215
6216    This is for non-external, top-function-context names only.  Transform
6217    identifier so it doesn't conflict with the transformed result
6218    of using a _different_ external name.  E.g. if "CALL FOO" is
6219    transformed into "FOO_();", then the variable in "FOO_ = 3"
6220    must be transformed into something that does not conflict, since
6221    these two things should be independent.
6222
6223    The transformation is as follows.  If the name does not contain
6224    an underscore, there is no possible conflict, so just return.
6225    If the name does contain an underscore, then transform it just
6226    like we transform an external identifier.  */
6227
6228 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6229 static tree
6230 ffecom_get_identifier_ (const char *name)
6231 {
6232   /* If name does not contain an underscore, just return it as is.  */
6233
6234   if (!ffe_is_underscoring ()
6235       || (strchr (name, '_') == NULL))
6236     return get_identifier (name);
6237
6238   return ffecom_get_appended_identifier_ (ffe_is_second_underscore (),
6239                                           name);
6240 }
6241
6242 #endif
6243 /* ffecom_gen_sfuncdef_ -- Generate definition of statement function
6244
6245    tree t;
6246    ffesymbol s;  // kindFUNCTION, whereIMMEDIATE.
6247    t = ffecom_gen_sfuncdef_(s,ffesymbol_basictype(s),
6248          ffesymbol_kindtype(s));
6249
6250    Call after setting up containing function and getting trees for all
6251    other symbols.  */
6252
6253 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6254 static tree
6255 ffecom_gen_sfuncdef_ (ffesymbol s, ffeinfoBasictype bt, ffeinfoKindtype kt)
6256 {
6257   ffebld expr = ffesymbol_sfexpr (s);
6258   tree type;
6259   tree func;
6260   tree result;
6261   bool charfunc = (bt == FFEINFO_basictypeCHARACTER);
6262   static bool recurse = FALSE;
6263   int yes;
6264   int old_lineno = lineno;
6265   char *old_input_filename = input_filename;
6266
6267   ffecom_nested_entry_ = s;
6268
6269   /* For now, we don't have a handy pointer to where the sfunc is actually
6270      defined, though that should be easy to add to an ffesymbol. (The
6271      token/where info available might well point to the place where the type
6272      of the sfunc is declared, especially if that precedes the place where
6273      the sfunc itself is defined, which is typically the case.)  We should
6274      put out a null pointer rather than point somewhere wrong, but I want to
6275      see how it works at this point.  */
6276
6277   input_filename = ffesymbol_where_filename (s);
6278   lineno = ffesymbol_where_filelinenum (s);
6279
6280   /* Pretransform the expression so any newly discovered things belong to the
6281      outer program unit, not to the statement function. */
6282
6283   ffecom_expr_transform_ (expr);
6284
6285   /* Make sure no recursive invocation of this fn (a specific case of failing
6286      to pretransform an sfunc's expression, i.e. where its expression
6287      references another untransformed sfunc) happens. */
6288
6289   assert (!recurse);
6290   recurse = TRUE;
6291
6292   yes = suspend_momentary ();
6293
6294   push_f_function_context ();
6295
6296   if (charfunc)
6297     type = void_type_node;
6298   else
6299     {
6300       type = ffecom_tree_type[bt][kt];
6301       if (type == NULL_TREE)
6302         type = integer_type_node;       /* _sym_exec_transition reports
6303                                            error. */
6304     }
6305
6306   start_function (ffecom_get_identifier_ (ffesymbol_text (s)),
6307                   build_function_type (type, NULL_TREE),
6308                   1,            /* nested/inline */
6309                   0);           /* TREE_PUBLIC */
6310
6311   /* We don't worry about COMPLEX return values here, because this is
6312      entirely internal to our code, and gcc has the ability to return COMPLEX
6313      directly as a value.  */
6314
6315   yes = suspend_momentary ();
6316
6317   if (charfunc)
6318     {                           /* Prepend arg for where result goes. */
6319       tree type;
6320
6321       type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
6322
6323       result = ffecom_get_invented_identifier ("__g77_%s", "result");
6324
6325       ffecom_char_enhance_arg_ (&type, s);      /* Ignore returned length. */
6326
6327       type = build_pointer_type (type);
6328       result = build_decl (PARM_DECL, result, type);
6329
6330       push_parm_decl (result);
6331     }
6332   else
6333     result = NULL_TREE;         /* Not ref'd if !charfunc. */
6334
6335   ffecom_push_dummy_decls_ (ffesymbol_dummyargs (s), TRUE);
6336
6337   resume_momentary (yes);
6338
6339   store_parm_decls (0);
6340
6341   ffecom_start_compstmt ();
6342
6343   if (expr != NULL)
6344     {
6345       if (charfunc)
6346         {
6347           ffetargetCharacterSize sz = ffesymbol_size (s);
6348           tree result_length;
6349
6350           result_length = build_int_2 (sz, 0);
6351           TREE_TYPE (result_length) = ffecom_f2c_ftnlen_type_node;
6352
6353           ffecom_prepare_let_char_ (sz, expr);
6354
6355           ffecom_prepare_end ();
6356
6357           ffecom_let_char_ (result, result_length, sz, expr);
6358           expand_null_return ();
6359         }
6360       else
6361         {
6362           ffecom_prepare_expr (expr);
6363
6364           ffecom_prepare_end ();
6365
6366           expand_return (ffecom_modify (NULL_TREE,
6367                                         DECL_RESULT (current_function_decl),
6368                                         ffecom_expr (expr)));
6369         }
6370
6371       clear_momentary ();
6372     }
6373
6374   ffecom_end_compstmt ();
6375
6376   func = current_function_decl;
6377   finish_function (1);
6378
6379   pop_f_function_context ();
6380
6381   resume_momentary (yes);
6382
6383   recurse = FALSE;
6384
6385   lineno = old_lineno;
6386   input_filename = old_input_filename;
6387
6388   ffecom_nested_entry_ = NULL;
6389
6390   return func;
6391 }
6392
6393 #endif
6394
6395 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6396 static const char *
6397 ffecom_gfrt_args_ (ffecomGfrt ix)
6398 {
6399   return ffecom_gfrt_argstring_[ix];
6400 }
6401
6402 #endif
6403 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6404 static tree
6405 ffecom_gfrt_tree_ (ffecomGfrt ix)
6406 {
6407   if (ffecom_gfrt_[ix] == NULL_TREE)
6408     ffecom_make_gfrt_ (ix);
6409
6410   return ffecom_1 (ADDR_EXPR,
6411                    build_pointer_type (TREE_TYPE (ffecom_gfrt_[ix])),
6412                    ffecom_gfrt_[ix]);
6413 }
6414
6415 #endif
6416 /* Return initialize-to-zero expression for this VAR_DECL.  */
6417
6418 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6419 /* A somewhat evil way to prevent the garbage collector
6420    from collecting 'tree' structures.  */
6421 #define NUM_TRACKED_CHUNK 63
6422 static struct tree_ggc_tracker 
6423 {
6424   struct tree_ggc_tracker *next;
6425   tree trees[NUM_TRACKED_CHUNK];
6426 } *tracker_head = NULL;
6427
6428 static void 
6429 mark_tracker_head (void *arg)
6430 {
6431   struct tree_ggc_tracker *head;
6432   int i;
6433   
6434   for (head = * (struct tree_ggc_tracker **) arg;
6435        head != NULL;
6436        head = head->next)
6437   {
6438     ggc_mark (head);
6439     for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6440       ggc_mark_tree (head->trees[i]);
6441   }
6442 }
6443
6444 void
6445 ffecom_save_tree_forever (tree t)
6446 {
6447   int i;
6448   if (tracker_head != NULL)
6449     for (i = 0; i < NUM_TRACKED_CHUNK; i++)
6450       if (tracker_head->trees[i] == NULL)
6451         {
6452           tracker_head->trees[i] = t;
6453           return;
6454         }
6455
6456   {
6457     /* Need to allocate a new block.  */
6458     struct tree_ggc_tracker *old_head = tracker_head;
6459     
6460     tracker_head = ggc_alloc (sizeof (*tracker_head));
6461     tracker_head->next = old_head;
6462     tracker_head->trees[0] = t;
6463     for (i = 1; i < NUM_TRACKED_CHUNK; i++)
6464       tracker_head->trees[i] = NULL;
6465   }
6466 }
6467
6468 static tree
6469 ffecom_init_zero_ (tree decl)
6470 {
6471   tree init;
6472   int incremental = TREE_STATIC (decl);
6473   tree type = TREE_TYPE (decl);
6474
6475   if (incremental)
6476     {
6477       make_decl_rtl (decl, NULL, TREE_PUBLIC (decl) ? 1 : 0);
6478       assemble_variable (decl, TREE_PUBLIC (decl) ? 1 : 0, 0, 1);
6479     }
6480
6481   push_momentary ();
6482
6483   if ((TREE_CODE (type) != ARRAY_TYPE)
6484       && (TREE_CODE (type) != RECORD_TYPE)
6485       && (TREE_CODE (type) != UNION_TYPE)
6486       && !incremental)
6487     init = convert (type, integer_zero_node);
6488   else if (!incremental)
6489     {
6490       int momentary = suspend_momentary ();
6491
6492       init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
6493       TREE_CONSTANT (init) = 1;
6494       TREE_STATIC (init) = 1;
6495
6496       resume_momentary (momentary);
6497     }
6498   else
6499     {
6500       int momentary = suspend_momentary ();
6501
6502       assemble_zeros (int_size_in_bytes (type));
6503       init = error_mark_node;
6504
6505       resume_momentary (momentary);
6506     }
6507
6508   pop_momentary_nofree ();
6509
6510   return init;
6511 }
6512
6513 #endif
6514 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6515 static tree
6516 ffecom_intrinsic_ichar_ (tree tree_type, ffebld arg,
6517                          tree *maybe_tree)
6518 {
6519   tree expr_tree;
6520   tree length_tree;
6521
6522   switch (ffebld_op (arg))
6523     {
6524     case FFEBLD_opCONTER:       /* For F90, check 0-length. */
6525       if (ffetarget_length_character1
6526           (ffebld_constant_character1
6527            (ffebld_conter (arg))) == 0)
6528         {
6529           *maybe_tree = integer_zero_node;
6530           return convert (tree_type, integer_zero_node);
6531         }
6532
6533       *maybe_tree = integer_one_node;
6534       expr_tree = build_int_2 (*ffetarget_text_character1
6535                                (ffebld_constant_character1
6536                                 (ffebld_conter (arg))),
6537                                0);
6538       TREE_TYPE (expr_tree) = tree_type;
6539       return expr_tree;
6540
6541     case FFEBLD_opSYMTER:
6542     case FFEBLD_opARRAYREF:
6543     case FFEBLD_opFUNCREF:
6544     case FFEBLD_opSUBSTR:
6545       ffecom_char_args_ (&expr_tree, &length_tree, arg);
6546
6547       if ((expr_tree == error_mark_node)
6548           || (length_tree == error_mark_node))
6549         {
6550           *maybe_tree = error_mark_node;
6551           return error_mark_node;
6552         }
6553
6554       if (integer_zerop (length_tree))
6555         {
6556           *maybe_tree = integer_zero_node;
6557           return convert (tree_type, integer_zero_node);
6558         }
6559
6560       expr_tree
6561         = ffecom_1 (INDIRECT_REF,
6562                     TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6563                     expr_tree);
6564       expr_tree
6565         = ffecom_2 (ARRAY_REF,
6566                     TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (expr_tree))),
6567                     expr_tree,
6568                     integer_one_node);
6569       expr_tree = convert (tree_type, expr_tree);
6570
6571       if (TREE_CODE (length_tree) == INTEGER_CST)
6572         *maybe_tree = integer_one_node;
6573       else                      /* Must check length at run time.  */
6574         *maybe_tree
6575           = ffecom_truth_value
6576             (ffecom_2 (GT_EXPR, integer_type_node,
6577                        length_tree,
6578                        ffecom_f2c_ftnlen_zero_node));
6579       return expr_tree;
6580
6581     case FFEBLD_opPAREN:
6582     case FFEBLD_opCONVERT:
6583       if (ffeinfo_size (ffebld_info (arg)) == 0)
6584         {
6585           *maybe_tree = integer_zero_node;
6586           return convert (tree_type, integer_zero_node);
6587         }
6588       return ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6589                                       maybe_tree);
6590
6591     case FFEBLD_opCONCATENATE:
6592       {
6593         tree maybe_left;
6594         tree maybe_right;
6595         tree expr_left;
6596         tree expr_right;
6597
6598         expr_left = ffecom_intrinsic_ichar_ (tree_type, ffebld_left (arg),
6599                                              &maybe_left);
6600         expr_right = ffecom_intrinsic_ichar_ (tree_type, ffebld_right (arg),
6601                                               &maybe_right);
6602         *maybe_tree = ffecom_2 (TRUTH_ORIF_EXPR, integer_type_node,
6603                                 maybe_left,
6604                                 maybe_right);
6605         expr_tree = ffecom_3 (COND_EXPR, tree_type,
6606                               maybe_left,
6607                               expr_left,
6608                               expr_right);
6609         return expr_tree;
6610       }
6611
6612     default:
6613       assert ("bad op in ICHAR" == NULL);
6614       return error_mark_node;
6615     }
6616 }
6617
6618 #endif
6619 /* ffecom_intrinsic_len_ -- Return length info for char arg (LEN())
6620
6621    tree length_arg;
6622    ffebld expr;
6623    length_arg = ffecom_intrinsic_len_ (expr);
6624
6625    Handles CHARACTER-type CONTER, SYMTER, SUBSTR, ARRAYREF, and FUNCREF
6626    subexpressions by constructing the appropriate tree for the
6627    length-of-character-text argument in a calling sequence.  */
6628
6629 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6630 static tree
6631 ffecom_intrinsic_len_ (ffebld expr)
6632 {
6633   ffetargetCharacter1 val;
6634   tree length;
6635
6636   switch (ffebld_op (expr))
6637     {
6638     case FFEBLD_opCONTER:
6639       val = ffebld_constant_character1 (ffebld_conter (expr));
6640       length = build_int_2 (ffetarget_length_character1 (val), 0);
6641       TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6642       break;
6643
6644     case FFEBLD_opSYMTER:
6645       {
6646         ffesymbol s = ffebld_symter (expr);
6647         tree item;
6648
6649         item = ffesymbol_hook (s).decl_tree;
6650         if (item == NULL_TREE)
6651           {
6652             s = ffecom_sym_transform_ (s);
6653             item = ffesymbol_hook (s).decl_tree;
6654           }
6655         if (ffesymbol_kind (s) == FFEINFO_kindENTITY)
6656           {
6657             if (ffesymbol_size (s) == FFETARGET_charactersizeNONE)
6658               length = ffesymbol_hook (s).length_tree;
6659             else
6660               {
6661                 length = build_int_2 (ffesymbol_size (s), 0);
6662                 TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6663               }
6664           }
6665         else if (item == error_mark_node)
6666           length = error_mark_node;
6667         else                    /* FFEINFO_kindFUNCTION: */
6668           length = NULL_TREE;
6669       }
6670       break;
6671
6672     case FFEBLD_opARRAYREF:
6673       length = ffecom_intrinsic_len_ (ffebld_left (expr));
6674       break;
6675
6676     case FFEBLD_opSUBSTR:
6677       {
6678         ffebld start;
6679         ffebld end;
6680         ffebld thing = ffebld_right (expr);
6681         tree start_tree;
6682         tree end_tree;
6683
6684         assert (ffebld_op (thing) == FFEBLD_opITEM);
6685         start = ffebld_head (thing);
6686         thing = ffebld_trail (thing);
6687         assert (ffebld_trail (thing) == NULL);
6688         end = ffebld_head (thing);
6689
6690         length = ffecom_intrinsic_len_ (ffebld_left (expr));
6691
6692         if (length == error_mark_node)
6693           break;
6694
6695         if (start == NULL)
6696           {
6697             if (end == NULL)
6698               ;
6699             else
6700               {
6701                 length = convert (ffecom_f2c_ftnlen_type_node,
6702                                   ffecom_expr (end));
6703               }
6704           }
6705         else
6706           {
6707             start_tree = convert (ffecom_f2c_ftnlen_type_node,
6708                                   ffecom_expr (start));
6709
6710             if (start_tree == error_mark_node)
6711               {
6712                 length = error_mark_node;
6713                 break;
6714               }
6715
6716             if (end == NULL)
6717               {
6718                 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6719                                    ffecom_f2c_ftnlen_one_node,
6720                                    ffecom_2 (MINUS_EXPR,
6721                                              ffecom_f2c_ftnlen_type_node,
6722                                              length,
6723                                              start_tree));
6724               }
6725             else
6726               {
6727                 end_tree = convert (ffecom_f2c_ftnlen_type_node,
6728                                     ffecom_expr (end));
6729
6730                 if (end_tree == error_mark_node)
6731                   {
6732                     length = error_mark_node;
6733                     break;
6734                   }
6735
6736                 length = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6737                                    ffecom_f2c_ftnlen_one_node,
6738                                    ffecom_2 (MINUS_EXPR,
6739                                              ffecom_f2c_ftnlen_type_node,
6740                                              end_tree, start_tree));
6741               }
6742           }
6743       }
6744       break;
6745
6746     case FFEBLD_opCONCATENATE:
6747       length
6748         = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
6749                     ffecom_intrinsic_len_ (ffebld_left (expr)),
6750                     ffecom_intrinsic_len_ (ffebld_right (expr)));
6751       break;
6752
6753     case FFEBLD_opFUNCREF:
6754     case FFEBLD_opCONVERT:
6755       length = build_int_2 (ffebld_size (expr), 0);
6756       TREE_TYPE (length) = ffecom_f2c_ftnlen_type_node;
6757       break;
6758
6759     default:
6760       assert ("bad op for single char arg expr" == NULL);
6761       length = ffecom_f2c_ftnlen_zero_node;
6762       break;
6763     }
6764
6765   assert (length != NULL_TREE);
6766
6767   return length;
6768 }
6769
6770 #endif
6771 /* Handle CHARACTER assignments.
6772
6773    Generates code to do the assignment.  Used by ordinary assignment
6774    statement handler ffecom_let_stmt and by statement-function
6775    handler to generate code for a statement function.  */
6776
6777 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6778 static void
6779 ffecom_let_char_ (tree dest_tree, tree dest_length,
6780                   ffetargetCharacterSize dest_size, ffebld source)
6781 {
6782   ffecomConcatList_ catlist;
6783   tree source_length;
6784   tree source_tree;
6785   tree expr_tree;
6786
6787   if ((dest_tree == error_mark_node)
6788       || (dest_length == error_mark_node))
6789     return;
6790
6791   assert (dest_tree != NULL_TREE);
6792   assert (dest_length != NULL_TREE);
6793
6794   /* Source might be an opCONVERT, which just means it is a different size
6795      than the destination.  Since the underlying implementation here handles
6796      that (directly or via the s_copy or s_cat run-time-library functions),
6797      we don't need the "convenience" of an opCONVERT that tells us to
6798      truncate or blank-pad, particularly since the resulting implementation
6799      would probably be slower than otherwise. */
6800
6801   while (ffebld_op (source) == FFEBLD_opCONVERT)
6802     source = ffebld_left (source);
6803
6804   catlist = ffecom_concat_list_new_ (source, dest_size);
6805   switch (ffecom_concat_list_count_ (catlist))
6806     {
6807     case 0:                     /* Shouldn't happen, but in case it does... */
6808       ffecom_concat_list_kill_ (catlist);
6809       source_tree = null_pointer_node;
6810       source_length = ffecom_f2c_ftnlen_zero_node;
6811       expr_tree = build_tree_list (NULL_TREE, dest_tree);
6812       TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6813       TREE_CHAIN (TREE_CHAIN (expr_tree))
6814         = build_tree_list (NULL_TREE, dest_length);
6815       TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6816         = build_tree_list (NULL_TREE, source_length);
6817
6818       expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6819       TREE_SIDE_EFFECTS (expr_tree) = 1;
6820
6821       expand_expr_stmt (expr_tree);
6822
6823       return;
6824
6825     case 1:                     /* The (fairly) easy case. */
6826       ffecom_char_args_ (&source_tree, &source_length,
6827                          ffecom_concat_list_expr_ (catlist, 0));
6828       ffecom_concat_list_kill_ (catlist);
6829       assert (source_tree != NULL_TREE);
6830       assert (source_length != NULL_TREE);
6831
6832       if ((source_tree == error_mark_node)
6833           || (source_length == error_mark_node))
6834         return;
6835
6836       if (dest_size == 1)
6837         {
6838           dest_tree
6839             = ffecom_1 (INDIRECT_REF,
6840                         TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6841                                                       (dest_tree))),
6842                         dest_tree);
6843           dest_tree
6844             = ffecom_2 (ARRAY_REF,
6845                         TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6846                                                       (dest_tree))),
6847                         dest_tree,
6848                         integer_one_node);
6849           source_tree
6850             = ffecom_1 (INDIRECT_REF,
6851                         TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6852                                                       (source_tree))),
6853                         source_tree);
6854           source_tree
6855             = ffecom_2 (ARRAY_REF,
6856                         TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE
6857                                                       (source_tree))),
6858                         source_tree,
6859                         integer_one_node);
6860
6861           expr_tree = ffecom_modify (void_type_node, dest_tree, source_tree);
6862
6863           expand_expr_stmt (expr_tree);
6864
6865           return;
6866         }
6867
6868       expr_tree = build_tree_list (NULL_TREE, dest_tree);
6869       TREE_CHAIN (expr_tree) = build_tree_list (NULL_TREE, source_tree);
6870       TREE_CHAIN (TREE_CHAIN (expr_tree))
6871         = build_tree_list (NULL_TREE, dest_length);
6872       TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6873         = build_tree_list (NULL_TREE, source_length);
6874
6875       expr_tree = ffecom_call_gfrt (FFECOM_gfrtCOPY, expr_tree, NULL_TREE);
6876       TREE_SIDE_EFFECTS (expr_tree) = 1;
6877
6878       expand_expr_stmt (expr_tree);
6879
6880       return;
6881
6882     default:                    /* Must actually concatenate things. */
6883       break;
6884     }
6885
6886   /* Heavy-duty concatenation. */
6887
6888   {
6889     int count = ffecom_concat_list_count_ (catlist);
6890     int i;
6891     tree lengths;
6892     tree items;
6893     tree length_array;
6894     tree item_array;
6895     tree citem;
6896     tree clength;
6897
6898 #ifdef HOHO
6899     length_array
6900       = lengths
6901       = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
6902                              FFETARGET_charactersizeNONE, count, TRUE);
6903     item_array = items = ffecom_push_tempvar (ffecom_f2c_address_type_node,
6904                                               FFETARGET_charactersizeNONE,
6905                                               count, TRUE);
6906 #else
6907     {
6908       tree hook;
6909
6910       hook = ffebld_nonter_hook (source);
6911       assert (hook);
6912       assert (TREE_CODE (hook) == TREE_VEC);
6913       assert (TREE_VEC_LENGTH (hook) == 2);
6914       length_array = lengths = TREE_VEC_ELT (hook, 0);
6915       item_array = items = TREE_VEC_ELT (hook, 1);
6916     }
6917 #endif
6918
6919     for (i = 0; i < count; ++i)
6920       {
6921         ffecom_char_args_ (&citem, &clength,
6922                            ffecom_concat_list_expr_ (catlist, i));
6923         if ((citem == error_mark_node)
6924             || (clength == error_mark_node))
6925           {
6926             ffecom_concat_list_kill_ (catlist);
6927             return;
6928           }
6929
6930         items
6931           = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
6932                       ffecom_modify (void_type_node,
6933                                      ffecom_2 (ARRAY_REF,
6934                      TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
6935                                                item_array,
6936                                                build_int_2 (i, 0)),
6937                                      citem),
6938                       items);
6939         lengths
6940           = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
6941                       ffecom_modify (void_type_node,
6942                                      ffecom_2 (ARRAY_REF,
6943                    TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
6944                                                length_array,
6945                                                build_int_2 (i, 0)),
6946                                      clength),
6947                       lengths);
6948       }
6949
6950     expr_tree = build_tree_list (NULL_TREE, dest_tree);
6951     TREE_CHAIN (expr_tree)
6952       = build_tree_list (NULL_TREE,
6953                          ffecom_1 (ADDR_EXPR,
6954                                    build_pointer_type (TREE_TYPE (items)),
6955                                    items));
6956     TREE_CHAIN (TREE_CHAIN (expr_tree))
6957       = build_tree_list (NULL_TREE,
6958                          ffecom_1 (ADDR_EXPR,
6959                                    build_pointer_type (TREE_TYPE (lengths)),
6960                                    lengths));
6961     TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree)))
6962       = build_tree_list
6963         (NULL_TREE,
6964          ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
6965                    convert (ffecom_f2c_ftnlen_type_node,
6966                             build_int_2 (count, 0))));
6967     TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (expr_tree))))
6968       = build_tree_list (NULL_TREE, dest_length);
6969
6970     expr_tree = ffecom_call_gfrt (FFECOM_gfrtCAT, expr_tree, NULL_TREE);
6971     TREE_SIDE_EFFECTS (expr_tree) = 1;
6972
6973     expand_expr_stmt (expr_tree);
6974   }
6975
6976   ffecom_concat_list_kill_ (catlist);
6977 }
6978
6979 #endif
6980 /* ffecom_make_gfrt_ -- Make initial info for run-time routine
6981
6982    ffecomGfrt ix;
6983    ffecom_make_gfrt_(ix);
6984
6985    Assumes gfrt_[ix] is NULL_TREE, and replaces it with the FUNCTION_DECL
6986    for the indicated run-time routine (ix).  */
6987
6988 #if FFECOM_targetCURRENT == FFECOM_targetGCC
6989 static void
6990 ffecom_make_gfrt_ (ffecomGfrt ix)
6991 {
6992   tree t;
6993   tree ttype;
6994
6995   switch (ffecom_gfrt_type_[ix])
6996     {
6997     case FFECOM_rttypeVOID_:
6998       ttype = void_type_node;
6999       break;
7000
7001     case FFECOM_rttypeVOIDSTAR_:
7002       ttype = TREE_TYPE (null_pointer_node);    /* `void *'. */
7003       break;
7004
7005     case FFECOM_rttypeFTNINT_:
7006       ttype = ffecom_f2c_ftnint_type_node;
7007       break;
7008
7009     case FFECOM_rttypeINTEGER_:
7010       ttype = ffecom_f2c_integer_type_node;
7011       break;
7012
7013     case FFECOM_rttypeLONGINT_:
7014       ttype = ffecom_f2c_longint_type_node;
7015       break;
7016
7017     case FFECOM_rttypeLOGICAL_:
7018       ttype = ffecom_f2c_logical_type_node;
7019       break;
7020
7021     case FFECOM_rttypeREAL_F2C_:
7022       ttype = double_type_node;
7023       break;
7024
7025     case FFECOM_rttypeREAL_GNU_:
7026       ttype = float_type_node;
7027       break;
7028
7029     case FFECOM_rttypeCOMPLEX_F2C_:
7030       ttype = void_type_node;
7031       break;
7032
7033     case FFECOM_rttypeCOMPLEX_GNU_:
7034       ttype = ffecom_f2c_complex_type_node;
7035       break;
7036
7037     case FFECOM_rttypeDOUBLE_:
7038       ttype = double_type_node;
7039       break;
7040
7041     case FFECOM_rttypeDOUBLEREAL_:
7042       ttype = ffecom_f2c_doublereal_type_node;
7043       break;
7044
7045     case FFECOM_rttypeDBLCMPLX_F2C_:
7046       ttype = void_type_node;
7047       break;
7048
7049     case FFECOM_rttypeDBLCMPLX_GNU_:
7050       ttype = ffecom_f2c_doublecomplex_type_node;
7051       break;
7052
7053     case FFECOM_rttypeCHARACTER_:
7054       ttype = void_type_node;
7055       break;
7056
7057     default:
7058       ttype = NULL;
7059       assert ("bad rttype" == NULL);
7060       break;
7061     }
7062
7063   ttype = build_function_type (ttype, NULL_TREE);
7064   t = build_decl (FUNCTION_DECL,
7065                   get_identifier (ffecom_gfrt_name_[ix]),
7066                   ttype);
7067   DECL_EXTERNAL (t) = 1;
7068   TREE_PUBLIC (t) = 1;
7069   TREE_THIS_VOLATILE (t) = ffecom_gfrt_volatile_[ix] ? 1 : 0;
7070
7071   t = start_decl (t, TRUE);
7072
7073   finish_decl (t, NULL_TREE, TRUE);
7074
7075   ffecom_gfrt_[ix] = t;
7076 }
7077
7078 #endif
7079 /* Phase 1 pass over each member of a COMMON/EQUIVALENCE group.  */
7080
7081 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7082 static void
7083 ffecom_member_phase1_ (ffestorag mst UNUSED, ffestorag st)
7084 {
7085   ffesymbol s = ffestorag_symbol (st);
7086
7087   if (ffesymbol_namelisted (s))
7088     ffecom_member_namelisted_ = TRUE;
7089 }
7090
7091 #endif
7092 /* Phase 2 pass over each member of a COMMON/EQUIVALENCE group.  Declare
7093    the member so debugger will see it.  Otherwise nobody should be
7094    referencing the member.  */
7095
7096 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7097 static void
7098 ffecom_member_phase2_ (ffestorag mst, ffestorag st)
7099 {
7100   ffesymbol s;
7101   tree t;
7102   tree mt;
7103   tree type;
7104
7105   if ((mst == NULL)
7106       || ((mt = ffestorag_hook (mst)) == NULL)
7107       || (mt == error_mark_node))
7108     return;
7109
7110   if ((st == NULL)
7111       || ((s = ffestorag_symbol (st)) == NULL))
7112     return;
7113
7114   type = ffecom_type_localvar_ (s,
7115                                 ffesymbol_basictype (s),
7116                                 ffesymbol_kindtype (s));
7117   if (type == error_mark_node)
7118     return;
7119
7120   t = build_decl (VAR_DECL,
7121                   ffecom_get_identifier_ (ffesymbol_text (s)),
7122                   type);
7123
7124   TREE_STATIC (t) = TREE_STATIC (mt);
7125   DECL_INITIAL (t) = NULL_TREE;
7126   TREE_ASM_WRITTEN (t) = 1;
7127
7128   DECL_RTL (t)
7129     = gen_rtx (MEM, TYPE_MODE (type),
7130                plus_constant (XEXP (DECL_RTL (mt), 0),
7131                               ffestorag_modulo (mst)
7132                               + ffestorag_offset (st)
7133                               - ffestorag_offset (mst)));
7134
7135   t = start_decl (t, FALSE);
7136
7137   finish_decl (t, NULL_TREE, FALSE);
7138 }
7139
7140 #endif
7141 /* Prepare source expression for assignment into a destination perhaps known
7142    to be of a specific size.  */
7143
7144 static void
7145 ffecom_prepare_let_char_ (ffetargetCharacterSize dest_size, ffebld source)
7146 {
7147   ffecomConcatList_ catlist;
7148   int count;
7149   int i;
7150   tree ltmp;
7151   tree itmp;
7152   tree tempvar = NULL_TREE;
7153
7154   while (ffebld_op (source) == FFEBLD_opCONVERT)
7155     source = ffebld_left (source);
7156
7157   catlist = ffecom_concat_list_new_ (source, dest_size);
7158   count = ffecom_concat_list_count_ (catlist);
7159
7160   if (count >= 2)
7161     {
7162       ltmp
7163         = ffecom_make_tempvar ("let_char_len", ffecom_f2c_ftnlen_type_node,
7164                                FFETARGET_charactersizeNONE, count);
7165       itmp
7166         = ffecom_make_tempvar ("let_char_item", ffecom_f2c_address_type_node,
7167                                FFETARGET_charactersizeNONE, count);
7168
7169       tempvar = make_tree_vec (2);
7170       TREE_VEC_ELT (tempvar, 0) = ltmp;
7171       TREE_VEC_ELT (tempvar, 1) = itmp;
7172     }
7173
7174   for (i = 0; i < count; ++i)
7175     ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist, i));
7176
7177   ffecom_concat_list_kill_ (catlist);
7178
7179   if (tempvar)
7180     {
7181       ffebld_nonter_set_hook (source, tempvar);
7182       current_binding_level->prep_state = 1;
7183     }
7184 }
7185
7186 /* ffecom_push_dummy_decls_ -- Transform dummy args, push parm decls in order
7187
7188    Ignores STAR (alternate-return) dummies.  All other get exec-transitioned
7189    (which generates their trees) and then their trees get push_parm_decl'd.
7190
7191    The second arg is TRUE if the dummies are for a statement function, in
7192    which case lengths are not pushed for character arguments (since they are
7193    always known by both the caller and the callee, though the code allows
7194    for someday permitting CHAR*(*) stmtfunc dummies).  */
7195
7196 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7197 static void
7198 ffecom_push_dummy_decls_ (ffebld dummy_list, bool stmtfunc)
7199 {
7200   ffebld dummy;
7201   ffebld dumlist;
7202   ffesymbol s;
7203   tree parm;
7204
7205   ffecom_transform_only_dummies_ = TRUE;
7206
7207   /* First push the parms corresponding to actual dummy "contents".  */
7208
7209   for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7210     {
7211       dummy = ffebld_head (dumlist);
7212       switch (ffebld_op (dummy))
7213         {
7214         case FFEBLD_opSTAR:
7215         case FFEBLD_opANY:
7216           continue;             /* Forget alternate returns. */
7217
7218         default:
7219           break;
7220         }
7221       assert (ffebld_op (dummy) == FFEBLD_opSYMTER);
7222       s = ffebld_symter (dummy);
7223       parm = ffesymbol_hook (s).decl_tree;
7224       if (parm == NULL_TREE)
7225         {
7226           s = ffecom_sym_transform_ (s);
7227           parm = ffesymbol_hook (s).decl_tree;
7228           assert (parm != NULL_TREE);
7229         }
7230       if (parm != error_mark_node)
7231         push_parm_decl (parm);
7232     }
7233
7234   /* Then, for CHARACTER dummies, push the parms giving their lengths.  */
7235
7236   for (dumlist = dummy_list; dumlist != NULL; dumlist = ffebld_trail (dumlist))
7237     {
7238       dummy = ffebld_head (dumlist);
7239       switch (ffebld_op (dummy))
7240         {
7241         case FFEBLD_opSTAR:
7242         case FFEBLD_opANY:
7243           continue;             /* Forget alternate returns, they mean
7244                                    NOTHING! */
7245
7246         default:
7247           break;
7248         }
7249       s = ffebld_symter (dummy);
7250       if (ffesymbol_basictype (s) != FFEINFO_basictypeCHARACTER)
7251         continue;               /* Only looking for CHARACTER arguments. */
7252       if (stmtfunc && (ffesymbol_size (s) != FFETARGET_charactersizeNONE))
7253         continue;               /* Stmtfunc arg with known size needs no
7254                                    length param. */
7255       if (ffesymbol_kind (s) != FFEINFO_kindENTITY)
7256         continue;               /* Only looking for variables and arrays. */
7257       parm = ffesymbol_hook (s).length_tree;
7258       assert (parm != NULL_TREE);
7259       if (parm != error_mark_node)
7260         push_parm_decl (parm);
7261     }
7262
7263   ffecom_transform_only_dummies_ = FALSE;
7264 }
7265
7266 #endif
7267 /* ffecom_start_progunit_ -- Beginning of program unit
7268
7269    Does GNU back end stuff necessary to teach it about the start of its
7270    equivalent of a Fortran program unit.  */
7271
7272 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7273 static void
7274 ffecom_start_progunit_ ()
7275 {
7276   ffesymbol fn = ffecom_primary_entry_;
7277   ffebld arglist;
7278   tree id;                      /* Identifier (name) of function. */
7279   tree type;                    /* Type of function. */
7280   tree result;                  /* Result of function. */
7281   ffeinfoBasictype bt;
7282   ffeinfoKindtype kt;
7283   ffeglobal g;
7284   ffeglobalType gt;
7285   ffeglobalType egt = FFEGLOBAL_type;
7286   bool charfunc;
7287   bool cmplxfunc;
7288   bool altentries = (ffecom_num_entrypoints_ != 0);
7289   bool multi
7290   = altentries
7291   && (ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
7292   && (ffecom_master_bt_ == FFEINFO_basictypeNONE);
7293   bool main_program = FALSE;
7294   int old_lineno = lineno;
7295   char *old_input_filename = input_filename;
7296   int yes;
7297
7298   assert (fn != NULL);
7299   assert (ffesymbol_hook (fn).decl_tree == NULL_TREE);
7300
7301   input_filename = ffesymbol_where_filename (fn);
7302   lineno = ffesymbol_where_filelinenum (fn);
7303
7304   /* c-parse.y indeed does call suspend_momentary and not only ignores the
7305      return value, but also never calls resume_momentary, when starting an
7306      outer function (see "fndef:", "setspecs:", and so on).  So g77 does the
7307      same thing.  It shouldn't be a problem since start_function calls
7308      temporary_allocation, but it might be necessary.  If it causes a problem
7309      here, then maybe there's a bug lurking in gcc.  NOTE: This identical
7310      comment appears twice in thist file.  */
7311
7312   suspend_momentary ();
7313
7314   switch (ffecom_primary_entry_kind_)
7315     {
7316     case FFEINFO_kindPROGRAM:
7317       main_program = TRUE;
7318       gt = FFEGLOBAL_typeMAIN;
7319       bt = FFEINFO_basictypeNONE;
7320       kt = FFEINFO_kindtypeNONE;
7321       type = ffecom_tree_fun_type_void;
7322       charfunc = FALSE;
7323       cmplxfunc = FALSE;
7324       break;
7325
7326     case FFEINFO_kindBLOCKDATA:
7327       gt = FFEGLOBAL_typeBDATA;
7328       bt = FFEINFO_basictypeNONE;
7329       kt = FFEINFO_kindtypeNONE;
7330       type = ffecom_tree_fun_type_void;
7331       charfunc = FALSE;
7332       cmplxfunc = FALSE;
7333       break;
7334
7335     case FFEINFO_kindFUNCTION:
7336       gt = FFEGLOBAL_typeFUNC;
7337       egt = FFEGLOBAL_typeEXT;
7338       bt = ffesymbol_basictype (fn);
7339       kt = ffesymbol_kindtype (fn);
7340       if (bt == FFEINFO_basictypeNONE)
7341         {
7342           ffeimplic_establish_symbol (fn);
7343           if (ffesymbol_funcresult (fn) != NULL)
7344             ffeimplic_establish_symbol (ffesymbol_funcresult (fn));
7345           bt = ffesymbol_basictype (fn);
7346           kt = ffesymbol_kindtype (fn);
7347         }
7348
7349       if (multi)
7350         charfunc = cmplxfunc = FALSE;
7351       else if (bt == FFEINFO_basictypeCHARACTER)
7352         charfunc = TRUE, cmplxfunc = FALSE;
7353       else if ((bt == FFEINFO_basictypeCOMPLEX)
7354                && ffesymbol_is_f2c (fn)
7355                && !altentries)
7356         charfunc = FALSE, cmplxfunc = TRUE;
7357       else
7358         charfunc = cmplxfunc = FALSE;
7359
7360       if (multi || charfunc)
7361         type = ffecom_tree_fun_type_void;
7362       else if (ffesymbol_is_f2c (fn) && !altentries)
7363         type = ffecom_tree_fun_type[bt][kt];
7364       else
7365         type = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
7366
7367       if ((type == NULL_TREE)
7368           || (TREE_TYPE (type) == NULL_TREE))
7369         type = ffecom_tree_fun_type_void;       /* _sym_exec_transition. */
7370       break;
7371
7372     case FFEINFO_kindSUBROUTINE:
7373       gt = FFEGLOBAL_typeSUBR;
7374       egt = FFEGLOBAL_typeEXT;
7375       bt = FFEINFO_basictypeNONE;
7376       kt = FFEINFO_kindtypeNONE;
7377       if (ffecom_is_altreturning_)
7378         type = ffecom_tree_subr_type;
7379       else
7380         type = ffecom_tree_fun_type_void;
7381       charfunc = FALSE;
7382       cmplxfunc = FALSE;
7383       break;
7384
7385     default:
7386       assert ("say what??" == NULL);
7387       /* Fall through. */
7388     case FFEINFO_kindANY:
7389       gt = FFEGLOBAL_typeANY;
7390       bt = FFEINFO_basictypeNONE;
7391       kt = FFEINFO_kindtypeNONE;
7392       type = error_mark_node;
7393       charfunc = FALSE;
7394       cmplxfunc = FALSE;
7395       break;
7396     }
7397
7398   if (altentries)
7399     {
7400       id = ffecom_get_invented_identifier ("__g77_masterfun_%s",
7401                                            ffesymbol_text (fn));
7402     }
7403 #if FFETARGET_isENFORCED_MAIN
7404   else if (main_program)
7405     id = get_identifier (FFETARGET_nameENFORCED_MAIN_NAME);
7406 #endif
7407   else
7408     id = ffecom_get_external_identifier_ (fn);
7409
7410   start_function (id,
7411                   type,
7412                   0,            /* nested/inline */
7413                   !altentries); /* TREE_PUBLIC */
7414
7415   TREE_USED (current_function_decl) = 1;        /* Avoid spurious warning if altentries. */
7416
7417   if (!altentries
7418       && ((g = ffesymbol_global (fn)) != NULL)
7419       && ((ffeglobal_type (g) == gt)
7420           || (ffeglobal_type (g) == egt)))
7421     {
7422       ffeglobal_set_hook (g, current_function_decl);
7423     }
7424
7425   yes = suspend_momentary ();
7426
7427   /* Arg handling needs exec-transitioned ffesymbols to work with.  But
7428      exec-transitioning needs current_function_decl to be filled in.  So we
7429      do these things in two phases. */
7430
7431   if (altentries)
7432     {                           /* 1st arg identifies which entrypoint. */
7433       ffecom_which_entrypoint_decl_
7434         = build_decl (PARM_DECL,
7435                       ffecom_get_invented_identifier ("__g77_%s",
7436                                                       "which_entrypoint"),
7437                       integer_type_node);
7438       push_parm_decl (ffecom_which_entrypoint_decl_);
7439     }
7440
7441   if (charfunc
7442       || cmplxfunc
7443       || multi)
7444     {                           /* Arg for result (return value). */
7445       tree type;
7446       tree length;
7447
7448       if (charfunc)
7449         type = ffecom_tree_type[FFEINFO_basictypeCHARACTER][kt];
7450       else if (cmplxfunc)
7451         type = ffecom_tree_type[FFEINFO_basictypeCOMPLEX][kt];
7452       else
7453         type = ffecom_multi_type_node_;
7454
7455       result = ffecom_get_invented_identifier ("__g77_%s", "result");
7456
7457       /* Make length arg _and_ enhance type info for CHAR arg itself.  */
7458
7459       if (charfunc)
7460         length = ffecom_char_enhance_arg_ (&type, fn);
7461       else
7462         length = NULL_TREE;     /* Not ref'd if !charfunc. */
7463
7464       type = build_pointer_type (type);
7465       result = build_decl (PARM_DECL, result, type);
7466
7467       push_parm_decl (result);
7468       if (multi)
7469         ffecom_multi_retval_ = result;
7470       else
7471         ffecom_func_result_ = result;
7472
7473       if (charfunc)
7474         {
7475           push_parm_decl (length);
7476           ffecom_func_length_ = length;
7477         }
7478     }
7479
7480   if (ffecom_primary_entry_is_proc_)
7481     {
7482       if (altentries)
7483         arglist = ffecom_master_arglist_;
7484       else
7485         arglist = ffesymbol_dummyargs (fn);
7486       ffecom_push_dummy_decls_ (arglist, FALSE);
7487     }
7488
7489   resume_momentary (yes);
7490
7491   if (TREE_CODE (current_function_decl) != ERROR_MARK)
7492     store_parm_decls (main_program ? 1 : 0);
7493
7494   ffecom_start_compstmt ();
7495   /* Disallow temp vars at this level.  */
7496   current_binding_level->prep_state = 2;
7497
7498   lineno = old_lineno;
7499   input_filename = old_input_filename;
7500
7501   /* This handles any symbols still untransformed, in case -g specified.
7502      This used to be done in ffecom_finish_progunit, but it turns out to
7503      be necessary to do it here so that statement functions are
7504      expanded before code.  But don't bother for BLOCK DATA.  */
7505
7506   if (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
7507     ffesymbol_drive (ffecom_finish_symbol_transform_);
7508 }
7509
7510 #endif
7511 /* ffecom_sym_transform_ -- Transform FFE sym into backend sym
7512
7513    ffesymbol s;
7514    ffecom_sym_transform_(s);
7515
7516    The ffesymbol_hook info for s is updated with appropriate backend info
7517    on the symbol.  */
7518
7519 #if FFECOM_targetCURRENT == FFECOM_targetGCC
7520 static ffesymbol
7521 ffecom_sym_transform_ (ffesymbol s)
7522 {
7523   tree t;                       /* Transformed thingy. */
7524   tree tlen;                    /* Length if CHAR*(*). */
7525   bool addr;                    /* Is t the address of the thingy? */
7526   ffeinfoBasictype bt;
7527   ffeinfoKindtype kt;
7528   ffeglobal g;
7529   int yes;
7530   int old_lineno = lineno;
7531   char *old_input_filename = input_filename;
7532
7533   /* Must ensure special ASSIGN variables are declared at top of outermost
7534      block, else they'll end up in the innermost block when their first
7535      ASSIGN is seen, which leaves them out of scope when they're the
7536      subject of a GOTO or I/O statement.
7537
7538      We make this variable even if -fugly-assign.  Just let it go unused,
7539      in case it turns out there are cases where we really want to use this
7540      variable anyway (e.g. ASSIGN to INTEGER*2 variable).  */
7541
7542   if (! ffecom_transform_only_dummies_
7543       && ffesymbol_assigned (s)
7544       && ! ffesymbol_hook (s).assign_tree)
7545     s = ffecom_sym_transform_assign_ (s);
7546
7547   if (ffesymbol_sfdummyparent (s) == NULL)
7548     {
7549       input_filename = ffesymbol_where_filename (s);
7550       lineno = ffesymbol_where_filelinenum (s);
7551     }
7552   else
7553     {
7554       ffesymbol sf = ffesymbol_sfdummyparent (s);
7555
7556       input_filename = ffesymbol_where_filename (sf);
7557       lineno = ffesymbol_where_filelinenum (sf);
7558     }
7559
7560   bt = ffeinfo_basictype (ffebld_info (s));
7561   kt = ffeinfo_kindtype (ffebld_info (s));
7562
7563   t = NULL_TREE;
7564   tlen = NULL_TREE;
7565   addr = FALSE;
7566
7567   switch (ffesymbol_kind (s))
7568     {
7569     case FFEINFO_kindNONE:
7570       switch (ffesymbol_where (s))
7571         {
7572         case FFEINFO_whereDUMMY:        /* Subroutine or function. */
7573           assert (ffecom_transform_only_dummies_);
7574
7575           /* Before 0.4, this could be ENTITY/DUMMY, but see
7576              ffestu_sym_end_transition -- no longer true (in particular, if
7577              it could be an ENTITY, it _will_ be made one, so that
7578              possibility won't come through here).  So we never make length
7579              arg for CHARACTER type.  */
7580
7581           t = build_decl (PARM_DECL,
7582                           ffecom_get_identifier_ (ffesymbol_text (s)),
7583                           ffecom_tree_ptr_to_subr_type);
7584 #if BUILT_FOR_270
7585           DECL_ARTIFICIAL (t) = 1;
7586 #endif
7587           addr = TRUE;
7588           break;
7589
7590         case FFEINFO_whereGLOBAL:       /* Subroutine or function. */
7591           assert (!ffecom_transform_only_dummies_);
7592
7593           if (((g = ffesymbol_global (s)) != NULL)
7594               && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7595                   || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7596                   || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
7597               && (ffeglobal_hook (g) != NULL_TREE)
7598               && ffe_is_globals ())
7599             {
7600               t = ffeglobal_hook (g);
7601               break;
7602             }
7603
7604           t = build_decl (FUNCTION_DECL,
7605                           ffecom_get_external_identifier_ (s),
7606                           ffecom_tree_subr_type);       /* Assume subr. */
7607           DECL_EXTERNAL (t) = 1;
7608           TREE_PUBLIC (t) = 1;
7609
7610           t = start_decl (t, FALSE);
7611           finish_decl (t, NULL_TREE, FALSE);
7612
7613           if ((g != NULL)
7614               && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
7615                   || (ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
7616                   || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
7617             ffeglobal_set_hook (g, t);
7618
7619           ffecom_save_tree_forever (t);
7620
7621           break;
7622
7623         default:
7624           assert ("NONE where unexpected" == NULL);
7625           /* Fall through. */
7626         case FFEINFO_whereANY:
7627           break;
7628         }
7629       break;
7630
7631     case FFEINFO_kindENTITY:
7632       switch (ffeinfo_where (ffesymbol_info (s)))
7633         {
7634
7635         case FFEINFO_whereCONSTANT:
7636           /* ~~Debugging info needed? */
7637           assert (!ffecom_transform_only_dummies_);
7638           t = error_mark_node;  /* Shouldn't ever see this in expr. */
7639           break;
7640
7641         case FFEINFO_whereLOCAL:
7642           assert (!ffecom_transform_only_dummies_);
7643
7644           {
7645             ffestorag st = ffesymbol_storage (s);
7646             tree type;
7647
7648             if ((st != NULL)
7649                 && (ffestorag_size (st) == 0))
7650               {
7651                 t = error_mark_node;
7652                 break;
7653               }
7654
7655             yes = suspend_momentary ();
7656             type = ffecom_type_localvar_ (s, bt, kt);
7657             resume_momentary (yes);
7658
7659             if (type == error_mark_node)
7660               {
7661                 t = error_mark_node;
7662                 break;
7663               }
7664
7665             if ((st != NULL)
7666                 && (ffestorag_parent (st) != NULL))
7667               {                 /* Child of EQUIVALENCE parent. */
7668                 ffestorag est;
7669                 tree et;
7670                 int yes;
7671                 ffetargetOffset offset;
7672
7673                 est = ffestorag_parent (st);
7674                 ffecom_transform_equiv_ (est);
7675
7676                 et = ffestorag_hook (est);
7677                 assert (et != NULL_TREE);
7678
7679                 if (! TREE_STATIC (et))
7680                   put_var_into_stack (et);
7681
7682                 yes = suspend_momentary ();
7683
7684                 offset = ffestorag_modulo (est)
7685                   + ffestorag_offset (ffesymbol_storage (s))
7686                   - ffestorag_offset (est);
7687
7688                 ffecom_debug_kludge_ (et, "EQUIVALENCE", s, type, offset);
7689
7690                 /* (t_type *) (((char *) &et) + offset) */
7691
7692                 t = convert (string_type_node,  /* (char *) */
7693                              ffecom_1 (ADDR_EXPR,
7694                                        build_pointer_type (TREE_TYPE (et)),
7695                                        et));
7696                 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
7697                               t,
7698                               build_int_2 (offset, 0));
7699                 t = convert (build_pointer_type (type),
7700                              t);
7701                 TREE_CONSTANT (t) = staticp (et);
7702
7703                 addr = TRUE;
7704
7705                 resume_momentary (yes);
7706               }
7707             else
7708               {
7709                 tree initexpr;
7710                 bool init = ffesymbol_is_init (s);
7711
7712                 yes = suspend_momentary ();
7713
7714                 t = build_decl (VAR_DECL,
7715                                 ffecom_get_identifier_ (ffesymbol_text (s)),
7716                                 type);
7717
7718                 if (init
7719                     || ffesymbol_namelisted (s)
7720 #ifdef FFECOM_sizeMAXSTACKITEM
7721                     || ((st != NULL)
7722                         && (ffestorag_size (st) > FFECOM_sizeMAXSTACKITEM))
7723 #endif
7724                     || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
7725                         && (ffecom_primary_entry_kind_
7726                             != FFEINFO_kindBLOCKDATA)
7727                         && (ffesymbol_is_save (s) || ffe_is_saveall ())))
7728                   TREE_STATIC (t) = !ffesymbol_attr (s, FFESYMBOL_attrADJUSTABLE);
7729                 else
7730                   TREE_STATIC (t) = 0;  /* No need to make static. */
7731
7732                 if (init || ffe_is_init_local_zero ())
7733                   DECL_INITIAL (t) = error_mark_node;
7734
7735                 /* Keep -Wunused from complaining about var if it
7736                    is used as sfunc arg or DATA implied-DO.  */
7737                 if (ffesymbol_attrs (s) & FFESYMBOL_attrsSFARG)
7738                   DECL_IN_SYSTEM_HEADER (t) = 1;
7739
7740                 t = start_decl (t, FALSE);
7741
7742                 if (init)
7743                   {
7744                     if (ffesymbol_init (s) != NULL)
7745                       initexpr = ffecom_expr (ffesymbol_init (s));
7746                     else
7747                       initexpr = ffecom_init_zero_ (t);
7748                   }
7749                 else if (ffe_is_init_local_zero ())
7750                   initexpr = ffecom_init_zero_ (t);
7751                 else
7752                   initexpr = NULL_TREE; /* Not ref'd if !init. */
7753
7754                 finish_decl (t, initexpr, FALSE);
7755
7756                 if (st != NULL && DECL_SIZE (t) != error_mark_node)
7757                   {
7758                     assert (TREE_CODE (DECL_SIZE_UNIT (t)) == INTEGER_CST);
7759                     assert (0 == compare_tree_int (DECL_SIZE_UNIT (t),
7760                                                    ffestorag_size (st)));
7761                   }
7762
7763                 resume_momentary (yes);
7764               }
7765           }
7766           break;
7767
7768         case FFEINFO_whereRESULT:
7769           assert (!ffecom_transform_only_dummies_);
7770
7771           if (bt == FFEINFO_basictypeCHARACTER)
7772             {                   /* Result is already in list of dummies, use
7773                                    it (& length). */
7774               t = ffecom_func_result_;
7775               tlen = ffecom_func_length_;
7776               addr = TRUE;
7777               break;
7778             }
7779           if ((ffecom_num_entrypoints_ == 0)
7780               && (bt == FFEINFO_basictypeCOMPLEX)
7781               && (ffesymbol_is_f2c (ffecom_primary_entry_)))
7782             {                   /* Result is already in list of dummies, use
7783                                    it. */
7784               t = ffecom_func_result_;
7785               addr = TRUE;
7786               break;
7787             }
7788           if (ffecom_func_result_ != NULL_TREE)
7789             {
7790               t = ffecom_func_result_;
7791               break;
7792             }
7793           if ((ffecom_num_entrypoints_ != 0)
7794               && (ffecom_master_bt_ == FFEINFO_basictypeNONE))
7795             {
7796               yes = suspend_momentary ();
7797
7798               assert (ffecom_multi_retval_ != NULL_TREE);
7799               t = ffecom_1 (INDIRECT_REF, ffecom_multi_type_node_,
7800                             ffecom_multi_retval_);
7801               t = ffecom_2 (COMPONENT_REF, ffecom_tree_type[bt][kt],
7802                             t, ffecom_multi_fields_[bt][kt]);
7803
7804               resume_momentary (yes);
7805               break;
7806             }
7807
7808           yes = suspend_momentary ();
7809
7810           t = build_decl (VAR_DECL,
7811                           ffecom_get_identifier_ (ffesymbol_text (s)),
7812                           ffecom_tree_type[bt][kt]);
7813           TREE_STATIC (t) = 0;  /* Put result on stack. */
7814           t = start_decl (t, FALSE);
7815           finish_decl (t, NULL_TREE, FALSE);
7816
7817           ffecom_func_result_ = t;
7818
7819           resume_momentary (yes);
7820           break;
7821
7822         case FFEINFO_whereDUMMY:
7823           {
7824             tree type;
7825             ffebld dl;
7826             ffebld dim;
7827             tree low;
7828             tree high;
7829             tree old_sizes;
7830             bool adjustable = FALSE;    /* Conditionally adjustable? */
7831
7832             type = ffecom_tree_type[bt][kt];
7833             if (ffesymbol_sfdummyparent (s) != NULL)
7834               {
7835                 if (current_function_decl == ffecom_outer_function_decl_)
7836                   {                     /* Exec transition before sfunc
7837                                            context; get it later. */
7838                     break;
7839                   }
7840                 t = ffecom_get_identifier_ (ffesymbol_text
7841                                             (ffesymbol_sfdummyparent (s)));
7842               }
7843             else
7844               t = ffecom_get_identifier_ (ffesymbol_text (s));
7845
7846             assert (ffecom_transform_only_dummies_);
7847
7848             old_sizes = get_pending_sizes ();
7849             put_pending_sizes (old_sizes);
7850
7851             if (bt == FFEINFO_basictypeCHARACTER)
7852               tlen = ffecom_char_enhance_arg_ (&type, s);
7853             type = ffecom_check_size_overflow_ (s, type, TRUE);
7854
7855             for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
7856               {
7857                 if (type == error_mark_node)
7858                   break;
7859
7860                 dim = ffebld_head (dl);
7861                 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
7862                 if ((ffebld_left (dim) == NULL) || ffecom_doing_entry_)
7863                   low = ffecom_integer_one_node;
7864                 else
7865                   low = ffecom_expr (ffebld_left (dim));
7866                 assert (ffebld_right (dim) != NULL);
7867                 if ((ffebld_op (ffebld_right (dim)) == FFEBLD_opSTAR)
7868                     || ffecom_doing_entry_)
7869                   {
7870                     /* Used to just do high=low.  But for ffecom_tree_
7871                        canonize_ref_, it probably is important to correctly
7872                        assess the size.  E.g. given COMPLEX C(*),CFUNC and
7873                        C(2)=CFUNC(C), overlap can happen, while it can't
7874                        for, say, C(1)=CFUNC(C(2)).  */
7875                     /* Even more recently used to set to INT_MAX, but that
7876                        broke when some overflow checking went into the back
7877                        end.  Now we just leave the upper bound unspecified.  */
7878                     high = NULL;
7879                   }
7880                 else
7881                   high = ffecom_expr (ffebld_right (dim));
7882
7883                 /* Determine whether array is conditionally adjustable,
7884                    to decide whether back-end magic is needed.
7885
7886                    Normally the front end uses the back-end function
7887                    variable_size to wrap SAVE_EXPR's around expressions
7888                    affecting the size/shape of an array so that the
7889                    size/shape info doesn't change during execution
7890                    of the compiled code even though variables and
7891                    functions referenced in those expressions might.
7892
7893                    variable_size also makes sure those saved expressions
7894                    get evaluated immediately upon entry to the
7895                    compiled procedure -- the front end normally doesn't
7896                    have to worry about that.
7897
7898                    However, there is a problem with this that affects
7899                    g77's implementation of entry points, and that is
7900                    that it is _not_ true that each invocation of the
7901                    compiled procedure is permitted to evaluate
7902                    array size/shape info -- because it is possible
7903                    that, for some invocations, that info is invalid (in
7904                    which case it is "promised" -- i.e. a violation of
7905                    the Fortran standard -- that the compiled code
7906                    won't reference the array or its size/shape
7907                    during that particular invocation).
7908
7909                    To phrase this in C terms, consider this gcc function:
7910
7911                      void foo (int *n, float (*a)[*n])
7912                      {
7913                        // a is "pointer to array ...", fyi.
7914                      }
7915
7916                    Suppose that, for some invocations, it is permitted
7917                    for a caller of foo to do this:
7918
7919                        foo (NULL, NULL);
7920
7921                    Now the _written_ code for foo can take such a call
7922                    into account by either testing explicitly for whether
7923                    (a == NULL) || (n == NULL) -- presumably it is
7924                    not permitted to reference *a in various fashions
7925                    if (n == NULL) I suppose -- or it can avoid it by
7926                    looking at other info (other arguments, static/global
7927                    data, etc.).
7928
7929                    However, this won't work in gcc 2.5.8 because it'll
7930                    automatically emit the code to save the "*n"
7931                    expression, which'll yield a NULL dereference for
7932                    the "foo (NULL, NULL)" call, something the code
7933                    for foo cannot prevent.
7934
7935                    g77 definitely needs to avoid executing such
7936                    code anytime the pointer to the adjustable array
7937                    is NULL, because even if its bounds expressions
7938                    don't have any references to possible "absent"
7939                    variables like "*n" -- say all variable references
7940                    are to COMMON variables, i.e. global (though in C,
7941                    local static could actually make sense) -- the
7942                    expressions could yield other run-time problems
7943                    for allowably "dead" values in those variables.
7944
7945                    For example, let's consider a more complicated
7946                    version of foo:
7947
7948                      extern int i;
7949                      extern int j;
7950
7951                      void foo (float (*a)[i/j])
7952                      {
7953                        ...
7954                      }
7955
7956                    The above is (essentially) quite valid for Fortran
7957                    but, again, for a call like "foo (NULL);", it is
7958                    permitted for i and j to be undefined when the
7959                    call is made.  If j happened to be zero, for
7960                    example, emitting the code to evaluate "i/j"
7961                    could result in a run-time error.
7962
7963                    Offhand, though I don't have my F77 or F90
7964                    standards handy, it might even be valid for a
7965                    bounds expression to contain a function reference,
7966                    in which case I doubt it is permitted for an
7967                    implementation to invoke that function in the
7968                    Fortran case involved here (invocation of an
7969                    alternate ENTRY point that doesn't have the adjustable
7970                    array as one of its arguments).
7971
7972                    So, the code that the compiler would normally emit
7973                    to preevaluate the size/shape info for an
7974                    adjustable array _must not_ be executed at run time
7975                    in certain cases.  Specifically, for Fortran,
7976                    the case is when the pointer to the adjustable
7977                    array == NULL.  (For gnu-ish C, it might be nice
7978                    for the source code itself to specify an expression
7979                    that, if TRUE, inhibits execution of the code.  Or
7980                    reverse the sense for elegance.)
7981
7982                    (Note that g77 could use a different test than NULL,
7983                    actually, since it happens to always pass an
7984                    integer to the called function that specifies which
7985                    entry point is being invoked.  Hmm, this might
7986                    solve the next problem.)
7987
7988                    One way a user could, I suppose, write "foo" so
7989                    it works is to insert COND_EXPR's for the
7990                    size/shape info so the dangerous stuff isn't
7991                    actually done, as in:
7992
7993                      void foo (int *n, float (*a)[(a == NULL) ? 0 : *n])
7994                      {
7995                        ...
7996                      }
7997
7998                    The next problem is that the front end needs to
7999                    be able to tell the back end about the array's
8000                    decl _before_ it tells it about the conditional
8001                    expression to inhibit evaluation of size/shape info,
8002                    as shown above.
8003
8004                    To solve this, the front end needs to be able
8005                    to give the back end the expression to inhibit
8006                    generation of the preevaluation code _after_
8007                    it makes the decl for the adjustable array.
8008
8009                    Until then, the above example using the COND_EXPR
8010                    doesn't pass muster with gcc because the "(a == NULL)"
8011                    part has a reference to "a", which is still
8012                    undefined at that point.
8013
8014                    g77 will therefore use a different mechanism in the
8015                    meantime.  */
8016
8017                 if (!adjustable
8018                     && ((TREE_CODE (low) != INTEGER_CST)
8019                         || (high && TREE_CODE (high) != INTEGER_CST)))
8020                   adjustable = TRUE;
8021
8022 #if 0                           /* Old approach -- see below. */
8023                 if (TREE_CODE (low) != INTEGER_CST)
8024                   low = ffecom_3 (COND_EXPR, integer_type_node,
8025                                   ffecom_adjarray_passed_ (s),
8026                                   low,
8027                                   ffecom_integer_zero_node);
8028
8029                 if (high && TREE_CODE (high) != INTEGER_CST)
8030                   high = ffecom_3 (COND_EXPR, integer_type_node,
8031                                    ffecom_adjarray_passed_ (s),
8032                                    high,
8033                                    ffecom_integer_zero_node);
8034 #endif
8035
8036                 /* ~~~gcc/stor-layout.c (layout_type) should do this,
8037                    probably.  Fixes 950302-1.f.  */
8038
8039                 if (TREE_CODE (low) != INTEGER_CST)
8040                   low = variable_size (low);
8041
8042                 /* ~~~Similarly, this fixes dumb0.f.  The C front end
8043                    does this, which is why dumb0.c would work.  */
8044
8045                 if (high && TREE_CODE (high) != INTEGER_CST)
8046                   high = variable_size (high);
8047
8048                 type
8049                   = build_array_type
8050                     (type,
8051                      build_range_type (ffecom_integer_type_node,
8052                                        low, high));
8053                 type = ffecom_check_size_overflow_ (s, type, TRUE);
8054               }
8055
8056             if (type == error_mark_node)
8057               {
8058                 t = error_mark_node;
8059                 break;
8060               }
8061
8062             if ((ffesymbol_sfdummyparent (s) == NULL)
8063                  || (ffesymbol_basictype (s) == FFEINFO_basictypeCHARACTER))
8064               {
8065                 type = build_pointer_type (type);
8066                 addr = TRUE;
8067               }
8068
8069             t = build_decl (PARM_DECL, t, type);
8070 #if BUILT_FOR_270
8071             DECL_ARTIFICIAL (t) = 1;
8072 #endif
8073
8074             /* If this arg is present in every entry point's list of
8075                dummy args, then we're done.  */
8076
8077             if (ffesymbol_numentries (s)
8078                 == (ffecom_num_entrypoints_ + 1))
8079               break;
8080
8081 #if 1
8082
8083             /* If variable_size in stor-layout has been called during
8084                the above, then get_pending_sizes should have the
8085                yet-to-be-evaluated saved expressions pending.
8086                Make the whole lot of them get emitted, conditionally
8087                on whether the array decl ("t" above) is not NULL.  */
8088
8089             {
8090               tree sizes = get_pending_sizes ();
8091               tree tem;
8092
8093               for (tem = sizes;
8094                    tem != old_sizes;
8095                    tem = TREE_CHAIN (tem))
8096                 {
8097                   tree temv = TREE_VALUE (tem);
8098
8099                   if (sizes == tem)
8100                     sizes = temv;
8101                   else
8102                     sizes
8103                       = ffecom_2 (COMPOUND_EXPR,
8104                                   TREE_TYPE (sizes),
8105                                   temv,
8106                                   sizes);
8107                 }
8108
8109               if (sizes != tem)
8110                 {
8111                   sizes
8112                     = ffecom_3 (COND_EXPR,
8113                                 TREE_TYPE (sizes),
8114                                 ffecom_2 (NE_EXPR,
8115                                           integer_type_node,
8116                                           t,
8117                                           null_pointer_node),
8118                                 sizes,
8119                                 convert (TREE_TYPE (sizes),
8120                                          integer_zero_node));
8121                   sizes = ffecom_save_tree (sizes);
8122
8123                   sizes
8124                     = tree_cons (NULL_TREE, sizes, tem);
8125                 }
8126
8127               if (sizes)
8128                 put_pending_sizes (sizes);
8129             }
8130
8131 #else
8132 #if 0
8133             if (adjustable
8134                 && (ffesymbol_numentries (s)
8135                     != ffecom_num_entrypoints_ + 1))
8136               DECL_SOMETHING (t)
8137                 = ffecom_2 (NE_EXPR, integer_type_node,
8138                             t,
8139                             null_pointer_node);
8140 #else
8141 #if 0
8142             if (adjustable
8143                 && (ffesymbol_numentries (s)
8144                     != ffecom_num_entrypoints_ + 1))
8145               {
8146                 ffebad_start (FFEBAD_MISSING_ADJARRAY_UNSUPPORTED);
8147                 ffebad_here (0, ffesymbol_where_line (s),
8148                              ffesymbol_where_column (s));
8149                 ffebad_string (ffesymbol_text (s));
8150                 ffebad_finish ();
8151               }
8152 #endif
8153 #endif
8154 #endif
8155           }
8156           break;
8157
8158         case FFEINFO_whereCOMMON:
8159           {
8160             ffesymbol cs;
8161             ffeglobal cg;
8162             tree ct;
8163             ffestorag st = ffesymbol_storage (s);
8164             tree type;
8165             int yes;
8166
8167             cs = ffesymbol_common (s);  /* The COMMON area itself.  */
8168             if (st != NULL)     /* Else not laid out. */
8169               {
8170                 ffecom_transform_common_ (cs);
8171                 st = ffesymbol_storage (s);
8172               }
8173
8174             yes = suspend_momentary ();
8175
8176             type = ffecom_type_localvar_ (s, bt, kt);
8177
8178             cg = ffesymbol_global (cs); /* The global COMMON info.  */
8179             if ((cg == NULL)
8180                 || (ffeglobal_type (cg) != FFEGLOBAL_typeCOMMON))
8181               ct = NULL_TREE;
8182             else
8183               ct = ffeglobal_hook (cg); /* The common area's tree.  */
8184
8185             if ((ct == NULL_TREE)
8186                 || (st == NULL)
8187                 || (type == error_mark_node))
8188               t = error_mark_node;
8189             else
8190               {
8191                 ffetargetOffset offset;
8192                 ffestorag cst;
8193
8194                 cst = ffestorag_parent (st);
8195                 assert (cst == ffesymbol_storage (cs));
8196
8197                 offset = ffestorag_modulo (cst)
8198                   + ffestorag_offset (st)
8199                   - ffestorag_offset (cst);
8200
8201                 ffecom_debug_kludge_ (ct, "COMMON", s, type, offset);
8202
8203                 /* (t_type *) (((char *) &ct) + offset) */
8204
8205                 t = convert (string_type_node,  /* (char *) */
8206                              ffecom_1 (ADDR_EXPR,
8207                                        build_pointer_type (TREE_TYPE (ct)),
8208                                        ct));
8209                 t = ffecom_2 (PLUS_EXPR, TREE_TYPE (t),
8210                               t,
8211                               build_int_2 (offset, 0));
8212                 t = convert (build_pointer_type (type),
8213                              t);
8214                 TREE_CONSTANT (t) = 1;
8215
8216                 addr = TRUE;
8217               }
8218
8219             resume_momentary (yes);
8220           }
8221           break;
8222
8223         case FFEINFO_whereIMMEDIATE:
8224         case FFEINFO_whereGLOBAL:
8225         case FFEINFO_whereFLEETING:
8226         case FFEINFO_whereFLEETING_CADDR:
8227         case FFEINFO_whereFLEETING_IADDR:
8228         case FFEINFO_whereINTRINSIC:
8229         case FFEINFO_whereCONSTANT_SUBOBJECT:
8230         default:
8231           assert ("ENTITY where unheard of" == NULL);
8232           /* Fall through. */
8233         case FFEINFO_whereANY:
8234           t = error_mark_node;
8235           break;
8236         }
8237       break;
8238
8239     case FFEINFO_kindFUNCTION:
8240       switch (ffeinfo_where (ffesymbol_info (s)))
8241         {
8242         case FFEINFO_whereLOCAL:        /* Me. */
8243           assert (!ffecom_transform_only_dummies_);
8244           t = current_function_decl;
8245           break;
8246
8247         case FFEINFO_whereGLOBAL:
8248           assert (!ffecom_transform_only_dummies_);
8249
8250           if (((g = ffesymbol_global (s)) != NULL)
8251               && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8252                   || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8253               && (ffeglobal_hook (g) != NULL_TREE)
8254               && ffe_is_globals ())
8255             {
8256               t = ffeglobal_hook (g);
8257               break;
8258             }
8259
8260           if (ffesymbol_is_f2c (s)
8261               && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8262             t = ffecom_tree_fun_type[bt][kt];
8263           else
8264             t = build_function_type (ffecom_tree_type[bt][kt], NULL_TREE);
8265
8266           t = build_decl (FUNCTION_DECL,
8267                           ffecom_get_external_identifier_ (s),
8268                           t);
8269           DECL_EXTERNAL (t) = 1;
8270           TREE_PUBLIC (t) = 1;
8271
8272           t = start_decl (t, FALSE);
8273           finish_decl (t, NULL_TREE, FALSE);
8274
8275           if ((g != NULL)
8276               && ((ffeglobal_type (g) == FFEGLOBAL_typeFUNC)
8277                   || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8278             ffeglobal_set_hook (g, t);
8279
8280           ffecom_save_tree_forever (t);
8281
8282           break;
8283
8284         case FFEINFO_whereDUMMY:
8285           assert (ffecom_transform_only_dummies_);
8286
8287           if (ffesymbol_is_f2c (s)
8288               && (ffesymbol_where (s) != FFEINFO_whereCONSTANT))
8289             t = ffecom_tree_ptr_to_fun_type[bt][kt];
8290           else
8291             t = build_pointer_type
8292               (build_function_type (ffecom_tree_type[bt][kt], NULL_TREE));
8293
8294           t = build_decl (PARM_DECL,
8295                           ffecom_get_identifier_ (ffesymbol_text (s)),
8296                           t);
8297 #if BUILT_FOR_270
8298           DECL_ARTIFICIAL (t) = 1;
8299 #endif
8300           addr = TRUE;
8301           break;
8302
8303         case FFEINFO_whereCONSTANT:     /* Statement function. */
8304           assert (!ffecom_transform_only_dummies_);
8305           t = ffecom_gen_sfuncdef_ (s, bt, kt);
8306           break;
8307
8308         case FFEINFO_whereINTRINSIC:
8309           assert (!ffecom_transform_only_dummies_);
8310           break;                /* Let actual references generate their
8311                                    decls. */
8312
8313         default:
8314           assert ("FUNCTION where unheard of" == NULL);
8315           /* Fall through. */
8316         case FFEINFO_whereANY:
8317           t = error_mark_node;
8318           break;
8319         }
8320       break;
8321
8322     case FFEINFO_kindSUBROUTINE:
8323       switch (ffeinfo_where (ffesymbol_info (s)))
8324         {
8325         case FFEINFO_whereLOCAL:        /* Me. */
8326           assert (!ffecom_transform_only_dummies_);
8327           t = current_function_decl;
8328           break;
8329
8330         case FFEINFO_whereGLOBAL:
8331           assert (!ffecom_transform_only_dummies_);
8332
8333           if (((g = ffesymbol_global (s)) != NULL)
8334               && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8335                   || (ffeglobal_type (g) == FFEGLOBAL_typeEXT))
8336               && (ffeglobal_hook (g) != NULL_TREE)
8337               && ffe_is_globals ())
8338             {
8339               t = ffeglobal_hook (g);
8340               break;
8341             }
8342
8343           t = build_decl (FUNCTION_DECL,
8344                           ffecom_get_external_identifier_ (s),
8345                           ffecom_tree_subr_type);
8346           DECL_EXTERNAL (t) = 1;
8347           TREE_PUBLIC (t) = 1;
8348
8349           t = start_decl (t, FALSE);
8350           finish_decl (t, NULL_TREE, FALSE);
8351
8352           if ((g != NULL)
8353               && ((ffeglobal_type (g) == FFEGLOBAL_typeSUBR)
8354                   || (ffeglobal_type (g) == FFEGLOBAL_typeEXT)))
8355             ffeglobal_set_hook (g, t);
8356
8357           ffecom_save_tree_forever (t);
8358
8359           break;
8360
8361         case FFEINFO_whereDUMMY:
8362           assert (ffecom_transform_only_dummies_);
8363
8364           t = build_decl (PARM_DECL,
8365                           ffecom_get_identifier_ (ffesymbol_text (s)),
8366                           ffecom_tree_ptr_to_subr_type);
8367 #if BUILT_FOR_270
8368           DECL_ARTIFICIAL (t) = 1;
8369 #endif
8370           addr = TRUE;
8371           break;
8372
8373         case FFEINFO_whereINTRINSIC:
8374           assert (!ffecom_transform_only_dummies_);
8375           break;                /* Let actual references generate their
8376                                    decls. */
8377
8378         default:
8379           assert ("SUBROUTINE where unheard of" == NULL);
8380           /* Fall through. */
8381         case FFEINFO_whereANY:
8382           t = error_mark_node;
8383           break;
8384         }
8385       break;
8386
8387     case FFEINFO_kindPROGRAM:
8388       switch (ffeinfo_where (ffesymbol_info (s)))
8389         {
8390         case FFEINFO_whereLOCAL:        /* Me. */
8391           assert (!ffecom_transform_only_dummies_);
8392           t = current_function_decl;
8393           break;
8394
8395         case FFEINFO_whereCOMMON:
8396         case FFEINFO_whereDUMMY:
8397         case FFEINFO_whereGLOBAL:
8398         case FFEINFO_whereRESULT:
8399         case FFEINFO_whereFLEETING:
8400         case FFEINFO_whereFLEETING_CADDR:
8401         case FFEINFO_whereFLEETING_IADDR:
8402         case FFEINFO_whereIMMEDIATE:
8403         case FFEINFO_whereINTRINSIC:
8404         case FFEINFO_whereCONSTANT:
8405         case FFEINFO_whereCONSTANT_SUBOBJECT:
8406         default:
8407           assert ("PROGRAM where unheard of" == NULL);
8408           /* Fall through. */
8409         case FFEINFO_whereANY:
8410           t = error_mark_node;
8411           break;
8412         }
8413       break;
8414
8415     case FFEINFO_kindBLOCKDATA:
8416       switch (ffeinfo_where (ffesymbol_info (s)))
8417         {
8418         case FFEINFO_whereLOCAL:        /* Me. */
8419           assert (!ffecom_transform_only_dummies_);
8420           t = current_function_decl;
8421           break;
8422
8423         case FFEINFO_whereGLOBAL:
8424           assert (!ffecom_transform_only_dummies_);
8425
8426           t = build_decl (FUNCTION_DECL,
8427                           ffecom_get_external_identifier_ (s),
8428                           ffecom_tree_blockdata_type);
8429           DECL_EXTERNAL (t) = 1;
8430           TREE_PUBLIC (t) = 1;
8431
8432           t = start_decl (t, FALSE);
8433           finish_decl (t, NULL_TREE, FALSE);
8434
8435           ffecom_save_tree_forever (t);
8436
8437           break;
8438
8439         case FFEINFO_whereCOMMON:
8440         case FFEINFO_whereDUMMY:
8441         case FFEINFO_whereRESULT:
8442         case FFEINFO_whereFLEETING:
8443         case FFEINFO_whereFLEETING_CADDR:
8444         case FFEINFO_whereFLEETING_IADDR:
8445         case FFEINFO_whereIMMEDIATE:
8446         case FFEINFO_whereINTRINSIC:
8447         case FFEINFO_whereCONSTANT:
8448         case FFEINFO_whereCONSTANT_SUBOBJECT:
8449         default:
8450           assert ("BLOCKDATA where unheard of" == NULL);
8451           /* Fall through. */
8452         case FFEINFO_whereANY:
8453           t = error_mark_node;
8454           break;
8455         }
8456       break;
8457
8458     case FFEINFO_kindCOMMON:
8459       switch (ffeinfo_where (ffesymbol_info (s)))
8460         {
8461         case FFEINFO_whereLOCAL:
8462           assert (!ffecom_transform_only_dummies_);
8463           ffecom_transform_common_ (s);
8464           break;
8465
8466         case FFEINFO_whereNONE:
8467         case FFEINFO_whereCOMMON:
8468         case FFEINFO_whereDUMMY:
8469         case FFEINFO_whereGLOBAL:
8470         case FFEINFO_whereRESULT:
8471         case FFEINFO_whereFLEETING:
8472         case FFEINFO_whereFLEETING_CADDR:
8473         case FFEINFO_whereFLEETING_IADDR:
8474         case FFEINFO_whereIMMEDIATE:
8475         case FFEINFO_whereINTRINSIC:
8476         case FFEINFO_whereCONSTANT:
8477         case FFEINFO_whereCONSTANT_SUBOBJECT:
8478         default:
8479           assert ("COMMON where unheard of" == NULL);
8480           /* Fall through. */
8481         case FFEINFO_whereANY:
8482           t = error_mark_node;
8483           break;
8484         }
8485       break;
8486
8487     case FFEINFO_kindCONSTRUCT:
8488       switch (ffeinfo_where (ffesymbol_info (s)))
8489         {
8490         case FFEINFO_whereLOCAL:
8491           assert (!ffecom_transform_only_dummies_);
8492           break;
8493
8494         case FFEINFO_whereNONE:
8495         case FFEINFO_whereCOMMON:
8496         case FFEINFO_whereDUMMY:
8497         case FFEINFO_whereGLOBAL:
8498         case FFEINFO_whereRESULT:
8499         case FFEINFO_whereFLEETING:
8500         case FFEINFO_whereFLEETING_CADDR:
8501         case FFEINFO_whereFLEETING_IADDR:
8502         case FFEINFO_whereIMMEDIATE:
8503         case FFEINFO_whereINTRINSIC:
8504         case FFEINFO_whereCONSTANT:
8505         case FFEINFO_whereCONSTANT_SUBOBJECT:
8506         default:
8507           assert ("CONSTRUCT where unheard of" == NULL);
8508           /* Fall through. */
8509         case FFEINFO_whereANY:
8510           t = error_mark_node;
8511           break;
8512         }
8513       break;
8514
8515     case FFEINFO_kindNAMELIST:
8516       switch (ffeinfo_where (ffesymbol_info (s)))
8517         {
8518         case FFEINFO_whereLOCAL:
8519           assert (!ffecom_transform_only_dummies_);
8520           t = ffecom_transform_namelist_ (s);
8521           break;
8522
8523         case FFEINFO_whereNONE:
8524         case FFEINFO_whereCOMMON:
8525         case FFEINFO_whereDUMMY:
8526         case FFEINFO_whereGLOBAL:
8527         case FFEINFO_whereRESULT:
8528         case FFEINFO_whereFLEETING:
8529         case FFEINFO_whereFLEETING_CADDR:
8530         case FFEINFO_whereFLEETING_IADDR:
8531         case FFEINFO_whereIMMEDIATE:
8532         case FFEINFO_whereINTRINSIC:
8533         case FFEINFO_whereCONSTANT:
8534         case FFEINFO_whereCONSTANT_SUBOBJECT:
8535         default:
8536           assert ("NAMELIST where unheard of" == NULL);
8537           /* Fall through. */
8538         case FFEINFO_whereANY:
8539           t = error_mark_node;
8540           break;
8541         }
8542       break;
8543
8544     default:
8545       assert ("kind unheard of" == NULL);
8546       /* Fall through. */
8547     case FFEINFO_kindANY:
8548       t = error_mark_node;
8549       break;
8550     }
8551
8552   ffesymbol_hook (s).decl_tree = t;
8553   ffesymbol_hook (s).length_tree = tlen;
8554   ffesymbol_hook (s).addr = addr;
8555
8556   lineno = old_lineno;
8557   input_filename = old_input_filename;
8558
8559   return s;
8560 }
8561
8562 #endif
8563 /* Transform into ASSIGNable symbol.
8564
8565    Symbol has already been transformed, but for whatever reason, the
8566    resulting decl_tree has been deemed not usable for an ASSIGN target.
8567    (E.g. it isn't wide enough to hold a pointer.)  So, here we invent
8568    another local symbol of type void * and stuff that in the assign_tree
8569    argument.  The F77/F90 standards allow this implementation.  */
8570
8571 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8572 static ffesymbol
8573 ffecom_sym_transform_assign_ (ffesymbol s)
8574 {
8575   tree t;                       /* Transformed thingy. */
8576   int yes;
8577   int old_lineno = lineno;
8578   char *old_input_filename = input_filename;
8579
8580   if (ffesymbol_sfdummyparent (s) == NULL)
8581     {
8582       input_filename = ffesymbol_where_filename (s);
8583       lineno = ffesymbol_where_filelinenum (s);
8584     }
8585   else
8586     {
8587       ffesymbol sf = ffesymbol_sfdummyparent (s);
8588
8589       input_filename = ffesymbol_where_filename (sf);
8590       lineno = ffesymbol_where_filelinenum (sf);
8591     }
8592
8593   assert (!ffecom_transform_only_dummies_);
8594
8595   yes = suspend_momentary ();
8596
8597   t = build_decl (VAR_DECL,
8598                   ffecom_get_invented_identifier ("__g77_ASSIGN_%s",
8599                                                    ffesymbol_text (s)),
8600                   TREE_TYPE (null_pointer_node));
8601
8602   switch (ffesymbol_where (s))
8603     {
8604     case FFEINFO_whereLOCAL:
8605       /* Unlike for regular vars, SAVE status is easy to determine for
8606          ASSIGNed vars, since there's no initialization, there's no
8607          effective storage association (so "SAVE J" does not apply to
8608          K even given "EQUIVALENCE (J,K)"), there's no size issue
8609          to worry about, etc.  */
8610       if ((ffesymbol_is_save (s) || ffe_is_saveall ())
8611           && (ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8612           && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA))
8613         TREE_STATIC (t) = 1;    /* SAVEd in proc, make static. */
8614       else
8615         TREE_STATIC (t) = 0;    /* No need to make static. */
8616       break;
8617
8618     case FFEINFO_whereCOMMON:
8619       TREE_STATIC (t) = 1;      /* Assume COMMONs always SAVEd. */
8620       break;
8621
8622     case FFEINFO_whereDUMMY:
8623       /* Note that twinning a DUMMY means the caller won't see
8624          the ASSIGNed value.  But both F77 and F90 allow implementations
8625          to do this, i.e. disallow Fortran code that would try and
8626          take advantage of actually putting a label into a variable
8627          via a dummy argument (or any other storage association, for
8628          that matter).  */
8629       TREE_STATIC (t) = 0;
8630       break;
8631
8632     default:
8633       TREE_STATIC (t) = 0;
8634       break;
8635     }
8636
8637   t = start_decl (t, FALSE);
8638   finish_decl (t, NULL_TREE, FALSE);
8639
8640   resume_momentary (yes);
8641
8642   ffesymbol_hook (s).assign_tree = t;
8643
8644   lineno = old_lineno;
8645   input_filename = old_input_filename;
8646
8647   return s;
8648 }
8649
8650 #endif
8651 /* Implement COMMON area in back end.
8652
8653    Because COMMON-based variables can be referenced in the dimension
8654    expressions of dummy (adjustable) arrays, and because dummies
8655    (in the gcc back end) need to be put in the outer binding level
8656    of a function (which has two binding levels, the outer holding
8657    the dummies and the inner holding the other vars), special care
8658    must be taken to handle COMMON areas.
8659
8660    The current strategy is basically to always tell the back end about
8661    the COMMON area as a top-level external reference to just a block
8662    of storage of the master type of that area (e.g. integer, real,
8663    character, whatever -- not a structure).  As a distinct action,
8664    if initial values are provided, tell the back end about the area
8665    as a top-level non-external (initialized) area and remember not to
8666    allow further initialization or expansion of the area.  Meanwhile,
8667    if no initialization happens at all, tell the back end about
8668    the largest size we've seen declared so the space does get reserved.
8669    (This function doesn't handle all that stuff, but it does some
8670    of the important things.)
8671
8672    Meanwhile, for COMMON variables themselves, just keep creating
8673    references like *((float *) (&common_area + offset)) each time
8674    we reference the variable.  In other words, don't make a VAR_DECL
8675    or any kind of component reference (like we used to do before 0.4),
8676    though we might do that as well just for debugging purposes (and
8677    stuff the rtl with the appropriate offset expression).  */
8678
8679 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8680 static void
8681 ffecom_transform_common_ (ffesymbol s)
8682 {
8683   ffestorag st = ffesymbol_storage (s);
8684   ffeglobal g = ffesymbol_global (s);
8685   tree cbt;
8686   tree cbtype;
8687   tree init;
8688   tree high;
8689   bool is_init = ffestorag_is_init (st);
8690
8691   assert (st != NULL);
8692
8693   if ((g == NULL)
8694       || (ffeglobal_type (g) != FFEGLOBAL_typeCOMMON))
8695     return;
8696
8697   /* First update the size of the area in global terms.  */
8698
8699   ffeglobal_size_common (s, ffestorag_size (st));
8700
8701   if (!ffeglobal_common_init (g))
8702     is_init = FALSE;    /* No explicit init, don't let erroneous joins init. */
8703
8704   cbt = ffeglobal_hook (g);
8705
8706   /* If we already have declared this common block for a previous program
8707      unit, and either we already initialized it or we don't have new
8708      initialization for it, just return what we have without changing it.  */
8709
8710   if ((cbt != NULL_TREE)
8711       && (!is_init
8712           || !DECL_EXTERNAL (cbt)))
8713     {
8714       if (st->hook == NULL) ffestorag_set_hook (st, cbt);
8715       return;
8716     }
8717
8718   /* Process inits.  */
8719
8720   if (is_init)
8721     {
8722       if (ffestorag_init (st) != NULL)
8723         {
8724           ffebld sexp;
8725
8726           /* Set the padding for the expression, so ffecom_expr
8727              knows to insert that many zeros.  */
8728           switch (ffebld_op (sexp = ffestorag_init (st)))
8729             {
8730             case FFEBLD_opCONTER:
8731               ffebld_conter_set_pad (sexp, ffestorag_modulo (st));
8732               break;
8733
8734             case FFEBLD_opARRTER:
8735               ffebld_arrter_set_pad (sexp, ffestorag_modulo (st));
8736               break;
8737
8738             case FFEBLD_opACCTER:
8739               ffebld_accter_set_pad (sexp, ffestorag_modulo (st));
8740               break;
8741
8742             default:
8743               assert ("bad op for cmn init (pad)" == NULL);
8744               break;
8745             }
8746
8747           init = ffecom_expr (sexp);
8748           if (init == error_mark_node)
8749             {                   /* Hopefully the back end complained! */
8750               init = NULL_TREE;
8751               if (cbt != NULL_TREE)
8752                 return;
8753             }
8754         }
8755       else
8756         init = error_mark_node;
8757     }
8758   else
8759     init = NULL_TREE;
8760
8761   /* cbtype must be permanently allocated!  */
8762
8763   /* Allocate the MAX of the areas so far, seen filewide.  */
8764   high = build_int_2 ((ffeglobal_common_size (g)
8765                        + ffeglobal_common_pad (g)) - 1, 0);
8766   TREE_TYPE (high) = ffecom_integer_type_node;
8767
8768   if (init)
8769     cbtype = build_array_type (char_type_node,
8770                                build_range_type (integer_type_node,
8771                                                  integer_zero_node,
8772                                                  high));
8773   else
8774     cbtype = build_array_type (char_type_node, NULL_TREE);
8775
8776   if (cbt == NULL_TREE)
8777     {
8778       cbt
8779         = build_decl (VAR_DECL,
8780                       ffecom_get_external_identifier_ (s),
8781                       cbtype);
8782       TREE_STATIC (cbt) = 1;
8783       TREE_PUBLIC (cbt) = 1;
8784     }
8785   else
8786     {
8787       assert (is_init);
8788       TREE_TYPE (cbt) = cbtype;
8789     }
8790   DECL_EXTERNAL (cbt) = init ? 0 : 1;
8791   DECL_INITIAL (cbt) = init ? error_mark_node : NULL_TREE;
8792
8793   cbt = start_decl (cbt, TRUE);
8794   if (ffeglobal_hook (g) != NULL)
8795     assert (cbt == ffeglobal_hook (g));
8796
8797   assert (!init || !DECL_EXTERNAL (cbt));
8798
8799   /* Make sure that any type can live in COMMON and be referenced
8800      without getting a bus error.  We could pick the most restrictive
8801      alignment of all entities actually placed in the COMMON, but
8802      this seems easy enough.  */
8803
8804   DECL_ALIGN (cbt) = BIGGEST_ALIGNMENT;
8805
8806   if (is_init && (ffestorag_init (st) == NULL))
8807     init = ffecom_init_zero_ (cbt);
8808
8809   finish_decl (cbt, init, TRUE);
8810
8811   if (is_init)
8812     ffestorag_set_init (st, ffebld_new_any ());
8813
8814   if (init)
8815     {
8816       assert (DECL_SIZE_UNIT (cbt) != NULL_TREE);
8817       assert (TREE_CODE (DECL_SIZE_UNIT (cbt)) == INTEGER_CST);
8818       assert (0 == compare_tree_int (DECL_SIZE_UNIT (cbt),
8819                                      (ffeglobal_common_size (g)
8820                                       + ffeglobal_common_pad (g))));
8821     }
8822
8823   ffeglobal_set_hook (g, cbt);
8824
8825   ffestorag_set_hook (st, cbt);
8826
8827   ffecom_save_tree_forever (cbt);
8828 }
8829
8830 #endif
8831 /* Make master area for local EQUIVALENCE.  */
8832
8833 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8834 static void
8835 ffecom_transform_equiv_ (ffestorag eqst)
8836 {
8837   tree eqt;
8838   tree eqtype;
8839   tree init;
8840   tree high;
8841   bool is_init = ffestorag_is_init (eqst);
8842   int yes;
8843
8844   assert (eqst != NULL);
8845
8846   eqt = ffestorag_hook (eqst);
8847
8848   if (eqt != NULL_TREE)
8849     return;
8850
8851   /* Process inits.  */
8852
8853   if (is_init)
8854     {
8855       if (ffestorag_init (eqst) != NULL)
8856         {
8857           ffebld sexp;
8858
8859           /* Set the padding for the expression, so ffecom_expr
8860              knows to insert that many zeros.  */
8861           switch (ffebld_op (sexp = ffestorag_init (eqst)))
8862             {
8863             case FFEBLD_opCONTER:
8864               ffebld_conter_set_pad (sexp, ffestorag_modulo (eqst));
8865               break;
8866
8867             case FFEBLD_opARRTER:
8868               ffebld_arrter_set_pad (sexp, ffestorag_modulo (eqst));
8869               break;
8870
8871             case FFEBLD_opACCTER:
8872               ffebld_accter_set_pad (sexp, ffestorag_modulo (eqst));
8873               break;
8874
8875             default:
8876               assert ("bad op for eqv init (pad)" == NULL);
8877               break;
8878             }
8879
8880           init = ffecom_expr (sexp);
8881           if (init == error_mark_node)
8882             init = NULL_TREE;   /* Hopefully the back end complained! */
8883         }
8884       else
8885         init = error_mark_node;
8886     }
8887   else if (ffe_is_init_local_zero ())
8888     init = error_mark_node;
8889   else
8890     init = NULL_TREE;
8891
8892   ffecom_member_namelisted_ = FALSE;
8893   ffestorag_drive (ffestorag_list_equivs (eqst),
8894                    &ffecom_member_phase1_,
8895                    eqst);
8896
8897   yes = suspend_momentary ();
8898
8899   high = build_int_2 ((ffestorag_size (eqst)
8900                        + ffestorag_modulo (eqst)) - 1, 0);
8901   TREE_TYPE (high) = ffecom_integer_type_node;
8902
8903   eqtype = build_array_type (char_type_node,
8904                              build_range_type (ffecom_integer_type_node,
8905                                                ffecom_integer_zero_node,
8906                                                high));
8907
8908   eqt = build_decl (VAR_DECL,
8909                     ffecom_get_invented_identifier ("__g77_equiv_%s",
8910                                                     ffesymbol_text
8911                                                     (ffestorag_symbol (eqst))),
8912                     eqtype);
8913   DECL_EXTERNAL (eqt) = 0;
8914   if (is_init
8915       || ffecom_member_namelisted_
8916 #ifdef FFECOM_sizeMAXSTACKITEM
8917       || (ffestorag_size (eqst) > FFECOM_sizeMAXSTACKITEM)
8918 #endif
8919       || ((ffecom_primary_entry_kind_ != FFEINFO_kindPROGRAM)
8920           && (ffecom_primary_entry_kind_ != FFEINFO_kindBLOCKDATA)
8921           && (ffestorag_is_save (eqst) || ffe_is_saveall ())))
8922     TREE_STATIC (eqt) = 1;
8923   else
8924     TREE_STATIC (eqt) = 0;
8925   TREE_PUBLIC (eqt) = 0;
8926   DECL_CONTEXT (eqt) = current_function_decl;
8927   if (init)
8928     DECL_INITIAL (eqt) = error_mark_node;
8929   else
8930     DECL_INITIAL (eqt) = NULL_TREE;
8931
8932   eqt = start_decl (eqt, FALSE);
8933
8934   /* Make sure that any type can live in EQUIVALENCE and be referenced
8935      without getting a bus error.  We could pick the most restrictive
8936      alignment of all entities actually placed in the EQUIVALENCE, but
8937      this seems easy enough.  */
8938
8939   DECL_ALIGN (eqt) = BIGGEST_ALIGNMENT;
8940
8941   if ((!is_init && ffe_is_init_local_zero ())
8942       || (is_init && (ffestorag_init (eqst) == NULL)))
8943     init = ffecom_init_zero_ (eqt);
8944
8945   finish_decl (eqt, init, FALSE);
8946
8947   if (is_init)
8948     ffestorag_set_init (eqst, ffebld_new_any ());
8949
8950   {
8951     assert (TREE_CODE (DECL_SIZE_UNIT (eqt)) == INTEGER_CST);
8952     assert (0 == compare_tree_int (DECL_SIZE_UNIT (eqt),
8953                                    (ffestorag_size (eqst)
8954                                     + ffestorag_modulo (eqst))));
8955   }
8956
8957   ffestorag_set_hook (eqst, eqt);
8958
8959 #ifdef SOMEONE_GETS_DEBUG_SUPPORT_WORKING
8960   ffestorag_drive (ffestorag_list_equivs (eqst),
8961                    &ffecom_member_phase2_,
8962                    eqst);
8963 #endif
8964
8965   resume_momentary (yes);
8966 }
8967
8968 #endif
8969 /* Implement NAMELIST in back end.  See f2c/format.c for more info.  */
8970
8971 #if FFECOM_targetCURRENT == FFECOM_targetGCC
8972 static tree
8973 ffecom_transform_namelist_ (ffesymbol s)
8974 {
8975   tree nmlt;
8976   tree nmltype = ffecom_type_namelist_ ();
8977   tree nmlinits;
8978   tree nameinit;
8979   tree varsinit;
8980   tree nvarsinit;
8981   tree field;
8982   tree high;
8983   int yes;
8984   int i;
8985   static int mynumber = 0;
8986
8987   yes = suspend_momentary ();
8988
8989   nmlt = build_decl (VAR_DECL,
8990                      ffecom_get_invented_identifier ("__g77_namelist_%d",
8991                                                      mynumber++),
8992                      nmltype);
8993   TREE_STATIC (nmlt) = 1;
8994   DECL_INITIAL (nmlt) = error_mark_node;
8995
8996   nmlt = start_decl (nmlt, FALSE);
8997
8998   /* Process inits.  */
8999
9000   i = strlen (ffesymbol_text (s));
9001
9002   high = build_int_2 (i, 0);
9003   TREE_TYPE (high) = ffecom_f2c_ftnlen_type_node;
9004
9005   nameinit = ffecom_build_f2c_string_ (i + 1,
9006                                        ffesymbol_text (s));
9007   TREE_TYPE (nameinit)
9008     = build_type_variant
9009     (build_array_type
9010      (char_type_node,
9011       build_range_type (ffecom_f2c_ftnlen_type_node,
9012                         ffecom_f2c_ftnlen_one_node,
9013                         high)),
9014      1, 0);
9015   TREE_CONSTANT (nameinit) = 1;
9016   TREE_STATIC (nameinit) = 1;
9017   nameinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (nameinit)),
9018                        nameinit);
9019
9020   varsinit = ffecom_vardesc_array_ (s);
9021   varsinit = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (varsinit)),
9022                        varsinit);
9023   TREE_CONSTANT (varsinit) = 1;
9024   TREE_STATIC (varsinit) = 1;
9025
9026   {
9027     ffebld b;
9028
9029     for (i = 0, b = ffesymbol_namelist (s); b != NULL; b = ffebld_trail (b))
9030       ++i;
9031   }
9032   nvarsinit = build_int_2 (i, 0);
9033   TREE_TYPE (nvarsinit) = integer_type_node;
9034   TREE_CONSTANT (nvarsinit) = 1;
9035   TREE_STATIC (nvarsinit) = 1;
9036
9037   nmlinits = build_tree_list ((field = TYPE_FIELDS (nmltype)), nameinit);
9038   TREE_CHAIN (nmlinits) = build_tree_list ((field = TREE_CHAIN (field)),
9039                                            varsinit);
9040   TREE_CHAIN (TREE_CHAIN (nmlinits))
9041     = build_tree_list ((field = TREE_CHAIN (field)), nvarsinit);
9042
9043   nmlinits = build (CONSTRUCTOR, nmltype, NULL_TREE, nmlinits);
9044   TREE_CONSTANT (nmlinits) = 1;
9045   TREE_STATIC (nmlinits) = 1;
9046
9047   finish_decl (nmlt, nmlinits, FALSE);
9048
9049   nmlt = ffecom_1 (ADDR_EXPR, build_pointer_type (nmltype), nmlt);
9050
9051   resume_momentary (yes);
9052
9053   return nmlt;
9054 }
9055
9056 #endif
9057
9058 /* A subroutine of ffecom_tree_canonize_ref_.  The incoming tree is
9059    analyzed on the assumption it is calculating a pointer to be
9060    indirected through.  It must return the proper decl and offset,
9061    taking into account different units of measurements for offsets.  */
9062
9063 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9064 static void
9065 ffecom_tree_canonize_ptr_ (tree *decl, tree *offset,
9066                            tree t)
9067 {
9068   switch (TREE_CODE (t))
9069     {
9070     case NOP_EXPR:
9071     case CONVERT_EXPR:
9072     case NON_LVALUE_EXPR:
9073       ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9074       break;
9075
9076     case PLUS_EXPR:
9077       ffecom_tree_canonize_ptr_ (decl, offset, TREE_OPERAND (t, 0));
9078       if ((*decl == NULL_TREE)
9079           || (*decl == error_mark_node))
9080         break;
9081
9082       if (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST)
9083         {
9084           /* An offset into COMMON.  */
9085           *offset = fold (build (PLUS_EXPR, TREE_TYPE (*offset),
9086                                  *offset, TREE_OPERAND (t, 1)));
9087           /* Convert offset (presumably in bytes) into canonical units
9088              (presumably bits).  */
9089           *offset = fold (build (MULT_EXPR, TREE_TYPE (*offset),
9090                                  TYPE_SIZE (TREE_TYPE (TREE_TYPE (t))),
9091                                  *offset));
9092           break;
9093         }
9094       /* Not a COMMON reference, so an unrecognized pattern.  */
9095       *decl = error_mark_node;
9096       break;
9097
9098     case PARM_DECL:
9099       *decl = t;
9100       *offset = bitsize_zero_node;
9101       break;
9102
9103     case ADDR_EXPR:
9104       if (TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL)
9105         {
9106           /* A reference to COMMON.  */
9107           *decl = TREE_OPERAND (t, 0);
9108           *offset = bitsize_zero_node;
9109           break;
9110         }
9111       /* Fall through.  */
9112     default:
9113       /* Not a COMMON reference, so an unrecognized pattern.  */
9114       *decl = error_mark_node;
9115       break;
9116     }
9117 }
9118 #endif
9119
9120 /* Given a tree that is possibly intended for use as an lvalue, return
9121    information representing a canonical view of that tree as a decl, an
9122    offset into that decl, and a size for the lvalue.
9123
9124    If there's no applicable decl, NULL_TREE is returned for the decl,
9125    and the other fields are left undefined.
9126
9127    If the tree doesn't fit the recognizable forms, an ERROR_MARK node
9128    is returned for the decl, and the other fields are left undefined.
9129
9130    Otherwise, the decl returned currently is either a VAR_DECL or a
9131    PARM_DECL.
9132
9133    The offset returned is always valid, but of course not necessarily
9134    a constant, and not necessarily converted into the appropriate
9135    type, leaving that up to the caller (so as to avoid that overhead
9136    if the decls being looked at are different anyway).
9137
9138    If the size cannot be determined (e.g. an adjustable array),
9139    an ERROR_MARK node is returned for the size.  Otherwise, the
9140    size returned is valid, not necessarily a constant, and not
9141    necessarily converted into the appropriate type as with the
9142    offset.
9143
9144    Note that the offset and size expressions are expressed in the
9145    base storage units (usually bits) rather than in the units of
9146    the type of the decl, because two decls with different types
9147    might overlap but with apparently non-overlapping array offsets,
9148    whereas converting the array offsets to consistant offsets will
9149    reveal the overlap.  */
9150
9151 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9152 static void
9153 ffecom_tree_canonize_ref_ (tree *decl, tree *offset,
9154                            tree *size, tree t)
9155 {
9156   /* The default path is to report a nonexistant decl.  */
9157   *decl = NULL_TREE;
9158
9159   if (t == NULL_TREE)
9160     return;
9161
9162   switch (TREE_CODE (t))
9163     {
9164     case ERROR_MARK:
9165     case IDENTIFIER_NODE:
9166     case INTEGER_CST:
9167     case REAL_CST:
9168     case COMPLEX_CST:
9169     case STRING_CST:
9170     case CONST_DECL:
9171     case PLUS_EXPR:
9172     case MINUS_EXPR:
9173     case MULT_EXPR:
9174     case TRUNC_DIV_EXPR:
9175     case CEIL_DIV_EXPR:
9176     case FLOOR_DIV_EXPR:
9177     case ROUND_DIV_EXPR:
9178     case TRUNC_MOD_EXPR:
9179     case CEIL_MOD_EXPR:
9180     case FLOOR_MOD_EXPR:
9181     case ROUND_MOD_EXPR:
9182     case RDIV_EXPR:
9183     case EXACT_DIV_EXPR:
9184     case FIX_TRUNC_EXPR:
9185     case FIX_CEIL_EXPR:
9186     case FIX_FLOOR_EXPR:
9187     case FIX_ROUND_EXPR:
9188     case FLOAT_EXPR:
9189     case EXPON_EXPR:
9190     case NEGATE_EXPR:
9191     case MIN_EXPR:
9192     case MAX_EXPR:
9193     case ABS_EXPR:
9194     case FFS_EXPR:
9195     case LSHIFT_EXPR:
9196     case RSHIFT_EXPR:
9197     case LROTATE_EXPR:
9198     case RROTATE_EXPR:
9199     case BIT_IOR_EXPR:
9200     case BIT_XOR_EXPR:
9201     case BIT_AND_EXPR:
9202     case BIT_ANDTC_EXPR:
9203     case BIT_NOT_EXPR:
9204     case TRUTH_ANDIF_EXPR:
9205     case TRUTH_ORIF_EXPR:
9206     case TRUTH_AND_EXPR:
9207     case TRUTH_OR_EXPR:
9208     case TRUTH_XOR_EXPR:
9209     case TRUTH_NOT_EXPR:
9210     case LT_EXPR:
9211     case LE_EXPR:
9212     case GT_EXPR:
9213     case GE_EXPR:
9214     case EQ_EXPR:
9215     case NE_EXPR:
9216     case COMPLEX_EXPR:
9217     case CONJ_EXPR:
9218     case REALPART_EXPR:
9219     case IMAGPART_EXPR:
9220     case LABEL_EXPR:
9221     case COMPONENT_REF:
9222     case COMPOUND_EXPR:
9223     case ADDR_EXPR:
9224       return;
9225
9226     case VAR_DECL:
9227     case PARM_DECL:
9228       *decl = t;
9229       *offset = bitsize_zero_node;
9230       *size = TYPE_SIZE (TREE_TYPE (t));
9231       return;
9232
9233     case ARRAY_REF:
9234       {
9235         tree array = TREE_OPERAND (t, 0);
9236         tree element = TREE_OPERAND (t, 1);
9237         tree init_offset;
9238
9239         if ((array == NULL_TREE)
9240             || (element == NULL_TREE))
9241           {
9242             *decl = error_mark_node;
9243             return;
9244           }
9245
9246         ffecom_tree_canonize_ref_ (decl, &init_offset, size,
9247                                    array);
9248         if ((*decl == NULL_TREE)
9249             || (*decl == error_mark_node))
9250           return;
9251
9252         *offset
9253           = size_binop (MULT_EXPR,
9254                         TYPE_SIZE (TREE_TYPE (TREE_TYPE (array))),
9255                         convert (sizetype,
9256                                  fold (build (MINUS_EXPR, TREE_TYPE (element),
9257                                               element,
9258                                               TYPE_MIN_VALUE
9259                                               (TYPE_DOMAIN
9260                                                (TREE_TYPE (array)))))));;
9261
9262         *offset = size_binop (PLUS_EXPR, convert (sizetype, init_offset),
9263                               *offset);
9264
9265         *size = TYPE_SIZE (TREE_TYPE (t));
9266         return;
9267       }
9268
9269     case INDIRECT_REF:
9270
9271       /* Most of this code is to handle references to COMMON.  And so
9272          far that is useful only for calling library functions, since
9273          external (user) functions might reference common areas.  But
9274          even calling an external function, it's worthwhile to decode
9275          COMMON references because if not storing into COMMON, we don't
9276          want COMMON-based arguments to gratuitously force use of a
9277          temporary.  */
9278
9279       *size = TYPE_SIZE (TREE_TYPE (t));
9280
9281       ffecom_tree_canonize_ptr_ (decl, offset,
9282                                  TREE_OPERAND (t, 0));
9283
9284       return;
9285
9286     case CONVERT_EXPR:
9287     case NOP_EXPR:
9288     case MODIFY_EXPR:
9289     case NON_LVALUE_EXPR:
9290     case RESULT_DECL:
9291     case FIELD_DECL:
9292     case COND_EXPR:             /* More cases than we can handle. */
9293     case SAVE_EXPR:
9294     case REFERENCE_EXPR:
9295     case PREDECREMENT_EXPR:
9296     case PREINCREMENT_EXPR:
9297     case POSTDECREMENT_EXPR:
9298     case POSTINCREMENT_EXPR:
9299     case CALL_EXPR:
9300     default:
9301       *decl = error_mark_node;
9302       return;
9303     }
9304 }
9305 #endif
9306
9307 /* Do divide operation appropriate to type of operands.  */
9308
9309 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9310 static tree
9311 ffecom_tree_divide_ (tree tree_type, tree left, tree right,
9312                      tree dest_tree, ffebld dest, bool *dest_used,
9313                      tree hook)
9314 {
9315   if ((left == error_mark_node)
9316       || (right == error_mark_node))
9317     return error_mark_node;
9318
9319   switch (TREE_CODE (tree_type))
9320     {
9321     case INTEGER_TYPE:
9322       return ffecom_2 (TRUNC_DIV_EXPR, tree_type,
9323                        left,
9324                        right);
9325
9326     case COMPLEX_TYPE:
9327       if (! optimize_size)
9328         return ffecom_2 (RDIV_EXPR, tree_type,
9329                          left,
9330                          right);
9331       {
9332         ffecomGfrt ix;
9333
9334         if (TREE_TYPE (tree_type)
9335             == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9336           ix = FFECOM_gfrtDIV_CC;       /* Overlapping result okay. */
9337         else
9338           ix = FFECOM_gfrtDIV_ZZ;       /* Overlapping result okay. */
9339
9340         left = ffecom_1 (ADDR_EXPR,
9341                          build_pointer_type (TREE_TYPE (left)),
9342                          left);
9343         left = build_tree_list (NULL_TREE, left);
9344         right = ffecom_1 (ADDR_EXPR,
9345                           build_pointer_type (TREE_TYPE (right)),
9346                           right);
9347         right = build_tree_list (NULL_TREE, right);
9348         TREE_CHAIN (left) = right;
9349
9350         return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9351                              ffecom_gfrt_kindtype (ix),
9352                              ffe_is_f2c_library (),
9353                              tree_type,
9354                              left,
9355                              dest_tree, dest, dest_used,
9356                              NULL_TREE, TRUE, hook);
9357       }
9358       break;
9359
9360     case RECORD_TYPE:
9361       {
9362         ffecomGfrt ix;
9363
9364         if (TREE_TYPE (TYPE_FIELDS (tree_type))
9365             == ffecom_tree_type [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1])
9366           ix = FFECOM_gfrtDIV_CC;       /* Overlapping result okay. */
9367         else
9368           ix = FFECOM_gfrtDIV_ZZ;       /* Overlapping result okay. */
9369
9370         left = ffecom_1 (ADDR_EXPR,
9371                          build_pointer_type (TREE_TYPE (left)),
9372                          left);
9373         left = build_tree_list (NULL_TREE, left);
9374         right = ffecom_1 (ADDR_EXPR,
9375                           build_pointer_type (TREE_TYPE (right)),
9376                           right);
9377         right = build_tree_list (NULL_TREE, right);
9378         TREE_CHAIN (left) = right;
9379
9380         return ffecom_call_ (ffecom_gfrt_tree_ (ix),
9381                              ffecom_gfrt_kindtype (ix),
9382                              ffe_is_f2c_library (),
9383                              tree_type,
9384                              left,
9385                              dest_tree, dest, dest_used,
9386                              NULL_TREE, TRUE, hook);
9387       }
9388       break;
9389
9390     default:
9391       return ffecom_2 (RDIV_EXPR, tree_type,
9392                        left,
9393                        right);
9394     }
9395 }
9396
9397 #endif
9398 /* Build type info for non-dummy variable.  */
9399
9400 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9401 static tree
9402 ffecom_type_localvar_ (ffesymbol s, ffeinfoBasictype bt,
9403                        ffeinfoKindtype kt)
9404 {
9405   tree type;
9406   ffebld dl;
9407   ffebld dim;
9408   tree lowt;
9409   tree hight;
9410
9411   type = ffecom_tree_type[bt][kt];
9412   if (bt == FFEINFO_basictypeCHARACTER)
9413     {
9414       hight = build_int_2 (ffesymbol_size (s), 0);
9415       TREE_TYPE (hight) = ffecom_f2c_ftnlen_type_node;
9416
9417       type
9418         = build_array_type
9419           (type,
9420            build_range_type (ffecom_f2c_ftnlen_type_node,
9421                              ffecom_f2c_ftnlen_one_node,
9422                              hight));
9423       type = ffecom_check_size_overflow_ (s, type, FALSE);
9424     }
9425
9426   for (dl = ffesymbol_dims (s); dl != NULL; dl = ffebld_trail (dl))
9427     {
9428       if (type == error_mark_node)
9429         break;
9430
9431       dim = ffebld_head (dl);
9432       assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
9433
9434       if (ffebld_left (dim) == NULL)
9435         lowt = integer_one_node;
9436       else
9437         lowt = ffecom_expr (ffebld_left (dim));
9438
9439       if (TREE_CODE (lowt) != INTEGER_CST)
9440         lowt = variable_size (lowt);
9441
9442       assert (ffebld_right (dim) != NULL);
9443       hight = ffecom_expr (ffebld_right (dim));
9444
9445       if (TREE_CODE (hight) != INTEGER_CST)
9446         hight = variable_size (hight);
9447
9448       type = build_array_type (type,
9449                                build_range_type (ffecom_integer_type_node,
9450                                                  lowt, hight));
9451       type = ffecom_check_size_overflow_ (s, type, FALSE);
9452     }
9453
9454   return type;
9455 }
9456
9457 #endif
9458 /* Build Namelist type.  */
9459
9460 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9461 static tree
9462 ffecom_type_namelist_ ()
9463 {
9464   static tree type = NULL_TREE;
9465
9466   if (type == NULL_TREE)
9467     {
9468       static tree namefield, varsfield, nvarsfield;
9469       tree vardesctype;
9470
9471       vardesctype = ffecom_type_vardesc_ ();
9472
9473       type = make_node (RECORD_TYPE);
9474
9475       vardesctype = build_pointer_type (build_pointer_type (vardesctype));
9476
9477       namefield = ffecom_decl_field (type, NULL_TREE, "name",
9478                                      string_type_node);
9479       varsfield = ffecom_decl_field (type, namefield, "vars", vardesctype);
9480       nvarsfield = ffecom_decl_field (type, varsfield, "nvars",
9481                                       integer_type_node);
9482
9483       TYPE_FIELDS (type) = namefield;
9484       layout_type (type);
9485
9486       ggc_add_tree_root (&type, 1);
9487     }
9488
9489   return type;
9490 }
9491
9492 #endif
9493
9494 /* Build Vardesc type.  */
9495
9496 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9497 static tree
9498 ffecom_type_vardesc_ ()
9499 {
9500   static tree type = NULL_TREE;
9501   static tree namefield, addrfield, dimsfield, typefield;
9502
9503   if (type == NULL_TREE)
9504     {
9505       type = make_node (RECORD_TYPE);
9506
9507       namefield = ffecom_decl_field (type, NULL_TREE, "name",
9508                                      string_type_node);
9509       addrfield = ffecom_decl_field (type, namefield, "addr",
9510                                      string_type_node);
9511       dimsfield = ffecom_decl_field (type, addrfield, "dims",
9512                                      ffecom_f2c_ptr_to_ftnlen_type_node);
9513       typefield = ffecom_decl_field (type, dimsfield, "type",
9514                                      integer_type_node);
9515
9516       TYPE_FIELDS (type) = namefield;
9517       layout_type (type);
9518
9519       ggc_add_tree_root (&type, 1);
9520     }
9521
9522   return type;
9523 }
9524
9525 #endif
9526
9527 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9528 static tree
9529 ffecom_vardesc_ (ffebld expr)
9530 {
9531   ffesymbol s;
9532
9533   assert (ffebld_op (expr) == FFEBLD_opSYMTER);
9534   s = ffebld_symter (expr);
9535
9536   if (ffesymbol_hook (s).vardesc_tree == NULL_TREE)
9537     {
9538       int i;
9539       tree vardesctype = ffecom_type_vardesc_ ();
9540       tree var;
9541       tree nameinit;
9542       tree dimsinit;
9543       tree addrinit;
9544       tree typeinit;
9545       tree field;
9546       tree varinits;
9547       int yes;
9548       static int mynumber = 0;
9549
9550       yes = suspend_momentary ();
9551
9552       var = build_decl (VAR_DECL,
9553                         ffecom_get_invented_identifier ("__g77_vardesc_%d",
9554                                                         mynumber++),
9555                         vardesctype);
9556       TREE_STATIC (var) = 1;
9557       DECL_INITIAL (var) = error_mark_node;
9558
9559       var = start_decl (var, FALSE);
9560
9561       /* Process inits.  */
9562
9563       nameinit = ffecom_build_f2c_string_ ((i = strlen (ffesymbol_text (s)))
9564                                            + 1,
9565                                            ffesymbol_text (s));
9566       TREE_TYPE (nameinit)
9567         = build_type_variant
9568         (build_array_type
9569          (char_type_node,
9570           build_range_type (integer_type_node,
9571                             integer_one_node,
9572                             build_int_2 (i, 0))),
9573          1, 0);
9574       TREE_CONSTANT (nameinit) = 1;
9575       TREE_STATIC (nameinit) = 1;
9576       nameinit = ffecom_1 (ADDR_EXPR,
9577                            build_pointer_type (TREE_TYPE (nameinit)),
9578                            nameinit);
9579
9580       addrinit = ffecom_arg_ptr_to_expr (expr, &typeinit);
9581
9582       dimsinit = ffecom_vardesc_dims_ (s);
9583
9584       if (typeinit == NULL_TREE)
9585         {
9586           ffeinfoBasictype bt = ffesymbol_basictype (s);
9587           ffeinfoKindtype kt = ffesymbol_kindtype (s);
9588           int tc = ffecom_f2c_typecode (bt, kt);
9589
9590           assert (tc != -1);
9591           typeinit = build_int_2 (tc, (tc < 0) ? -1 : 0);
9592         }
9593       else
9594         typeinit = ffecom_1 (NEGATE_EXPR, TREE_TYPE (typeinit), typeinit);
9595
9596       varinits = build_tree_list ((field = TYPE_FIELDS (vardesctype)),
9597                                   nameinit);
9598       TREE_CHAIN (varinits) = build_tree_list ((field = TREE_CHAIN (field)),
9599                                                addrinit);
9600       TREE_CHAIN (TREE_CHAIN (varinits))
9601         = build_tree_list ((field = TREE_CHAIN (field)), dimsinit);
9602       TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (varinits)))
9603         = build_tree_list ((field = TREE_CHAIN (field)), typeinit);
9604
9605       varinits = build (CONSTRUCTOR, vardesctype, NULL_TREE, varinits);
9606       TREE_CONSTANT (varinits) = 1;
9607       TREE_STATIC (varinits) = 1;
9608
9609       finish_decl (var, varinits, FALSE);
9610
9611       var = ffecom_1 (ADDR_EXPR, build_pointer_type (vardesctype), var);
9612
9613       resume_momentary (yes);
9614
9615       ffesymbol_hook (s).vardesc_tree = var;
9616     }
9617
9618   return ffesymbol_hook (s).vardesc_tree;
9619 }
9620
9621 #endif
9622 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9623 static tree
9624 ffecom_vardesc_array_ (ffesymbol s)
9625 {
9626   ffebld b;
9627   tree list;
9628   tree item = NULL_TREE;
9629   tree var;
9630   int i;
9631   int yes;
9632   static int mynumber = 0;
9633
9634   for (i = 0, list = NULL_TREE, b = ffesymbol_namelist (s);
9635        b != NULL;
9636        b = ffebld_trail (b), ++i)
9637     {
9638       tree t;
9639
9640       t = ffecom_vardesc_ (ffebld_head (b));
9641
9642       if (list == NULL_TREE)
9643         list = item = build_tree_list (NULL_TREE, t);
9644       else
9645         {
9646           TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9647           item = TREE_CHAIN (item);
9648         }
9649     }
9650
9651   yes = suspend_momentary ();
9652
9653   item = build_array_type (build_pointer_type (ffecom_type_vardesc_ ()),
9654                            build_range_type (integer_type_node,
9655                                              integer_one_node,
9656                                              build_int_2 (i, 0)));
9657   list = build (CONSTRUCTOR, item, NULL_TREE, list);
9658   TREE_CONSTANT (list) = 1;
9659   TREE_STATIC (list) = 1;
9660
9661   var = ffecom_get_invented_identifier ("__g77_vardesc_array_%d", mynumber++);
9662   var = build_decl (VAR_DECL, var, item);
9663   TREE_STATIC (var) = 1;
9664   DECL_INITIAL (var) = error_mark_node;
9665   var = start_decl (var, FALSE);
9666   finish_decl (var, list, FALSE);
9667
9668   resume_momentary (yes);
9669
9670   return var;
9671 }
9672
9673 #endif
9674 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9675 static tree
9676 ffecom_vardesc_dims_ (ffesymbol s)
9677 {
9678   if (ffesymbol_dims (s) == NULL)
9679     return convert (ffecom_f2c_ptr_to_ftnlen_type_node,
9680                     integer_zero_node);
9681
9682   {
9683     ffebld b;
9684     ffebld e;
9685     tree list;
9686     tree backlist;
9687     tree item = NULL_TREE;
9688     tree var;
9689     int yes;
9690     tree numdim;
9691     tree numelem;
9692     tree baseoff = NULL_TREE;
9693     static int mynumber = 0;
9694
9695     numdim = build_int_2 ((int) ffesymbol_rank (s), 0);
9696     TREE_TYPE (numdim) = ffecom_f2c_ftnlen_type_node;
9697
9698     numelem = ffecom_expr (ffesymbol_arraysize (s));
9699     TREE_TYPE (numelem) = ffecom_f2c_ftnlen_type_node;
9700
9701     list = NULL_TREE;
9702     backlist = NULL_TREE;
9703     for (b = ffesymbol_dims (s), e = ffesymbol_extents (s);
9704          b != NULL;
9705          b = ffebld_trail (b), e = ffebld_trail (e))
9706       {
9707         tree t;
9708         tree low;
9709         tree back;
9710
9711         if (ffebld_trail (b) == NULL)
9712           t = NULL_TREE;
9713         else
9714           {
9715             t = convert (ffecom_f2c_ftnlen_type_node,
9716                          ffecom_expr (ffebld_head (e)));
9717
9718             if (list == NULL_TREE)
9719               list = item = build_tree_list (NULL_TREE, t);
9720             else
9721               {
9722                 TREE_CHAIN (item) = build_tree_list (NULL_TREE, t);
9723                 item = TREE_CHAIN (item);
9724               }
9725           }
9726
9727         if (ffebld_left (ffebld_head (b)) == NULL)
9728           low = ffecom_integer_one_node;
9729         else
9730           low = ffecom_expr (ffebld_left (ffebld_head (b)));
9731         low = convert (ffecom_f2c_ftnlen_type_node, low);
9732
9733         back = build_tree_list (low, t);
9734         TREE_CHAIN (back) = backlist;
9735         backlist = back;
9736       }
9737
9738     for (item = backlist; item != NULL_TREE; item = TREE_CHAIN (item))
9739       {
9740         if (TREE_VALUE (item) == NULL_TREE)
9741           baseoff = TREE_PURPOSE (item);
9742         else
9743           baseoff = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
9744                               TREE_PURPOSE (item),
9745                               ffecom_2 (MULT_EXPR,
9746                                         ffecom_f2c_ftnlen_type_node,
9747                                         TREE_VALUE (item),
9748                                         baseoff));
9749       }
9750
9751     /* backlist now dead, along with all TREE_PURPOSEs on it.  */
9752
9753     baseoff = build_tree_list (NULL_TREE, baseoff);
9754     TREE_CHAIN (baseoff) = list;
9755
9756     numelem = build_tree_list (NULL_TREE, numelem);
9757     TREE_CHAIN (numelem) = baseoff;
9758
9759     numdim = build_tree_list (NULL_TREE, numdim);
9760     TREE_CHAIN (numdim) = numelem;
9761
9762     yes = suspend_momentary ();
9763
9764     item = build_array_type (ffecom_f2c_ftnlen_type_node,
9765                              build_range_type (integer_type_node,
9766                                                integer_zero_node,
9767                                                build_int_2
9768                                                ((int) ffesymbol_rank (s)
9769                                                 + 2, 0)));
9770     list = build (CONSTRUCTOR, item, NULL_TREE, numdim);
9771     TREE_CONSTANT (list) = 1;
9772     TREE_STATIC (list) = 1;
9773
9774     var = ffecom_get_invented_identifier ("__g77_dims_%d", mynumber++);
9775     var = build_decl (VAR_DECL, var, item);
9776     TREE_STATIC (var) = 1;
9777     DECL_INITIAL (var) = error_mark_node;
9778     var = start_decl (var, FALSE);
9779     finish_decl (var, list, FALSE);
9780
9781     var = ffecom_1 (ADDR_EXPR, build_pointer_type (item), var);
9782
9783     resume_momentary (yes);
9784
9785     return var;
9786   }
9787 }
9788
9789 #endif
9790 /* Essentially does a "fold (build1 (code, type, node))" while checking
9791    for certain housekeeping things.
9792
9793    NOTE: for building an ADDR_EXPR around a FUNCTION_DECL, use
9794    ffecom_1_fn instead.  */
9795
9796 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9797 tree
9798 ffecom_1 (enum tree_code code, tree type, tree node)
9799 {
9800   tree item;
9801
9802   if ((node == error_mark_node)
9803       || (type == error_mark_node))
9804     return error_mark_node;
9805
9806   if (code == ADDR_EXPR)
9807     {
9808       if (!mark_addressable (node))
9809         assert ("can't mark_addressable this node!" == NULL);
9810     }
9811
9812   switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9813     {
9814       tree realtype;
9815
9816     case REALPART_EXPR:
9817       item = build (COMPONENT_REF, type, node, TYPE_FIELDS (TREE_TYPE (node)));
9818       break;
9819
9820     case IMAGPART_EXPR:
9821       item = build (COMPONENT_REF, type, node, TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (node))));
9822       break;
9823
9824
9825     case NEGATE_EXPR:
9826       if (TREE_CODE (type) != RECORD_TYPE)
9827         {
9828           item = build1 (code, type, node);
9829           break;
9830         }
9831       node = ffecom_stabilize_aggregate_ (node);
9832       realtype = TREE_TYPE (TYPE_FIELDS (type));
9833       item =
9834         ffecom_2 (COMPLEX_EXPR, type,
9835                   ffecom_1 (NEGATE_EXPR, realtype,
9836                             ffecom_1 (REALPART_EXPR, realtype,
9837                                       node)),
9838                   ffecom_1 (NEGATE_EXPR, realtype,
9839                             ffecom_1 (IMAGPART_EXPR, realtype,
9840                                       node)));
9841       break;
9842
9843     default:
9844       item = build1 (code, type, node);
9845       break;
9846     }
9847
9848   if (TREE_SIDE_EFFECTS (node))
9849     TREE_SIDE_EFFECTS (item) = 1;
9850   if ((code == ADDR_EXPR) && staticp (node))
9851     TREE_CONSTANT (item) = 1;
9852   return fold (item);
9853 }
9854 #endif
9855
9856 /* Like ffecom_1 (ADDR_EXPR, TREE_TYPE (node), node), except
9857    handles TREE_CODE (node) == FUNCTION_DECL.  In particular,
9858    does not set TREE_ADDRESSABLE (because calling an inline
9859    function does not mean the function needs to be separately
9860    compiled).  */
9861
9862 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9863 tree
9864 ffecom_1_fn (tree node)
9865 {
9866   tree item;
9867   tree type;
9868
9869   if (node == error_mark_node)
9870     return error_mark_node;
9871
9872   type = build_type_variant (TREE_TYPE (node),
9873                              TREE_READONLY (node),
9874                              TREE_THIS_VOLATILE (node));
9875   item = build1 (ADDR_EXPR,
9876                  build_pointer_type (type), node);
9877   if (TREE_SIDE_EFFECTS (node))
9878     TREE_SIDE_EFFECTS (item) = 1;
9879   if (staticp (node))
9880     TREE_CONSTANT (item) = 1;
9881   return fold (item);
9882 }
9883 #endif
9884
9885 /* Essentially does a "fold (build (code, type, node1, node2))" while
9886    checking for certain housekeeping things.  */
9887
9888 #if FFECOM_targetCURRENT == FFECOM_targetGCC
9889 tree
9890 ffecom_2 (enum tree_code code, tree type, tree node1,
9891           tree node2)
9892 {
9893   tree item;
9894
9895   if ((node1 == error_mark_node)
9896       || (node2 == error_mark_node)
9897       || (type == error_mark_node))
9898     return error_mark_node;
9899
9900   switch (ffe_is_emulate_complex () ? code : NOP_EXPR)
9901     {
9902       tree a, b, c, d, realtype;
9903
9904     case CONJ_EXPR:
9905       assert ("no CONJ_EXPR support yet" == NULL);
9906       return error_mark_node;
9907
9908     case COMPLEX_EXPR:
9909       item = build_tree_list (TYPE_FIELDS (type), node1);
9910       TREE_CHAIN (item) = build_tree_list (TREE_CHAIN (TYPE_FIELDS (type)), node2);
9911       item = build (CONSTRUCTOR, type, NULL_TREE, item);
9912       break;
9913
9914     case PLUS_EXPR:
9915       if (TREE_CODE (type) != RECORD_TYPE)
9916         {
9917           item = build (code, type, node1, node2);
9918           break;
9919         }
9920       node1 = ffecom_stabilize_aggregate_ (node1);
9921       node2 = ffecom_stabilize_aggregate_ (node2);
9922       realtype = TREE_TYPE (TYPE_FIELDS (type));
9923       item =
9924         ffecom_2 (COMPLEX_EXPR, type,
9925                   ffecom_2 (PLUS_EXPR, realtype,
9926                             ffecom_1 (REALPART_EXPR, realtype,
9927                                       node1),
9928                             ffecom_1 (REALPART_EXPR, realtype,
9929                                       node2)),
9930                   ffecom_2 (PLUS_EXPR, realtype,
9931                             ffecom_1 (IMAGPART_EXPR, realtype,
9932                                       node1),
9933                             ffecom_1 (IMAGPART_EXPR, realtype,
9934                                       node2)));
9935       break;
9936
9937     case MINUS_EXPR:
9938       if (TREE_CODE (type) != RECORD_TYPE)
9939         {
9940           item = build (code, type, node1, node2);
9941           break;
9942         }
9943       node1 = ffecom_stabilize_aggregate_ (node1);
9944       node2 = ffecom_stabilize_aggregate_ (node2);
9945       realtype = TREE_TYPE (TYPE_FIELDS (type));
9946       item =
9947         ffecom_2 (COMPLEX_EXPR, type,
9948                   ffecom_2 (MINUS_EXPR, realtype,
9949                             ffecom_1 (REALPART_EXPR, realtype,
9950                                       node1),
9951                             ffecom_1 (REALPART_EXPR, realtype,
9952                                       node2)),
9953                   ffecom_2 (MINUS_EXPR, realtype,
9954                             ffecom_1 (IMAGPART_EXPR, realtype,
9955                                       node1),
9956                             ffecom_1 (IMAGPART_EXPR, realtype,
9957                                       node2)));
9958       break;
9959
9960     case MULT_EXPR:
9961       if (TREE_CODE (type) != RECORD_TYPE)
9962         {
9963           item = build (code, type, node1, node2);
9964           break;
9965         }
9966       node1 = ffecom_stabilize_aggregate_ (node1);
9967       node2 = ffecom_stabilize_aggregate_ (node2);
9968       realtype = TREE_TYPE (TYPE_FIELDS (type));
9969       a = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9970                                node1));
9971       b = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9972                                node1));
9973       c = save_expr (ffecom_1 (REALPART_EXPR, realtype,
9974                                node2));
9975       d = save_expr (ffecom_1 (IMAGPART_EXPR, realtype,
9976                                node2));
9977       item =
9978         ffecom_2 (COMPLEX_EXPR, type,
9979                   ffecom_2 (MINUS_EXPR, realtype,
9980                             ffecom_2 (MULT_EXPR, realtype,
9981                                       a,
9982                                       c),
9983                             ffecom_2 (MULT_EXPR, realtype,
9984                                       b,
9985                                       d)),
9986                   ffecom_2 (PLUS_EXPR, realtype,
9987                             ffecom_2 (MULT_EXPR, realtype,
9988                                       a,
9989                                       d),
9990                             ffecom_2 (MULT_EXPR, realtype,
9991                                       c,
9992                                       b)));
9993       break;
9994
9995     case EQ_EXPR:
9996       if ((TREE_CODE (node1) != RECORD_TYPE)
9997           && (TREE_CODE (node2) != RECORD_TYPE))
9998         {
9999           item = build (code, type, node1, node2);
10000           break;
10001         }
10002       assert (TREE_CODE (node1) == RECORD_TYPE);
10003       assert (TREE_CODE (node2) == RECORD_TYPE);
10004       node1 = ffecom_stabilize_aggregate_ (node1);
10005       node2 = ffecom_stabilize_aggregate_ (node2);
10006       realtype = TREE_TYPE (TYPE_FIELDS (type));
10007       item =
10008         ffecom_2 (TRUTH_ANDIF_EXPR, type,
10009                   ffecom_2 (code, type,
10010                             ffecom_1 (REALPART_EXPR, realtype,
10011                                       node1),
10012                             ffecom_1 (REALPART_EXPR, realtype,
10013                                       node2)),
10014                   ffecom_2 (code, type,
10015                             ffecom_1 (IMAGPART_EXPR, realtype,
10016                                       node1),
10017                             ffecom_1 (IMAGPART_EXPR, realtype,
10018                                       node2)));
10019       break;
10020
10021     case NE_EXPR:
10022       if ((TREE_CODE (node1) != RECORD_TYPE)
10023           && (TREE_CODE (node2) != RECORD_TYPE))
10024         {
10025           item = build (code, type, node1, node2);
10026           break;
10027         }
10028       assert (TREE_CODE (node1) == RECORD_TYPE);
10029       assert (TREE_CODE (node2) == RECORD_TYPE);
10030       node1 = ffecom_stabilize_aggregate_ (node1);
10031       node2 = ffecom_stabilize_aggregate_ (node2);
10032       realtype = TREE_TYPE (TYPE_FIELDS (type));
10033       item =
10034         ffecom_2 (TRUTH_ORIF_EXPR, type,
10035                   ffecom_2 (code, type,
10036                             ffecom_1 (REALPART_EXPR, realtype,
10037                                       node1),
10038                             ffecom_1 (REALPART_EXPR, realtype,
10039                                       node2)),
10040                   ffecom_2 (code, type,
10041                             ffecom_1 (IMAGPART_EXPR, realtype,
10042                                       node1),
10043                             ffecom_1 (IMAGPART_EXPR, realtype,
10044                                       node2)));
10045       break;
10046
10047     default:
10048       item = build (code, type, node1, node2);
10049       break;
10050     }
10051
10052   if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2))
10053     TREE_SIDE_EFFECTS (item) = 1;
10054   return fold (item);
10055 }
10056
10057 #endif
10058 /* ffecom_2pass_advise_entrypoint -- Advise that there's this entrypoint
10059
10060    ffesymbol s;  // the ENTRY point itself
10061    if (ffecom_2pass_advise_entrypoint(s))
10062        // the ENTRY point has been accepted
10063
10064    Does whatever compiler needs to do when it learns about the entrypoint,
10065    like determine the return type of the master function, count the
10066    number of entrypoints, etc.  Returns FALSE if the return type is
10067    not compatible with the return type(s) of other entrypoint(s).
10068
10069    NOTE: for every call to this fn that returns TRUE, _do_entrypoint must
10070    later (after _finish_progunit) be called with the same entrypoint(s)
10071    as passed to this fn for which TRUE was returned.
10072
10073    03-Jan-92  JCB  2.0
10074       Return FALSE if the return type conflicts with previous entrypoints.  */
10075
10076 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10077 bool
10078 ffecom_2pass_advise_entrypoint (ffesymbol entry)
10079 {
10080   ffebld list;                  /* opITEM. */
10081   ffebld mlist;                 /* opITEM. */
10082   ffebld plist;                 /* opITEM. */
10083   ffebld arg;                   /* ffebld_head(opITEM). */
10084   ffebld item;                  /* opITEM. */
10085   ffesymbol s;                  /* ffebld_symter(arg). */
10086   ffeinfoBasictype bt = ffesymbol_basictype (entry);
10087   ffeinfoKindtype kt = ffesymbol_kindtype (entry);
10088   ffetargetCharacterSize size = ffesymbol_size (entry);
10089   bool ok;
10090
10091   if (ffecom_num_entrypoints_ == 0)
10092     {                           /* First entrypoint, make list of main
10093                                    arglist's dummies. */
10094       assert (ffecom_primary_entry_ != NULL);
10095
10096       ffecom_master_bt_ = ffesymbol_basictype (ffecom_primary_entry_);
10097       ffecom_master_kt_ = ffesymbol_kindtype (ffecom_primary_entry_);
10098       ffecom_master_size_ = ffesymbol_size (ffecom_primary_entry_);
10099
10100       for (plist = NULL, list = ffesymbol_dummyargs (ffecom_primary_entry_);
10101            list != NULL;
10102            list = ffebld_trail (list))
10103         {
10104           arg = ffebld_head (list);
10105           if (ffebld_op (arg) != FFEBLD_opSYMTER)
10106             continue;           /* Alternate return or some such thing. */
10107           item = ffebld_new_item (arg, NULL);
10108           if (plist == NULL)
10109             ffecom_master_arglist_ = item;
10110           else
10111             ffebld_set_trail (plist, item);
10112           plist = item;
10113         }
10114     }
10115
10116   /* If necessary, scan entry arglist for alternate returns.  Do this scan
10117      apparently redundantly (it's done below to UNIONize the arglists) so
10118      that we don't complain about RETURN 1 if an offending ENTRY is the only
10119      one with an alternate return.  */
10120
10121   if (!ffecom_is_altreturning_)
10122     {
10123       for (list = ffesymbol_dummyargs (entry);
10124            list != NULL;
10125            list = ffebld_trail (list))
10126         {
10127           arg = ffebld_head (list);
10128           if (ffebld_op (arg) == FFEBLD_opSTAR)
10129             {
10130               ffecom_is_altreturning_ = TRUE;
10131               break;
10132             }
10133         }
10134     }
10135
10136   /* Now check type compatibility. */
10137
10138   switch (ffecom_master_bt_)
10139     {
10140     case FFEINFO_basictypeNONE:
10141       ok = (bt != FFEINFO_basictypeCHARACTER);
10142       break;
10143
10144     case FFEINFO_basictypeCHARACTER:
10145       ok
10146         = (bt == FFEINFO_basictypeCHARACTER)
10147         && (kt == ffecom_master_kt_)
10148         && (size == ffecom_master_size_);
10149       break;
10150
10151     case FFEINFO_basictypeANY:
10152       return FALSE;             /* Just don't bother. */
10153
10154     default:
10155       if (bt == FFEINFO_basictypeCHARACTER)
10156         {
10157           ok = FALSE;
10158           break;
10159         }
10160       ok = TRUE;
10161       if ((bt != ffecom_master_bt_) || (kt != ffecom_master_kt_))
10162         {
10163           ffecom_master_bt_ = FFEINFO_basictypeNONE;
10164           ffecom_master_kt_ = FFEINFO_kindtypeNONE;
10165         }
10166       break;
10167     }
10168
10169   if (!ok)
10170     {
10171       ffebad_start (FFEBAD_ENTRY_CONFLICTS);
10172       ffest_ffebad_here_current_stmt (0);
10173       ffebad_finish ();
10174       return FALSE;             /* Can't handle entrypoint. */
10175     }
10176
10177   /* Entrypoint type compatible with previous types. */
10178
10179   ++ffecom_num_entrypoints_;
10180
10181   /* Master-arg-list = UNION(Master-arg-list,entry-arg-list). */
10182
10183   for (list = ffesymbol_dummyargs (entry);
10184        list != NULL;
10185        list = ffebld_trail (list))
10186     {
10187       arg = ffebld_head (list);
10188       if (ffebld_op (arg) != FFEBLD_opSYMTER)
10189         continue;               /* Alternate return or some such thing. */
10190       s = ffebld_symter (arg);
10191       for (plist = NULL, mlist = ffecom_master_arglist_;
10192            mlist != NULL;
10193            plist = mlist, mlist = ffebld_trail (mlist))
10194         {                       /* plist points to previous item for easy
10195                                    appending of arg. */
10196           if (ffebld_symter (ffebld_head (mlist)) == s)
10197             break;              /* Already have this arg in the master list. */
10198         }
10199       if (mlist != NULL)
10200         continue;               /* Already have this arg in the master list. */
10201
10202       /* Append this arg to the master list. */
10203
10204       item = ffebld_new_item (arg, NULL);
10205       if (plist == NULL)
10206         ffecom_master_arglist_ = item;
10207       else
10208         ffebld_set_trail (plist, item);
10209     }
10210
10211   return TRUE;
10212 }
10213
10214 #endif
10215 /* ffecom_2pass_do_entrypoint -- Do compilation of entrypoint
10216
10217    ffesymbol s;  // the ENTRY point itself
10218    ffecom_2pass_do_entrypoint(s);
10219
10220    Does whatever compiler needs to do to make the entrypoint actually
10221    happen.  Must be called for each entrypoint after
10222    ffecom_finish_progunit is called.  */
10223
10224 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10225 void
10226 ffecom_2pass_do_entrypoint (ffesymbol entry)
10227 {
10228   static int mfn_num = 0;
10229   static int ent_num;
10230
10231   if (mfn_num != ffecom_num_fns_)
10232     {                           /* First entrypoint for this program unit. */
10233       ent_num = 1;
10234       mfn_num = ffecom_num_fns_;
10235       ffecom_do_entry_ (ffecom_primary_entry_, 0);
10236     }
10237   else
10238     ++ent_num;
10239
10240   --ffecom_num_entrypoints_;
10241
10242   ffecom_do_entry_ (entry, ent_num);
10243 }
10244
10245 #endif
10246
10247 /* Essentially does a "fold (build (code, type, node1, node2))" while
10248    checking for certain housekeeping things.  Always sets
10249    TREE_SIDE_EFFECTS.  */
10250
10251 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10252 tree
10253 ffecom_2s (enum tree_code code, tree type, tree node1,
10254            tree node2)
10255 {
10256   tree item;
10257
10258   if ((node1 == error_mark_node)
10259       || (node2 == error_mark_node)
10260       || (type == error_mark_node))
10261     return error_mark_node;
10262
10263   item = build (code, type, node1, node2);
10264   TREE_SIDE_EFFECTS (item) = 1;
10265   return fold (item);
10266 }
10267
10268 #endif
10269 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10270    checking for certain housekeeping things.  */
10271
10272 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10273 tree
10274 ffecom_3 (enum tree_code code, tree type, tree node1,
10275           tree node2, tree node3)
10276 {
10277   tree item;
10278
10279   if ((node1 == error_mark_node)
10280       || (node2 == error_mark_node)
10281       || (node3 == error_mark_node)
10282       || (type == error_mark_node))
10283     return error_mark_node;
10284
10285   item = build (code, type, node1, node2, node3);
10286   if (TREE_SIDE_EFFECTS (node1) || TREE_SIDE_EFFECTS (node2)
10287       || (node3 != NULL_TREE && TREE_SIDE_EFFECTS (node3)))
10288     TREE_SIDE_EFFECTS (item) = 1;
10289   return fold (item);
10290 }
10291
10292 #endif
10293 /* Essentially does a "fold (build (code, type, node1, node2, node3))" while
10294    checking for certain housekeeping things.  Always sets
10295    TREE_SIDE_EFFECTS.  */
10296
10297 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10298 tree
10299 ffecom_3s (enum tree_code code, tree type, tree node1,
10300            tree node2, tree node3)
10301 {
10302   tree item;
10303
10304   if ((node1 == error_mark_node)
10305       || (node2 == error_mark_node)
10306       || (node3 == error_mark_node)
10307       || (type == error_mark_node))
10308     return error_mark_node;
10309
10310   item = build (code, type, node1, node2, node3);
10311   TREE_SIDE_EFFECTS (item) = 1;
10312   return fold (item);
10313 }
10314
10315 #endif
10316
10317 /* ffecom_arg_expr -- Transform argument expr into gcc tree
10318
10319    See use by ffecom_list_expr.
10320
10321    If expression is NULL, returns an integer zero tree.  If it is not
10322    a CHARACTER expression, returns whatever ffecom_expr
10323    returns and sets the length return value to NULL_TREE.  Otherwise
10324    generates code to evaluate the character expression, returns the proper
10325    pointer to the result, but does NOT set the length return value to a tree
10326    that specifies the length of the result.  (In other words, the length
10327    variable is always set to NULL_TREE, because a length is never passed.)
10328
10329    21-Dec-91  JCB  1.1
10330       Don't set returned length, since nobody needs it (yet; someday if
10331       we allow CHARACTER*(*) dummies to statement functions, we'll need
10332       it).  */
10333
10334 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10335 tree
10336 ffecom_arg_expr (ffebld expr, tree *length)
10337 {
10338   tree ign;
10339
10340   *length = NULL_TREE;
10341
10342   if (expr == NULL)
10343     return integer_zero_node;
10344
10345   if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10346     return ffecom_expr (expr);
10347
10348   return ffecom_arg_ptr_to_expr (expr, &ign);
10349 }
10350
10351 #endif
10352 /* Transform expression into constant argument-pointer-to-expression tree.
10353
10354    If the expression can be transformed into a argument-pointer-to-expression
10355    tree that is constant, that is done, and the tree returned.  Else
10356    NULL_TREE is returned.
10357
10358    That way, a caller can attempt to provide compile-time initialization
10359    of a variable and, if that fails, *then* choose to start a new block
10360    and resort to using temporaries, as appropriate.  */
10361
10362 tree
10363 ffecom_arg_ptr_to_const_expr (ffebld expr, tree *length)
10364 {
10365   if (! expr)
10366     return integer_zero_node;
10367
10368   if (ffebld_op (expr) == FFEBLD_opANY)
10369     {
10370       if (length)
10371         *length = error_mark_node;
10372       return error_mark_node;
10373     }
10374
10375   if (ffebld_arity (expr) == 0
10376       && (ffebld_op (expr) != FFEBLD_opSYMTER
10377           || ffebld_where (expr) == FFEINFO_whereCOMMON
10378           || ffebld_where (expr) == FFEINFO_whereGLOBAL
10379           || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10380     {
10381       tree t;
10382
10383       t = ffecom_arg_ptr_to_expr (expr, length);
10384       assert (TREE_CONSTANT (t));
10385       assert (! length || TREE_CONSTANT (*length));
10386       return t;
10387     }
10388
10389   if (length
10390       && ffebld_size (expr) != FFETARGET_charactersizeNONE)
10391     *length = build_int_2 (ffebld_size (expr), 0);
10392   else if (length)
10393     *length = NULL_TREE;
10394   return NULL_TREE;
10395 }
10396
10397 /* ffecom_arg_ptr_to_expr -- Transform argument expr into gcc tree
10398
10399    See use by ffecom_list_ptr_to_expr.
10400
10401    If expression is NULL, returns an integer zero tree.  If it is not
10402    a CHARACTER expression, returns whatever ffecom_ptr_to_expr
10403    returns and sets the length return value to NULL_TREE.  Otherwise
10404    generates code to evaluate the character expression, returns the proper
10405    pointer to the result, AND sets the length return value to a tree that
10406    specifies the length of the result.
10407
10408    If the length argument is NULL, this is a slightly special
10409    case of building a FORMAT expression, that is, an expression that
10410    will be used at run time without regard to length.  For the current
10411    implementation, which uses the libf2c library, this means it is nice
10412    to append a null byte to the end of the expression, where feasible,
10413    to make sure any diagnostic about the FORMAT string terminates at
10414    some useful point.
10415
10416    For now, treat %REF(char-expr) as the same as char-expr with a NULL
10417    length argument.  This might even be seen as a feature, if a null
10418    byte can always be appended.  */
10419
10420 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10421 tree
10422 ffecom_arg_ptr_to_expr (ffebld expr, tree *length)
10423 {
10424   tree item;
10425   tree ign_length;
10426   ffecomConcatList_ catlist;
10427
10428   if (length != NULL)
10429     *length = NULL_TREE;
10430
10431   if (expr == NULL)
10432     return integer_zero_node;
10433
10434   switch (ffebld_op (expr))
10435     {
10436     case FFEBLD_opPERCENT_VAL:
10437       if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10438         return ffecom_expr (ffebld_left (expr));
10439       {
10440         tree temp_exp;
10441         tree temp_length;
10442
10443         temp_exp = ffecom_arg_ptr_to_expr (ffebld_left (expr), &temp_length);
10444         if (temp_exp == error_mark_node)
10445           return error_mark_node;
10446
10447         return ffecom_1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (temp_exp)),
10448                          temp_exp);
10449       }
10450
10451     case FFEBLD_opPERCENT_REF:
10452       if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10453         return ffecom_ptr_to_expr (ffebld_left (expr));
10454       if (length != NULL)
10455         {
10456           ign_length = NULL_TREE;
10457           length = &ign_length;
10458         }
10459       expr = ffebld_left (expr);
10460       break;
10461
10462     case FFEBLD_opPERCENT_DESCR:
10463       switch (ffeinfo_basictype (ffebld_info (expr)))
10464         {
10465 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10466         case FFEINFO_basictypeHOLLERITH:
10467 #endif
10468         case FFEINFO_basictypeCHARACTER:
10469           break;                /* Passed by descriptor anyway. */
10470
10471         default:
10472           item = ffecom_ptr_to_expr (expr);
10473           if (item != error_mark_node)
10474             *length = TYPE_SIZE (TREE_TYPE (TREE_TYPE (item)));
10475           break;
10476         }
10477       break;
10478
10479     default:
10480       break;
10481     }
10482
10483 #ifdef PASS_HOLLERITH_BY_DESCRIPTOR
10484   if ((ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeHOLLERITH)
10485       && (length != NULL))
10486     {                           /* Pass Hollerith by descriptor. */
10487       ffetargetHollerith h;
10488
10489       assert (ffebld_op (expr) == FFEBLD_opCONTER);
10490       h = ffebld_cu_val_hollerith (ffebld_constant_union
10491                                    (ffebld_conter (expr)));
10492       *length
10493         = build_int_2 (h.length, 0);
10494       TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10495     }
10496 #endif
10497
10498   if (ffeinfo_basictype (ffebld_info (expr)) != FFEINFO_basictypeCHARACTER)
10499     return ffecom_ptr_to_expr (expr);
10500
10501   assert (ffeinfo_kindtype (ffebld_info (expr))
10502           == FFEINFO_kindtypeCHARACTER1);
10503
10504   while (ffebld_op (expr) == FFEBLD_opPAREN)
10505     expr = ffebld_left (expr);
10506
10507   catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
10508   switch (ffecom_concat_list_count_ (catlist))
10509     {
10510     case 0:                     /* Shouldn't happen, but in case it does... */
10511       if (length != NULL)
10512         {
10513           *length = ffecom_f2c_ftnlen_zero_node;
10514           TREE_TYPE (*length) = ffecom_f2c_ftnlen_type_node;
10515         }
10516       ffecom_concat_list_kill_ (catlist);
10517       return null_pointer_node;
10518
10519     case 1:                     /* The (fairly) easy case. */
10520       if (length == NULL)
10521         ffecom_char_args_with_null_ (&item, &ign_length,
10522                                      ffecom_concat_list_expr_ (catlist, 0));
10523       else
10524         ffecom_char_args_ (&item, length,
10525                            ffecom_concat_list_expr_ (catlist, 0));
10526       ffecom_concat_list_kill_ (catlist);
10527       assert (item != NULL_TREE);
10528       return item;
10529
10530     default:                    /* Must actually concatenate things. */
10531       break;
10532     }
10533
10534   {
10535     int count = ffecom_concat_list_count_ (catlist);
10536     int i;
10537     tree lengths;
10538     tree items;
10539     tree length_array;
10540     tree item_array;
10541     tree citem;
10542     tree clength;
10543     tree temporary;
10544     tree num;
10545     tree known_length;
10546     ffetargetCharacterSize sz;
10547
10548     sz = ffecom_concat_list_maxlen_ (catlist);
10549     /* ~~Kludge! */
10550     assert (sz != FFETARGET_charactersizeNONE);
10551
10552 #ifdef HOHO
10553     length_array
10554       = lengths
10555       = ffecom_push_tempvar (ffecom_f2c_ftnlen_type_node,
10556                              FFETARGET_charactersizeNONE, count, TRUE);
10557     item_array
10558       = items
10559       = ffecom_push_tempvar (ffecom_f2c_address_type_node,
10560                              FFETARGET_charactersizeNONE, count, TRUE);
10561     temporary = ffecom_push_tempvar (char_type_node,
10562                                      sz, -1, TRUE);
10563 #else
10564     {
10565       tree hook;
10566
10567       hook = ffebld_nonter_hook (expr);
10568       assert (hook);
10569       assert (TREE_CODE (hook) == TREE_VEC);
10570       assert (TREE_VEC_LENGTH (hook) == 3);
10571       length_array = lengths = TREE_VEC_ELT (hook, 0);
10572       item_array = items = TREE_VEC_ELT (hook, 1);
10573       temporary = TREE_VEC_ELT (hook, 2);
10574     }
10575 #endif
10576
10577     known_length = ffecom_f2c_ftnlen_zero_node;
10578
10579     for (i = 0; i < count; ++i)
10580       {
10581         if ((i == count)
10582             && (length == NULL))
10583           ffecom_char_args_with_null_ (&citem, &clength,
10584                                        ffecom_concat_list_expr_ (catlist, i));
10585         else
10586           ffecom_char_args_ (&citem, &clength,
10587                              ffecom_concat_list_expr_ (catlist, i));
10588         if ((citem == error_mark_node)
10589             || (clength == error_mark_node))
10590           {
10591             ffecom_concat_list_kill_ (catlist);
10592             *length = error_mark_node;
10593             return error_mark_node;
10594           }
10595
10596         items
10597           = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (items),
10598                       ffecom_modify (void_type_node,
10599                                      ffecom_2 (ARRAY_REF,
10600                      TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (item_array))),
10601                                                item_array,
10602                                                build_int_2 (i, 0)),
10603                                      citem),
10604                       items);
10605         clength = ffecom_save_tree (clength);
10606         if (length != NULL)
10607           known_length
10608             = ffecom_2 (PLUS_EXPR, ffecom_f2c_ftnlen_type_node,
10609                         known_length,
10610                         clength);
10611         lengths
10612           = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (lengths),
10613                       ffecom_modify (void_type_node,
10614                                      ffecom_2 (ARRAY_REF,
10615                    TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (length_array))),
10616                                                length_array,
10617                                                build_int_2 (i, 0)),
10618                                      clength),
10619                       lengths);
10620       }
10621
10622     temporary = ffecom_1 (ADDR_EXPR,
10623                           build_pointer_type (TREE_TYPE (temporary)),
10624                           temporary);
10625
10626     item = build_tree_list (NULL_TREE, temporary);
10627     TREE_CHAIN (item)
10628       = build_tree_list (NULL_TREE,
10629                          ffecom_1 (ADDR_EXPR,
10630                                    build_pointer_type (TREE_TYPE (items)),
10631                                    items));
10632     TREE_CHAIN (TREE_CHAIN (item))
10633       = build_tree_list (NULL_TREE,
10634                          ffecom_1 (ADDR_EXPR,
10635                                    build_pointer_type (TREE_TYPE (lengths)),
10636                                    lengths));
10637     TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item)))
10638       = build_tree_list
10639         (NULL_TREE,
10640          ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
10641                    convert (ffecom_f2c_ftnlen_type_node,
10642                             build_int_2 (count, 0))));
10643     num = build_int_2 (sz, 0);
10644     TREE_TYPE (num) = ffecom_f2c_ftnlen_type_node;
10645     TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (item))))
10646       = build_tree_list (NULL_TREE, num);
10647
10648     item = ffecom_call_gfrt (FFECOM_gfrtCAT, item, NULL_TREE);
10649     TREE_SIDE_EFFECTS (item) = 1;
10650     item = ffecom_2 (COMPOUND_EXPR, TREE_TYPE (temporary),
10651                      item,
10652                      temporary);
10653
10654     if (length != NULL)
10655       *length = known_length;
10656   }
10657
10658   ffecom_concat_list_kill_ (catlist);
10659   assert (item != NULL_TREE);
10660   return item;
10661 }
10662
10663 #endif
10664 /* Generate call to run-time function.
10665
10666    The first arg is the GNU Fortran Run-Time function index, the second
10667    arg is the list of arguments to pass to it.  Returned is the expression
10668    (WITHOUT TREE_SIDE_EFFECTS set!) that makes the call and returns the
10669    result (which may be void).  */
10670
10671 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10672 tree
10673 ffecom_call_gfrt (ffecomGfrt ix, tree args, tree hook)
10674 {
10675   return ffecom_call_ (ffecom_gfrt_tree_ (ix),
10676                        ffecom_gfrt_kindtype (ix),
10677                        ffe_is_f2c_library () && ffecom_gfrt_complex_[ix],
10678                        NULL_TREE, args, NULL_TREE, NULL,
10679                        NULL, NULL_TREE, TRUE, hook);
10680 }
10681 #endif
10682
10683 /* Transform constant-union to tree.  */
10684
10685 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10686 tree
10687 ffecom_constantunion (ffebldConstantUnion *cu, ffeinfoBasictype bt,
10688                       ffeinfoKindtype kt, tree tree_type)
10689 {
10690   tree item;
10691
10692   switch (bt)
10693     {
10694     case FFEINFO_basictypeINTEGER:
10695       {
10696         int val;
10697
10698         switch (kt)
10699           {
10700 #if FFETARGET_okINTEGER1
10701           case FFEINFO_kindtypeINTEGER1:
10702             val = ffebld_cu_val_integer1 (*cu);
10703             break;
10704 #endif
10705
10706 #if FFETARGET_okINTEGER2
10707           case FFEINFO_kindtypeINTEGER2:
10708             val = ffebld_cu_val_integer2 (*cu);
10709             break;
10710 #endif
10711
10712 #if FFETARGET_okINTEGER3
10713           case FFEINFO_kindtypeINTEGER3:
10714             val = ffebld_cu_val_integer3 (*cu);
10715             break;
10716 #endif
10717
10718 #if FFETARGET_okINTEGER4
10719           case FFEINFO_kindtypeINTEGER4:
10720             val = ffebld_cu_val_integer4 (*cu);
10721             break;
10722 #endif
10723
10724           default:
10725             assert ("bad INTEGER constant kind type" == NULL);
10726             /* Fall through. */
10727           case FFEINFO_kindtypeANY:
10728             return error_mark_node;
10729           }
10730         item = build_int_2 (val, (val < 0) ? -1 : 0);
10731         TREE_TYPE (item) = tree_type;
10732       }
10733       break;
10734
10735     case FFEINFO_basictypeLOGICAL:
10736       {
10737         int val;
10738
10739         switch (kt)
10740           {
10741 #if FFETARGET_okLOGICAL1
10742           case FFEINFO_kindtypeLOGICAL1:
10743             val = ffebld_cu_val_logical1 (*cu);
10744             break;
10745 #endif
10746
10747 #if FFETARGET_okLOGICAL2
10748           case FFEINFO_kindtypeLOGICAL2:
10749             val = ffebld_cu_val_logical2 (*cu);
10750             break;
10751 #endif
10752
10753 #if FFETARGET_okLOGICAL3
10754           case FFEINFO_kindtypeLOGICAL3:
10755             val = ffebld_cu_val_logical3 (*cu);
10756             break;
10757 #endif
10758
10759 #if FFETARGET_okLOGICAL4
10760           case FFEINFO_kindtypeLOGICAL4:
10761             val = ffebld_cu_val_logical4 (*cu);
10762             break;
10763 #endif
10764
10765           default:
10766             assert ("bad LOGICAL constant kind type" == NULL);
10767             /* Fall through. */
10768           case FFEINFO_kindtypeANY:
10769             return error_mark_node;
10770           }
10771         item = build_int_2 (val, (val < 0) ? -1 : 0);
10772         TREE_TYPE (item) = tree_type;
10773       }
10774       break;
10775
10776     case FFEINFO_basictypeREAL:
10777       {
10778         REAL_VALUE_TYPE val;
10779
10780         switch (kt)
10781           {
10782 #if FFETARGET_okREAL1
10783           case FFEINFO_kindtypeREAL1:
10784             val = ffetarget_value_real1 (ffebld_cu_val_real1 (*cu));
10785             break;
10786 #endif
10787
10788 #if FFETARGET_okREAL2
10789           case FFEINFO_kindtypeREAL2:
10790             val = ffetarget_value_real2 (ffebld_cu_val_real2 (*cu));
10791             break;
10792 #endif
10793
10794 #if FFETARGET_okREAL3
10795           case FFEINFO_kindtypeREAL3:
10796             val = ffetarget_value_real3 (ffebld_cu_val_real3 (*cu));
10797             break;
10798 #endif
10799
10800 #if FFETARGET_okREAL4
10801           case FFEINFO_kindtypeREAL4:
10802             val = ffetarget_value_real4 (ffebld_cu_val_real4 (*cu));
10803             break;
10804 #endif
10805
10806           default:
10807             assert ("bad REAL constant kind type" == NULL);
10808             /* Fall through. */
10809           case FFEINFO_kindtypeANY:
10810             return error_mark_node;
10811           }
10812         item = build_real (tree_type, val);
10813       }
10814       break;
10815
10816     case FFEINFO_basictypeCOMPLEX:
10817       {
10818         REAL_VALUE_TYPE real;
10819         REAL_VALUE_TYPE imag;
10820         tree el_type = ffecom_tree_type[FFEINFO_basictypeREAL][kt];
10821
10822         switch (kt)
10823           {
10824 #if FFETARGET_okCOMPLEX1
10825           case FFEINFO_kindtypeREAL1:
10826             real = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).real);
10827             imag = ffetarget_value_real1 (ffebld_cu_val_complex1 (*cu).imaginary);
10828             break;
10829 #endif
10830
10831 #if FFETARGET_okCOMPLEX2
10832           case FFEINFO_kindtypeREAL2:
10833             real = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).real);
10834             imag = ffetarget_value_real2 (ffebld_cu_val_complex2 (*cu).imaginary);
10835             break;
10836 #endif
10837
10838 #if FFETARGET_okCOMPLEX3
10839           case FFEINFO_kindtypeREAL3:
10840             real = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).real);
10841             imag = ffetarget_value_real3 (ffebld_cu_val_complex3 (*cu).imaginary);
10842             break;
10843 #endif
10844
10845 #if FFETARGET_okCOMPLEX4
10846           case FFEINFO_kindtypeREAL4:
10847             real = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).real);
10848             imag = ffetarget_value_real4 (ffebld_cu_val_complex4 (*cu).imaginary);
10849             break;
10850 #endif
10851
10852           default:
10853             assert ("bad REAL constant kind type" == NULL);
10854             /* Fall through. */
10855           case FFEINFO_kindtypeANY:
10856             return error_mark_node;
10857           }
10858         item = ffecom_build_complex_constant_ (tree_type,
10859                                                build_real (el_type, real),
10860                                                build_real (el_type, imag));
10861       }
10862       break;
10863
10864     case FFEINFO_basictypeCHARACTER:
10865       {                         /* Happens only in DATA and similar contexts. */
10866         ffetargetCharacter1 val;
10867
10868         switch (kt)
10869           {
10870 #if FFETARGET_okCHARACTER1
10871           case FFEINFO_kindtypeLOGICAL1:
10872             val = ffebld_cu_val_character1 (*cu);
10873             break;
10874 #endif
10875
10876           default:
10877             assert ("bad CHARACTER constant kind type" == NULL);
10878             /* Fall through. */
10879           case FFEINFO_kindtypeANY:
10880             return error_mark_node;
10881           }
10882         item = build_string (ffetarget_length_character1 (val),
10883                              ffetarget_text_character1 (val));
10884         TREE_TYPE (item)
10885           = build_type_variant (build_array_type (char_type_node,
10886                                                   build_range_type
10887                                                   (integer_type_node,
10888                                                    integer_one_node,
10889                                                    build_int_2
10890                                                 (ffetarget_length_character1
10891                                                  (val), 0))),
10892                                 1, 0);
10893       }
10894       break;
10895
10896     case FFEINFO_basictypeHOLLERITH:
10897       {
10898         ffetargetHollerith h;
10899
10900         h = ffebld_cu_val_hollerith (*cu);
10901
10902         /* If not at least as wide as default INTEGER, widen it.  */
10903         if (h.length >= FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE)
10904           item = build_string (h.length, h.text);
10905         else
10906           {
10907             char str[FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE];
10908
10909             memcpy (str, h.text, h.length);
10910             memset (&str[h.length], ' ',
10911                     FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE
10912                     - h.length);
10913             item = build_string (FLOAT_TYPE_SIZE / CHAR_TYPE_SIZE,
10914                                  str);
10915           }
10916         TREE_TYPE (item)
10917           = build_type_variant (build_array_type (char_type_node,
10918                                                   build_range_type
10919                                                   (integer_type_node,
10920                                                    integer_one_node,
10921                                                    build_int_2
10922                                                    (h.length, 0))),
10923                                 1, 0);
10924       }
10925       break;
10926
10927     case FFEINFO_basictypeTYPELESS:
10928       {
10929         ffetargetInteger1 ival;
10930         ffetargetTypeless tless;
10931         ffebad error;
10932
10933         tless = ffebld_cu_val_typeless (*cu);
10934         error = ffetarget_convert_integer1_typeless (&ival, tless);
10935         assert (error == FFEBAD);
10936
10937         item = build_int_2 ((int) ival, 0);
10938       }
10939       break;
10940
10941     default:
10942       assert ("not yet on constant type" == NULL);
10943       /* Fall through. */
10944     case FFEINFO_basictypeANY:
10945       return error_mark_node;
10946     }
10947
10948   TREE_CONSTANT (item) = 1;
10949
10950   return item;
10951 }
10952
10953 #endif
10954
10955 /* Transform expression into constant tree.
10956
10957    If the expression can be transformed into a tree that is constant,
10958    that is done, and the tree returned.  Else NULL_TREE is returned.
10959
10960    That way, a caller can attempt to provide compile-time initialization
10961    of a variable and, if that fails, *then* choose to start a new block
10962    and resort to using temporaries, as appropriate.  */
10963
10964 tree
10965 ffecom_const_expr (ffebld expr)
10966 {
10967   if (! expr)
10968     return integer_zero_node;
10969
10970   if (ffebld_op (expr) == FFEBLD_opANY)
10971     return error_mark_node;
10972
10973   if (ffebld_arity (expr) == 0
10974       && (ffebld_op (expr) != FFEBLD_opSYMTER
10975 #if NEWCOMMON
10976           /* ~~Enable once common/equivalence is handled properly?  */
10977           || ffebld_where (expr) == FFEINFO_whereCOMMON
10978 #endif
10979           || ffebld_where (expr) == FFEINFO_whereGLOBAL
10980           || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
10981     {
10982       tree t;
10983
10984       t = ffecom_expr (expr);
10985       assert (TREE_CONSTANT (t));
10986       return t;
10987     }
10988
10989   return NULL_TREE;
10990 }
10991
10992 /* Handy way to make a field in a struct/union.  */
10993
10994 #if FFECOM_targetCURRENT == FFECOM_targetGCC
10995 tree
10996 ffecom_decl_field (tree context, tree prevfield,
10997                    const char *name, tree type)
10998 {
10999   tree field;
11000
11001   field = build_decl (FIELD_DECL, get_identifier (name), type);
11002   DECL_CONTEXT (field) = context;
11003   DECL_FRAME_SIZE (field) = 0;
11004   if (prevfield != NULL_TREE)
11005     TREE_CHAIN (prevfield) = field;
11006
11007   return field;
11008 }
11009
11010 #endif
11011
11012 void
11013 ffecom_close_include (FILE *f)
11014 {
11015 #if FFECOM_GCC_INCLUDE
11016   ffecom_close_include_ (f);
11017 #endif
11018 }
11019
11020 int
11021 ffecom_decode_include_option (char *spec)
11022 {
11023 #if FFECOM_GCC_INCLUDE
11024   return ffecom_decode_include_option_ (spec);
11025 #else
11026   return 1;
11027 #endif
11028 }
11029
11030 /* End a compound statement (block).  */
11031
11032 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11033 tree
11034 ffecom_end_compstmt (void)
11035 {
11036   return bison_rule_compstmt_ ();
11037 }
11038 #endif  /* FFECOM_targetCURRENT == FFECOM_targetGCC */
11039
11040 /* ffecom_end_transition -- Perform end transition on all symbols
11041
11042    ffecom_end_transition();
11043
11044    Calls ffecom_sym_end_transition for each global and local symbol.  */
11045
11046 void
11047 ffecom_end_transition ()
11048 {
11049 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11050   ffebld item;
11051 #endif
11052
11053   if (ffe_is_ffedebug ())
11054     fprintf (dmpout, "; end_stmt_transition\n");
11055
11056 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11057   ffecom_list_blockdata_ = NULL;
11058   ffecom_list_common_ = NULL;
11059 #endif
11060
11061   ffesymbol_drive (ffecom_sym_end_transition);
11062   if (ffe_is_ffedebug ())
11063     {
11064       ffestorag_report ();
11065 #if FFECOM_targetCURRENT == FFECOM_targetFFE
11066       ffesymbol_report_all ();
11067 #endif
11068     }
11069
11070 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11071   ffecom_start_progunit_ ();
11072
11073   for (item = ffecom_list_blockdata_;
11074        item != NULL;
11075        item = ffebld_trail (item))
11076     {
11077       ffebld callee;
11078       ffesymbol s;
11079       tree dt;
11080       tree t;
11081       tree var;
11082       int yes;
11083       static int number = 0;
11084
11085       callee = ffebld_head (item);
11086       s = ffebld_symter (callee);
11087       t = ffesymbol_hook (s).decl_tree;
11088       if (t == NULL_TREE)
11089         {
11090           s = ffecom_sym_transform_ (s);
11091           t = ffesymbol_hook (s).decl_tree;
11092         }
11093
11094       yes = suspend_momentary ();
11095
11096       dt = build_pointer_type (TREE_TYPE (t));
11097
11098       var = build_decl (VAR_DECL,
11099                         ffecom_get_invented_identifier ("__g77_forceload_%d",
11100                                                         number++),
11101                         dt);
11102       DECL_EXTERNAL (var) = 0;
11103       TREE_STATIC (var) = 1;
11104       TREE_PUBLIC (var) = 0;
11105       DECL_INITIAL (var) = error_mark_node;
11106       TREE_USED (var) = 1;
11107
11108       var = start_decl (var, FALSE);
11109
11110       t = ffecom_1 (ADDR_EXPR, dt, t);
11111
11112       finish_decl (var, t, FALSE);
11113
11114       resume_momentary (yes);
11115     }
11116
11117   /* This handles any COMMON areas that weren't referenced but have, for
11118      example, important initial data.  */
11119
11120   for (item = ffecom_list_common_;
11121        item != NULL;
11122        item = ffebld_trail (item))
11123     ffecom_transform_common_ (ffebld_symter (ffebld_head (item)));
11124
11125   ffecom_list_common_ = NULL;
11126 #endif
11127 }
11128
11129 /* ffecom_exec_transition -- Perform exec transition on all symbols
11130
11131    ffecom_exec_transition();
11132
11133    Calls ffecom_sym_exec_transition for each global and local symbol.
11134    Make sure error updating not inhibited.  */
11135
11136 void
11137 ffecom_exec_transition ()
11138 {
11139   bool inhibited;
11140
11141   if (ffe_is_ffedebug ())
11142     fprintf (dmpout, "; exec_stmt_transition\n");
11143
11144   inhibited = ffebad_inhibit ();
11145   ffebad_set_inhibit (FALSE);
11146
11147   ffesymbol_drive (ffecom_sym_exec_transition); /* Don't retract! */
11148   ffeequiv_exec_transition ();  /* Handle all pending EQUIVALENCEs. */
11149   if (ffe_is_ffedebug ())
11150     {
11151       ffestorag_report ();
11152 #if FFECOM_targetCURRENT == FFECOM_targetFFE
11153       ffesymbol_report_all ();
11154 #endif
11155     }
11156
11157   if (inhibited)
11158     ffebad_set_inhibit (TRUE);
11159 }
11160
11161 /* Handle assignment statement.
11162
11163    Convert dest and source using ffecom_expr, then join them
11164    with an ASSIGN op and pass the whole thing to expand_expr_stmt.  */
11165
11166 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11167 void
11168 ffecom_expand_let_stmt (ffebld dest, ffebld source)
11169 {
11170   tree dest_tree;
11171   tree dest_length;
11172   tree source_tree;
11173   tree expr_tree;
11174
11175   if (ffeinfo_basictype (ffebld_info (dest)) != FFEINFO_basictypeCHARACTER)
11176     {
11177       bool dest_used;
11178       tree assign_temp;
11179
11180       /* This attempts to replicate the test below, but must not be
11181          true when the test below is false.  (Always err on the side
11182          of creating unused temporaries, to avoid ICEs.)  */
11183       if (ffebld_op (dest) != FFEBLD_opSYMTER
11184           || ((dest_tree = ffesymbol_hook (ffebld_symter (dest)).decl_tree)
11185               && (TREE_CODE (dest_tree) != VAR_DECL
11186                   || TREE_ADDRESSABLE (dest_tree))))
11187         {
11188           ffecom_prepare_expr_ (source, dest);
11189           dest_used = TRUE;
11190         }
11191       else
11192         {
11193           ffecom_prepare_expr_ (source, NULL);
11194           dest_used = FALSE;
11195         }
11196
11197       ffecom_prepare_expr_w (NULL_TREE, dest);
11198
11199       /* For COMPLEX assignment like C1=C2, if partial overlap is possible,
11200          create a temporary through which the assignment is to take place,
11201          since MODIFY_EXPR doesn't handle partial overlap properly.  */
11202       if (ffebld_basictype (dest) == FFEINFO_basictypeCOMPLEX
11203           && ffecom_possible_partial_overlap_ (dest, source))
11204         {
11205           assign_temp = ffecom_make_tempvar ("complex_let",
11206                                              ffecom_tree_type
11207                                              [ffebld_basictype (dest)]
11208                                              [ffebld_kindtype (dest)],
11209                                              FFETARGET_charactersizeNONE,
11210                                              -1);
11211         }
11212       else
11213         assign_temp = NULL_TREE;
11214
11215       ffecom_prepare_end ();
11216
11217       dest_tree = ffecom_expr_w (NULL_TREE, dest);
11218       if (dest_tree == error_mark_node)
11219         return;
11220
11221       if ((TREE_CODE (dest_tree) != VAR_DECL)
11222           || TREE_ADDRESSABLE (dest_tree))
11223         source_tree = ffecom_expr_ (source, dest_tree, dest, &dest_used,
11224                                     FALSE, FALSE);
11225       else
11226         {
11227           assert (! dest_used);
11228           dest_used = FALSE;
11229           source_tree = ffecom_expr (source);
11230         }
11231       if (source_tree == error_mark_node)
11232         return;
11233
11234       if (dest_used)
11235         expr_tree = source_tree;
11236       else if (assign_temp)
11237         {
11238 #ifdef MOVE_EXPR
11239           /* The back end understands a conceptual move (evaluate source;
11240              store into dest), so use that, in case it can determine
11241              that it is going to use, say, two registers as temporaries
11242              anyway.  So don't use the temp (and someday avoid generating
11243              it, once this code starts triggering regularly).  */
11244           expr_tree = ffecom_2s (MOVE_EXPR, void_type_node,
11245                                  dest_tree,
11246                                  source_tree);
11247 #else
11248           expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11249                                  assign_temp,
11250                                  source_tree);
11251           expand_expr_stmt (expr_tree);
11252           expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11253                                  dest_tree,
11254                                  assign_temp);
11255 #endif
11256         }
11257       else
11258         expr_tree = ffecom_2s (MODIFY_EXPR, void_type_node,
11259                                dest_tree,
11260                                source_tree);
11261
11262       expand_expr_stmt (expr_tree);
11263       return;
11264     }
11265
11266   ffecom_prepare_let_char_ (ffebld_size_known (dest), source);
11267   ffecom_prepare_expr_w (NULL_TREE, dest);
11268
11269   ffecom_prepare_end ();
11270
11271   ffecom_char_args_ (&dest_tree, &dest_length, dest);
11272   ffecom_let_char_ (dest_tree, dest_length, ffebld_size_known (dest),
11273                     source);
11274 }
11275
11276 #endif
11277 /* ffecom_expr -- Transform expr into gcc tree
11278
11279    tree t;
11280    ffebld expr;  // FFE expression.
11281    tree = ffecom_expr(expr);
11282
11283    Recursive descent on expr while making corresponding tree nodes and
11284    attaching type info and such.  */
11285
11286 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11287 tree
11288 ffecom_expr (ffebld expr)
11289 {
11290   return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, FALSE, FALSE);
11291 }
11292
11293 #endif
11294 /* Like ffecom_expr, but return tree usable for assigned GOTO or FORMAT.  */
11295
11296 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11297 tree
11298 ffecom_expr_assign (ffebld expr)
11299 {
11300   return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11301 }
11302
11303 #endif
11304 /* Like ffecom_expr_rw, but return tree usable for ASSIGN.  */
11305
11306 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11307 tree
11308 ffecom_expr_assign_w (ffebld expr)
11309 {
11310   return ffecom_expr_ (expr, NULL_TREE, NULL, NULL, TRUE, FALSE);
11311 }
11312
11313 #endif
11314 /* Transform expr for use as into read/write tree and stabilize the
11315    reference.  Not for use on CHARACTER expressions.
11316
11317    Recursive descent on expr while making corresponding tree nodes and
11318    attaching type info and such.  */
11319
11320 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11321 tree
11322 ffecom_expr_rw (tree type, ffebld expr)
11323 {
11324   assert (expr != NULL);
11325   /* Different target types not yet supported.  */
11326   assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11327
11328   return stabilize_reference (ffecom_expr (expr));
11329 }
11330
11331 #endif
11332 /* Transform expr for use as into write tree and stabilize the
11333    reference.  Not for use on CHARACTER expressions.
11334
11335    Recursive descent on expr while making corresponding tree nodes and
11336    attaching type info and such.  */
11337
11338 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11339 tree
11340 ffecom_expr_w (tree type, ffebld expr)
11341 {
11342   assert (expr != NULL);
11343   /* Different target types not yet supported.  */
11344   assert (type == NULL_TREE || type == ffecom_type_expr (expr));
11345
11346   return stabilize_reference (ffecom_expr (expr));
11347 }
11348
11349 #endif
11350 /* Do global stuff.  */
11351
11352 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11353 void
11354 ffecom_finish_compile ()
11355 {
11356   assert (ffecom_outer_function_decl_ == NULL_TREE);
11357   assert (current_function_decl == NULL_TREE);
11358
11359   ffeglobal_drive (ffecom_finish_global_);
11360 }
11361
11362 #endif
11363 /* Public entry point for front end to access finish_decl.  */
11364
11365 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11366 void
11367 ffecom_finish_decl (tree decl, tree init, bool is_top_level)
11368 {
11369   assert (!is_top_level);
11370   finish_decl (decl, init, FALSE);
11371 }
11372
11373 #endif
11374 /* Finish a program unit.  */
11375
11376 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11377 void
11378 ffecom_finish_progunit ()
11379 {
11380   ffecom_end_compstmt ();
11381
11382   ffecom_previous_function_decl_ = current_function_decl;
11383   ffecom_which_entrypoint_decl_ = NULL_TREE;
11384
11385   finish_function (0);
11386 }
11387
11388 #endif
11389
11390 /* Wrapper for get_identifier.  pattern is sprintf-like.  */
11391
11392 #if FFECOM_targetCURRENT == FFECOM_targetGCC
11393 tree
11394 ffecom_get_invented_identifier (const char *pattern, ...)
11395 {
11396   tree decl;
11397   char *nam;
11398   va_list ap;
11399
11400   va_start (ap, pattern);
11401   if (vasprintf (&nam, pattern, ap) == 0)
11402     abort ();
11403   va_end (ap);
11404   decl = get_identifier (nam);
11405   free (nam);
11406   IDENTIFIER_INVENTED (decl) = 1;
11407   return decl;
11408 }
11409
11410 ffeinfoBasictype
11411 ffecom_gfrt_basictype (ffecomGfrt gfrt)
11412 {
11413   assert (gfrt < FFECOM_gfrt);
11414
11415   switch (ffecom_gfrt_type_[gfrt])
11416     {
11417     case FFECOM_rttypeVOID_:
11418     case FFECOM_rttypeVOIDSTAR_:
11419       return FFEINFO_basictypeNONE;
11420
11421     case FFECOM_rttypeFTNINT_:
11422       return FFEINFO_basictypeINTEGER;
11423
11424     case FFECOM_rttypeINTEGER_:
11425       return FFEINFO_basictypeINTEGER;
11426
11427     case FFECOM_rttypeLONGINT_:
11428       return FFEINFO_basictypeINTEGER;
11429
11430     case FFECOM_rttypeLOGICAL_:
11431       return FFEINFO_basictypeLOGICAL;
11432
11433     case FFECOM_rttypeREAL_F2C_:
11434     case FFECOM_rttypeREAL_GNU_:
11435       return FFEINFO_basictypeREAL;
11436
11437     case FFECOM_rttypeCOMPLEX_F2C_:
11438     case FFECOM_rttypeCOMPLEX_GNU_:
11439       return FFEINFO_basictypeCOMPLEX;
11440
11441     case FFECOM_rttypeDOUBLE_:
11442     case FFECOM_rttypeDOUBLEREAL_:
11443       return FFEINFO_basictypeREAL;
11444
11445     case FFECOM_rttypeDBLCMPLX_F2C_:
11446     case FFECOM_rttypeDBLCMPLX_GNU_:
11447       return FFEINFO_basictypeCOMPLEX;
11448
11449     case FFECOM_rttypeCHARACTER_:
11450       return FFEINFO_basictypeCHARACTER;
11451
11452     default:
11453       return FFEINFO_basictypeANY;
11454     }
11455 }
11456
11457 ffeinfoKindtype
11458 ffecom_gfrt_kindtype (ffecomGfrt gfrt)
11459 {
11460   assert (gfrt < FFECOM_gfrt);
11461
11462   switch (ffecom_gfrt_type_[gfrt])
11463     {
11464     case FFECOM_rttypeVOID_:
11465     case FFECOM_rttypeVOIDSTAR_:
11466       return FFEINFO_kindtypeNONE;
11467
11468     case FFECOM_rttypeFTNINT_:
11469       return FFEINFO_kindtypeINTEGER1;
11470
11471     case FFECOM_rttypeINTEGER_:
11472       return FFEINFO_kindtypeINTEGER1;
11473
11474     case FFECOM_rttypeLONGINT_:
11475       return FFEINFO_kindtypeINTEGER4;
11476
11477     case FFECOM_rttypeLOGICAL_:
11478       return FFEINFO_kindtypeLOGICAL1;
11479
11480     case FFECOM_rttypeREAL_F2C_:
11481     case FFECOM_rttypeREAL_GNU_:
11482       return FFEINFO_kindtypeREAL1;
11483
11484     case FFECOM_rttypeCOMPLEX_F2C_:
11485     case FFECOM_rttypeCOMPLEX_GNU_:
11486       return FFEINFO_kindtypeREAL1;
11487
11488     case FFECOM_rttypeDOUBLE_:
11489     case FFECOM_rttypeDOUBLEREAL_:
11490       return FFEINFO_kindtypeREAL2;
11491
11492     case FFECOM_rttypeDBLCMPLX_F2C_:
11493     case FFECOM_rttypeDBLCMPLX_GNU_:
11494       return FFEINFO_kindtypeREAL2;
11495
11496     case FFECOM_rttypeCHARACTER_:
11497       return FFEINFO_kindtypeCHARACTER1;
11498
11499     default:
11500       return FFEINFO_kindtypeANY;
11501     }
11502 }
11503
11504 void
11505 ffecom_init_0 ()
11506 {
11507   tree endlink;
11508   int i;
11509   int j;
11510   tree t;
11511   tree field;
11512   ffetype type;
11513   ffetype base_type;
11514   tree double_ftype_double;
11515   tree float_ftype_float;
11516   tree ldouble_ftype_ldouble;
11517   tree ffecom_tree_ptr_to_fun_type_void;
11518
11519   /* This block of code comes from the now-obsolete cktyps.c.  It checks
11520      whether the compiler environment is buggy in known ways, some of which
11521      would, if not explicitly checked here, result in subtle bugs in g77.  */
11522
11523   if (ffe_is_do_internal_checks ())
11524     {
11525       static char names[][12]
11526         =
11527       {"bar", "bletch", "foo", "foobar"};
11528       char *name;
11529       unsigned long ul;
11530       double fl;
11531
11532       name = bsearch ("foo", &names[0], ARRAY_SIZE (names), sizeof (names[0]),
11533                       (int (*)(const void *, const void *)) strcmp);
11534       if (name != (char *) &names[2])
11535         {
11536           assert ("bsearch doesn't work, #define FFEPROJ_BSEARCH 0 in proj.h"
11537                   == NULL);
11538           abort ();
11539         }
11540
11541       ul = strtoul ("123456789", NULL, 10);
11542       if (ul != 123456789L)
11543         {
11544           assert ("strtoul doesn't have enough range, #define FFEPROJ_STRTOUL 0\
11545  in proj.h" == NULL);
11546           abort ();
11547         }
11548
11549       fl = atof ("56.789");
11550       if ((fl < 56.788) || (fl > 56.79))
11551         {
11552           assert ("atof not type double, fix your #include <stdio.h>"
11553                   == NULL);
11554           abort ();
11555         }
11556     }
11557
11558 #if FFECOM_GCC_INCLUDE
11559   ffecom_initialize_char_syntax_ ();
11560 #endif
11561
11562   ffecom_outer_function_decl_ = NULL_TREE;
11563   current_function_decl = NULL_TREE;
11564   named_labels = NULL_TREE;
11565   current_binding_level = NULL_BINDING_LEVEL;
11566   free_binding_level = NULL_BINDING_LEVEL;
11567   /* Make the binding_level structure for global names.  */
11568   pushlevel (0);
11569   global_binding_level = current_binding_level;
11570   current_binding_level->prep_state = 2;
11571
11572   build_common_tree_nodes (1);
11573
11574   /* Define `int' and `char' first so that dbx will output them first.  */
11575   pushdecl (build_decl (TYPE_DECL, get_identifier ("int"),
11576                         integer_type_node));
11577   pushdecl (build_decl (TYPE_DECL, get_identifier ("char"),
11578                         char_type_node));
11579   pushdecl (build_decl (TYPE_DECL, get_identifier ("long int"),
11580                         long_integer_type_node));
11581   pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned int"),
11582                         unsigned_type_node));
11583   pushdecl (build_decl (TYPE_DECL, get_identifier ("long unsigned int"),
11584                         long_unsigned_type_node));
11585   pushdecl (build_decl (TYPE_DECL, get_identifier ("long long int"),
11586                         long_long_integer_type_node));
11587   pushdecl (build_decl (TYPE_DECL, get_identifier ("long long unsigned int"),
11588                         long_long_unsigned_type_node));
11589   pushdecl (build_decl (TYPE_DECL, get_identifier ("short int"),
11590                         short_integer_type_node));
11591   pushdecl (build_decl (TYPE_DECL, get_identifier ("short unsigned int"),
11592                         short_unsigned_type_node));
11593
11594   /* Set the sizetype before we make other types.  This *should* be the
11595      first type we create.  */
11596
11597   set_sizetype
11598     (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
11599   ffecom_typesize_pointer_
11600     = TREE_INT_CST_LOW (TYPE_SIZE (sizetype)) / BITS_PER_UNIT;
11601
11602   build_common_tree_nodes_2 (0);
11603
11604   /* Define both `signed char' and `unsigned char'.  */
11605   pushdecl (build_decl (TYPE_DECL, get_identifier ("signed char"),
11606                         signed_char_type_node));
11607
11608   pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
11609                         unsigned_char_type_node));
11610
11611   pushdecl (build_decl (TYPE_DECL, get_identifier ("float"),
11612                         float_type_node));
11613   pushdecl (build_decl (TYPE_DECL, get_identifier ("double"),
11614                         double_type_node));
11615   pushdecl (build_decl (TYPE_DECL, get_identifier ("long double"),
11616                         long_double_type_node));
11617
11618   /* For now, override what build_common_tree_nodes has done.  */
11619   complex_integer_type_node = ffecom_make_complex_type_ (integer_type_node);
11620   complex_float_type_node = ffecom_make_complex_type_ (float_type_node);
11621   complex_double_type_node = ffecom_make_complex_type_ (double_type_node);
11622   complex_long_double_type_node
11623     = ffecom_make_complex_type_ (long_double_type_node);
11624
11625   pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
11626                         complex_integer_type_node));
11627   pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
11628                         complex_float_type_node));
11629   pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
11630                         complex_double_type_node));
11631   pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
11632                         complex_long_double_type_node));
11633
11634   pushdecl (build_decl (TYPE_DECL, get_identifier ("void"),
11635                         void_type_node));
11636   /* We are not going to have real types in C with less than byte alignment,
11637      so we might as well not have any types that claim to have it.  */
11638   TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
11639
11640   string_type_node = build_pointer_type (char_type_node);
11641
11642   ffecom_tree_fun_type_void
11643     = build_function_type (void_type_node, NULL_TREE);
11644
11645   ffecom_tree_ptr_to_fun_type_void
11646     = build_pointer_type (ffecom_tree_fun_type_void);
11647
11648   endlink = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
11649
11650   float_ftype_float
11651     = build_function_type (float_type_node,
11652                            tree_cons (NULL_TREE, float_type_node, endlink));
11653
11654   double_ftype_double
11655     = build_function_type (double_type_node,
11656                            tree_cons (NULL_TREE, double_type_node, endlink));
11657
11658   ldouble_ftype_ldouble
11659     = build_function_type (long_double_type_node,
11660                            tree_cons (NULL_TREE, long_double_type_node,
11661                                       endlink));
11662
11663   for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11664     for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11665       {
11666         ffecom_tree_type[i][j] = NULL_TREE;
11667         ffecom_tree_fun_type[i][j] = NULL_TREE;
11668         ffecom_tree_ptr_to_fun_type[i][j] = NULL_TREE;
11669         ffecom_f2c_typecode_[i][j] = -1;
11670       }
11671
11672   /* Set up standard g77 types.  Note that INTEGER and LOGICAL are set
11673      to size FLOAT_TYPE_SIZE because they have to be the same size as
11674      REAL, which also is FLOAT_TYPE_SIZE, according to the standard.
11675      Compiler options and other such stuff that change the ways these
11676      types are set should not affect this particular setup.  */
11677
11678   ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1]
11679     = t = make_signed_type (FLOAT_TYPE_SIZE);
11680   pushdecl (build_decl (TYPE_DECL, get_identifier ("integer"),
11681                         t));
11682   type = ffetype_new ();
11683   base_type = type;
11684   ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER1,
11685                     type);
11686   ffetype_set_ams (type,
11687                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11688                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11689   ffetype_set_star (base_type,
11690                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11691                     type);
11692   ffetype_set_kind (base_type, 1, type);
11693   ffecom_typesize_integer1_ = ffetype_size (type);
11694   assert (ffetype_size (type) == sizeof (ffetargetInteger1));
11695
11696   ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER1]
11697     = t = make_unsigned_type (FLOAT_TYPE_SIZE); /* HOLLERITH means unsigned. */
11698   pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned"),
11699                         t));
11700
11701   ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER2]
11702     = t = make_signed_type (CHAR_TYPE_SIZE);
11703   pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"),
11704                         t));
11705   type = ffetype_new ();
11706   ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER2,
11707                     type);
11708   ffetype_set_ams (type,
11709                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11710                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11711   ffetype_set_star (base_type,
11712                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11713                     type);
11714   ffetype_set_kind (base_type, 3, type);
11715   assert (ffetype_size (type) == sizeof (ffetargetInteger2));
11716
11717   ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER2]
11718     = t = make_unsigned_type (CHAR_TYPE_SIZE);
11719   pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned byte"),
11720                         t));
11721
11722   ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER3]
11723     = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11724   pushdecl (build_decl (TYPE_DECL, get_identifier ("word"),
11725                         t));
11726   type = ffetype_new ();
11727   ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER3,
11728                     type);
11729   ffetype_set_ams (type,
11730                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11731                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11732   ffetype_set_star (base_type,
11733                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11734                     type);
11735   ffetype_set_kind (base_type, 6, type);
11736   assert (ffetype_size (type) == sizeof (ffetargetInteger3));
11737
11738   ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER3]
11739     = t = make_unsigned_type (CHAR_TYPE_SIZE * 2);
11740   pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned word"),
11741                         t));
11742
11743   ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER4]
11744     = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11745   pushdecl (build_decl (TYPE_DECL, get_identifier ("integer4"),
11746                         t));
11747   type = ffetype_new ();
11748   ffeinfo_set_type (FFEINFO_basictypeINTEGER, FFEINFO_kindtypeINTEGER4,
11749                     type);
11750   ffetype_set_ams (type,
11751                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11752                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11753   ffetype_set_star (base_type,
11754                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11755                     type);
11756   ffetype_set_kind (base_type, 2, type);
11757   assert (ffetype_size (type) == sizeof (ffetargetInteger4));
11758
11759   ffecom_tree_type[FFEINFO_basictypeHOLLERITH][FFEINFO_kindtypeINTEGER4]
11760     = t = make_unsigned_type (FLOAT_TYPE_SIZE * 2);
11761   pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned4"),
11762                         t));
11763
11764 #if 0
11765   if (ffe_is_do_internal_checks ()
11766       && LONG_TYPE_SIZE != FLOAT_TYPE_SIZE
11767       && LONG_TYPE_SIZE != CHAR_TYPE_SIZE
11768       && LONG_TYPE_SIZE != SHORT_TYPE_SIZE
11769       && LONG_TYPE_SIZE != LONG_LONG_TYPE_SIZE)
11770     {
11771       fprintf (stderr, "Sorry, no g77 support for LONG_TYPE_SIZE (%d bits) yet.\n",
11772                LONG_TYPE_SIZE);
11773     }
11774 #endif
11775
11776   ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL1]
11777     = t = make_signed_type (FLOAT_TYPE_SIZE);
11778   pushdecl (build_decl (TYPE_DECL, get_identifier ("logical"),
11779                         t));
11780   type = ffetype_new ();
11781   base_type = type;
11782   ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL1,
11783                     type);
11784   ffetype_set_ams (type,
11785                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11786                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11787   ffetype_set_star (base_type,
11788                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11789                     type);
11790   ffetype_set_kind (base_type, 1, type);
11791   assert (ffetype_size (type) == sizeof (ffetargetLogical1));
11792
11793   ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL2]
11794     = t = make_signed_type (CHAR_TYPE_SIZE);
11795   pushdecl (build_decl (TYPE_DECL, get_identifier ("logical2"),
11796                         t));
11797   type = ffetype_new ();
11798   ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL2,
11799                     type);
11800   ffetype_set_ams (type,
11801                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11802                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11803   ffetype_set_star (base_type,
11804                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11805                     type);
11806   ffetype_set_kind (base_type, 3, type);
11807   assert (ffetype_size (type) == sizeof (ffetargetLogical2));
11808
11809   ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL3]
11810     = t = make_signed_type (CHAR_TYPE_SIZE * 2);
11811   pushdecl (build_decl (TYPE_DECL, get_identifier ("logical3"),
11812                         t));
11813   type = ffetype_new ();
11814   ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL3,
11815                     type);
11816   ffetype_set_ams (type,
11817                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11818                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11819   ffetype_set_star (base_type,
11820                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11821                     type);
11822   ffetype_set_kind (base_type, 6, type);
11823   assert (ffetype_size (type) == sizeof (ffetargetLogical3));
11824
11825   ffecom_tree_type[FFEINFO_basictypeLOGICAL][FFEINFO_kindtypeLOGICAL4]
11826     = t = make_signed_type (FLOAT_TYPE_SIZE * 2);
11827   pushdecl (build_decl (TYPE_DECL, get_identifier ("logical4"),
11828                         t));
11829   type = ffetype_new ();
11830   ffeinfo_set_type (FFEINFO_basictypeLOGICAL, FFEINFO_kindtypeLOGICAL4,
11831                     type);
11832   ffetype_set_ams (type,
11833                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11834                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11835   ffetype_set_star (base_type,
11836                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11837                     type);
11838   ffetype_set_kind (base_type, 2, type);
11839   assert (ffetype_size (type) == sizeof (ffetargetLogical4));
11840
11841   ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11842     = t = make_node (REAL_TYPE);
11843   TYPE_PRECISION (t) = FLOAT_TYPE_SIZE;
11844   pushdecl (build_decl (TYPE_DECL, get_identifier ("real"),
11845                         t));
11846   layout_type (t);
11847   type = ffetype_new ();
11848   base_type = type;
11849   ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREAL1,
11850                     type);
11851   ffetype_set_ams (type,
11852                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11853                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11854   ffetype_set_star (base_type,
11855                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11856                     type);
11857   ffetype_set_kind (base_type, 1, type);
11858   ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]
11859     = FFETARGET_f2cTYREAL;
11860   assert (ffetype_size (type) == sizeof (ffetargetReal1));
11861
11862   ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREALDOUBLE]
11863     = t = make_node (REAL_TYPE);
11864   TYPE_PRECISION (t) = FLOAT_TYPE_SIZE * 2;     /* Always twice REAL. */
11865   pushdecl (build_decl (TYPE_DECL, get_identifier ("double precision"),
11866                         t));
11867   layout_type (t);
11868   type = ffetype_new ();
11869   ffeinfo_set_type (FFEINFO_basictypeREAL, FFEINFO_kindtypeREALDOUBLE,
11870                     type);
11871   ffetype_set_ams (type,
11872                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11873                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11874   ffetype_set_star (base_type,
11875                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11876                     type);
11877   ffetype_set_kind (base_type, 2, type);
11878   ffecom_f2c_typecode_[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]
11879     = FFETARGET_f2cTYDREAL;
11880   assert (ffetype_size (type) == sizeof (ffetargetReal2));
11881
11882   ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11883     = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL1]);
11884   pushdecl (build_decl (TYPE_DECL, get_identifier ("complex"),
11885                         t));
11886   type = ffetype_new ();
11887   base_type = type;
11888   ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREAL1,
11889                     type);
11890   ffetype_set_ams (type,
11891                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11892                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11893   ffetype_set_star (base_type,
11894                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11895                     type);
11896   ffetype_set_kind (base_type, 1, type);
11897   ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL1]
11898     = FFETARGET_f2cTYCOMPLEX;
11899   assert (ffetype_size (type) == sizeof (ffetargetComplex1));
11900
11901   ffecom_tree_type[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREALDOUBLE]
11902     = t = ffecom_make_complex_type_ (ffecom_tree_type[FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2]);
11903   pushdecl (build_decl (TYPE_DECL, get_identifier ("double complex"),
11904                         t));
11905   type = ffetype_new ();
11906   ffeinfo_set_type (FFEINFO_basictypeCOMPLEX, FFEINFO_kindtypeREALDOUBLE,
11907                     type);
11908   ffetype_set_ams (type,
11909                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
11910                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
11911   ffetype_set_star (base_type,
11912                     TREE_INT_CST_LOW (TYPE_SIZE (t)) / CHAR_TYPE_SIZE,
11913                     type);
11914   ffetype_set_kind (base_type, 2,
11915                     type);
11916   ffecom_f2c_typecode_[FFEINFO_basictypeCOMPLEX][FFEINFO_kindtypeREAL2]
11917     = FFETARGET_f2cTYDCOMPLEX;
11918   assert (ffetype_size (type) == sizeof (ffetargetComplex2));
11919
11920   /* Make function and ptr-to-function types for non-CHARACTER types. */
11921
11922   for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
11923     for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
11924       {
11925         if ((t = ffecom_tree_type[i][j]) != NULL_TREE)
11926           {
11927             if (i == FFEINFO_basictypeINTEGER)
11928               {
11929                 /* Figure out the smallest INTEGER type that can hold
11930                    a pointer on this machine. */
11931                 if (GET_MODE_SIZE (TYPE_MODE (t))
11932                     >= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
11933                   {
11934                     if ((ffecom_pointer_kind_ == FFEINFO_kindtypeNONE)
11935                         || (GET_MODE_SIZE (TYPE_MODE (ffecom_tree_type[i][ffecom_pointer_kind_]))
11936                             > GET_MODE_SIZE (TYPE_MODE (t))))
11937                       ffecom_pointer_kind_ = j;
11938                   }
11939               }
11940             else if (i == FFEINFO_basictypeCOMPLEX)
11941               t = void_type_node;
11942             /* For f2c compatibility, REAL functions are really
11943                implemented as DOUBLE PRECISION.  */
11944             else if ((i == FFEINFO_basictypeREAL)
11945                      && (j == FFEINFO_kindtypeREAL1))
11946               t = ffecom_tree_type
11947                 [FFEINFO_basictypeREAL][FFEINFO_kindtypeREAL2];
11948
11949             t = ffecom_tree_fun_type[i][j] = build_function_type (t,
11950                                                                   NULL_TREE);
11951             ffecom_tree_ptr_to_fun_type[i][j] = build_pointer_type (t);
11952           }
11953       }
11954
11955   /* Set up pointer types.  */
11956
11957   if (ffecom_pointer_kind_ == FFEINFO_basictypeNONE)
11958     fatal ("no INTEGER type can hold a pointer on this configuration");
11959   else if (0 && ffe_is_do_internal_checks ())
11960     fprintf (stderr, "Pointer type kt=%d\n", ffecom_pointer_kind_);
11961   ffetype_set_kind (ffeinfo_type (FFEINFO_basictypeINTEGER,
11962                                   FFEINFO_kindtypeINTEGERDEFAULT),
11963                     7,
11964                     ffeinfo_type (FFEINFO_basictypeINTEGER,
11965                                   ffecom_pointer_kind_));
11966
11967   if (ffe_is_ugly_assign ())
11968     ffecom_label_kind_ = ffecom_pointer_kind_;  /* Require ASSIGN etc to this. */
11969   else
11970     ffecom_label_kind_ = FFEINFO_kindtypeINTEGERDEFAULT;
11971   if (0 && ffe_is_do_internal_checks ())
11972     fprintf (stderr, "Label type kt=%d\n", ffecom_label_kind_);
11973
11974   ffecom_integer_type_node
11975     = ffecom_tree_type[FFEINFO_basictypeINTEGER][FFEINFO_kindtypeINTEGER1];
11976   ffecom_integer_zero_node = convert (ffecom_integer_type_node,
11977                                       integer_zero_node);
11978   ffecom_integer_one_node = convert (ffecom_integer_type_node,
11979                                      integer_one_node);
11980
11981   /* Yes, the "FLOAT_TYPE_SIZE" references below are intentional.
11982      Turns out that by TYLONG, runtime/libI77/lio.h really means
11983      "whatever size an ftnint is".  For consistency and sanity,
11984      com.h and runtime/f2c.h.in agree that flag, ftnint, and ftlen
11985      all are INTEGER, which we also make out of whatever back-end
11986      integer type is FLOAT_TYPE_SIZE bits wide.  This change, from
11987      LONG_TYPE_SIZE, for TYLONG and TYLOGICAL, was necessary to
11988      accommodate machines like the Alpha.  Note that this suggests
11989      f2c and libf2c are missing a distinction perhaps needed on
11990      some machines between "int" and "long int".  -- burley 0.5.5 950215 */
11991
11992   ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, FLOAT_TYPE_SIZE,
11993                             FFETARGET_f2cTYLONG);
11994   ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, SHORT_TYPE_SIZE,
11995                             FFETARGET_f2cTYSHORT);
11996   ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, CHAR_TYPE_SIZE,
11997                             FFETARGET_f2cTYINT1);
11998   ffecom_f2c_set_lio_code_ (FFEINFO_basictypeINTEGER, LONG_LONG_TYPE_SIZE,
11999                             FFETARGET_f2cTYQUAD);
12000   ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, FLOAT_TYPE_SIZE,
12001                             FFETARGET_f2cTYLOGICAL);
12002   ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, SHORT_TYPE_SIZE,
12003                             FFETARGET_f2cTYLOGICAL2);
12004   ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, CHAR_TYPE_SIZE,
12005                             FFETARGET_f2cTYLOGICAL1);
12006   /* ~~~Not really such a type in libf2c, e.g. I/O support?  */
12007   ffecom_f2c_set_lio_code_ (FFEINFO_basictypeLOGICAL, LONG_LONG_TYPE_SIZE,
12008                             FFETARGET_f2cTYQUAD);
12009
12010   /* CHARACTER stuff is all special-cased, so it is not handled in the above
12011      loop.  CHARACTER items are built as arrays of unsigned char.  */
12012
12013   ffecom_tree_type[FFEINFO_basictypeCHARACTER]
12014     [FFEINFO_kindtypeCHARACTER1] = t = char_type_node;
12015   type = ffetype_new ();
12016   base_type = type;
12017   ffeinfo_set_type (FFEINFO_basictypeCHARACTER,
12018                     FFEINFO_kindtypeCHARACTER1,
12019                     type);
12020   ffetype_set_ams (type,
12021                    TYPE_ALIGN (t) / BITS_PER_UNIT, 0,
12022                    TREE_INT_CST_LOW (TYPE_SIZE (t)) / BITS_PER_UNIT);
12023   ffetype_set_kind (base_type, 1, type);
12024   assert (ffetype_size (type)
12025           == sizeof (((ffetargetCharacter1) { 0, NULL }).text[0]));
12026
12027   ffecom_tree_fun_type[FFEINFO_basictypeCHARACTER]
12028     [FFEINFO_kindtypeCHARACTER1] = ffecom_tree_fun_type_void;
12029   ffecom_tree_ptr_to_fun_type[FFEINFO_basictypeCHARACTER]
12030     [FFEINFO_kindtypeCHARACTER1]
12031     = ffecom_tree_ptr_to_fun_type_void;
12032   ffecom_f2c_typecode_[FFEINFO_basictypeCHARACTER][FFEINFO_kindtypeCHARACTER1]
12033     = FFETARGET_f2cTYCHAR;
12034
12035   ffecom_f2c_typecode_[FFEINFO_basictypeANY][FFEINFO_kindtypeANY]
12036     = 0;
12037
12038   /* Make multi-return-value type and fields. */
12039
12040   ffecom_multi_type_node_ = make_node (UNION_TYPE);
12041
12042   field = NULL_TREE;
12043
12044   for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
12045     for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
12046       {
12047         char name[30];
12048
12049         if (ffecom_tree_type[i][j] == NULL_TREE)
12050           continue;             /* Not supported. */
12051         sprintf (&name[0], "bt_%s_kt_%s",
12052                  ffeinfo_basictype_string ((ffeinfoBasictype) i),
12053                  ffeinfo_kindtype_string ((ffeinfoKindtype) j));
12054         ffecom_multi_fields_[i][j] = build_decl (FIELD_DECL,
12055                                                  get_identifier (name),
12056                                                  ffecom_tree_type[i][j]);
12057         DECL_CONTEXT (ffecom_multi_fields_[i][j])
12058           = ffecom_multi_type_node_;
12059         DECL_FRAME_SIZE (ffecom_multi_fields_[i][j]) = 0;
12060         TREE_CHAIN (ffecom_multi_fields_[i][j]) = field;
12061         field = ffecom_multi_fields_[i][j];
12062       }
12063
12064   TYPE_FIELDS (ffecom_multi_type_node_) = field;
12065   layout_type (ffecom_multi_type_node_);
12066
12067   /* Subroutines usually return integer because they might have alternate
12068      returns. */
12069
12070   ffecom_tree_subr_type
12071     = build_function_type (integer_type_node, NULL_TREE);
12072   ffecom_tree_ptr_to_subr_type
12073     = build_pointer_type (ffecom_tree_subr_type);
12074   ffecom_tree_blockdata_type
12075     = build_function_type (void_type_node, NULL_TREE);
12076
12077   builtin_function ("__builtin_sqrtf", float_ftype_float,
12078                     BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtf");
12079   builtin_function ("__builtin_fsqrt", double_ftype_double,
12080                     BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrt");
12081   builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
12082                     BUILT_IN_FSQRT, BUILT_IN_NORMAL, "sqrtl");
12083   builtin_function ("__builtin_sinf", float_ftype_float,
12084                     BUILT_IN_SIN, BUILT_IN_NORMAL, "sinf");
12085   builtin_function ("__builtin_sin", double_ftype_double,
12086                     BUILT_IN_SIN, BUILT_IN_NORMAL, "sin");
12087   builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
12088                     BUILT_IN_SIN, BUILT_IN_NORMAL, "sinl");
12089   builtin_function ("__builtin_cosf", float_ftype_float,
12090                     BUILT_IN_COS, BUILT_IN_NORMAL, "cosf");
12091   builtin_function ("__builtin_cos", double_ftype_double,
12092                     BUILT_IN_COS, BUILT_IN_NORMAL, "cos");
12093   builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
12094                     BUILT_IN_COS, BUILT_IN_NORMAL, "cosl");
12095
12096 #if BUILT_FOR_270
12097   pedantic_lvalues = FALSE;
12098 #endif
12099
12100   ffecom_f2c_make_type_ (&ffecom_f2c_integer_type_node,
12101                          FFECOM_f2cINTEGER,
12102                          "integer");
12103   ffecom_f2c_make_type_ (&ffecom_f2c_address_type_node,
12104                          FFECOM_f2cADDRESS,
12105                          "address");
12106   ffecom_f2c_make_type_ (&ffecom_f2c_real_type_node,
12107                          FFECOM_f2cREAL,
12108                          "real");
12109   ffecom_f2c_make_type_ (&ffecom_f2c_doublereal_type_node,
12110                          FFECOM_f2cDOUBLEREAL,
12111                          "doublereal");
12112   ffecom_f2c_make_type_ (&ffecom_f2c_complex_type_node,
12113                          FFECOM_f2cCOMPLEX,
12114                          "complex");
12115   ffecom_f2c_make_type_ (&ffecom_f2c_doublecomplex_type_node,
12116                          FFECOM_f2cDOUBLECOMPLEX,
12117                          "doublecomplex");
12118   ffecom_f2c_make_type_ (&ffecom_f2c_longint_type_node,
12119                          FFECOM_f2cLONGINT,
12120                          "longint");
12121   ffecom_f2c_make_type_ (&ffecom_f2c_logical_type_node,
12122                          FFECOM_f2cLOGICAL,
12123                          "logical");
12124   ffecom_f2c_make_type_ (&ffecom_f2c_flag_type_node,
12125                          FFECOM_f2cFLAG,
12126                          "flag");
12127   ffecom_f2c_make_type_ (&ffecom_f2c_ftnlen_type_node,
12128                          FFECOM_f2cFTNLEN,
12129                          "ftnlen");
12130   ffecom_f2c_make_type_ (&ffecom_f2c_ftnint_type_node,
12131                          FFECOM_f2cFTNINT,
12132                          "ftnint");
12133
12134   ffecom_f2c_ftnlen_zero_node
12135     = convert (ffecom_f2c_ftnlen_type_node, integer_zero_node);
12136
12137   ffecom_f2c_ftnlen_one_node
12138     = convert (ffecom_f2c_ftnlen_type_node, integer_one_node);
12139
12140   ffecom_f2c_ftnlen_two_node = build_int_2 (2, 0);
12141   TREE_TYPE (ffecom_f2c_ftnlen_two_node) = ffecom_integer_type_node;
12142
12143   ffecom_f2c_ptr_to_ftnlen_type_node
12144     = build_pointer_type (ffecom_f2c_ftnlen_type_node);
12145
12146   ffecom_f2c_ptr_to_ftnint_type_node
12147     = build_pointer_type (ffecom_f2c_ftnint_type_node);
12148
12149   ffecom_f2c_ptr_to_integer_type_node
12150     = build_pointer_type (ffecom_f2c_integer_type_node);
12151
12152   ffecom_f2c_ptr_to_real_type_node
12153     = build_pointer_type (ffecom_f2c_real_type_node);
12154
12155   ffecom_float_zero_ = build_real (float_type_node, dconst0);
12156   ffecom_double_zero_ = build_real (double_type_node, dconst0);
12157   {
12158     REAL_VALUE_TYPE point_5;
12159
12160 #ifdef REAL_ARITHMETIC
12161     REAL_ARITHMETIC (point_5, RDIV_EXPR, dconst1, dconst2);
12162 #else
12163     point_5 = .5;
12164 #endif
12165     ffecom_float_half_ = build_real (float_type_node, point_5);
12166     ffecom_double_half_ = build_real (double_type_node, point_5);
12167   }
12168
12169   /* Do "extern int xargc;".  */
12170
12171   ffecom_tree_xargc_ = build_decl (VAR_DECL,
12172                                    get_identifier ("f__xargc"),
12173                                    integer_type_node);
12174   DECL_EXTERNAL (ffecom_tree_xargc_) = 1;
12175   TREE_STATIC (ffecom_tree_xargc_) = 1;
12176   TREE_PUBLIC (ffecom_tree_xargc_) = 1;
12177   ffecom_tree_xargc_ = start_decl (ffecom_tree_xargc_, FALSE);
12178   finish_decl (ffecom_tree_xargc_, NULL_TREE, FALSE);
12179
12180 #if 0   /* This is being fixed, and seems to be working now. */
12181   if ((FLOAT_TYPE_SIZE != 32)
12182       || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))) != 32))
12183     {
12184       warning ("configuration: REAL, INTEGER, and LOGICAL are %d bits wide,",
12185                (int) FLOAT_TYPE_SIZE);
12186       warning ("and pointers are %d bits wide, but g77 doesn't yet work",
12187           (int) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (null_pointer_node))));
12188       warning ("properly unless they all are 32 bits wide.");
12189       warning ("Please keep this in mind before you report bugs.  g77 should");
12190       warning ("support non-32-bit machines better as of version 0.6.");
12191     }
12192 #endif
12193
12194 #if 0   /* Code in ste.c that would crash has been commented out. */
12195   if (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
12196       < TYPE_PRECISION (string_type_node))
12197     /* I/O will probably crash.  */
12198     warning ("configuration: char * holds %d bits, but ftnlen only %d",
12199              TYPE_PRECISION (string_type_node),
12200              TYPE_PRECISION (ffecom_f2c_ftnlen_type_node));
12201 #endif
12202
12203 #if 0   /* ASSIGN-related stuff has been changed to accommodate this. */
12204   if (TYPE_PRECISION (ffecom_integer_type_node)
12205       < TYPE_PRECISION (string_type_node))
12206     /* ASSIGN 10 TO I will crash.  */
12207     warning ("configuration: char * holds %d bits, but INTEGER only %d --\n\
12208  ASSIGN statement might fail",
12209              TYPE_PRECISION (string_type_node),
12210              TYPE_PRECISION (ffecom_integer_type_node));
12211 #endif
12212 }
12213
12214 #endif
12215 /* ffecom_init_2 -- Initialize
12216
12217    ffecom_init_2();  */
12218
12219 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12220 void
12221 ffecom_init_2 ()
12222 {
12223   assert (ffecom_outer_function_decl_ == NULL_TREE);
12224   assert (current_function_decl == NULL_TREE);
12225   assert (ffecom_which_entrypoint_decl_ == NULL_TREE);
12226
12227   ffecom_master_arglist_ = NULL;
12228   ++ffecom_num_fns_;
12229   ffecom_primary_entry_ = NULL;
12230   ffecom_is_altreturning_ = FALSE;
12231   ffecom_func_result_ = NULL_TREE;
12232   ffecom_multi_retval_ = NULL_TREE;
12233 }
12234
12235 #endif
12236 /* ffecom_list_expr -- Transform list of exprs into gcc tree
12237
12238    tree t;
12239    ffebld expr;  // FFE opITEM list.
12240    tree = ffecom_list_expr(expr);
12241
12242    List of actual args is transformed into corresponding gcc backend list.  */
12243
12244 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12245 tree
12246 ffecom_list_expr (ffebld expr)
12247 {
12248   tree list;
12249   tree *plist = &list;
12250   tree trail = NULL_TREE;       /* Append char length args here. */
12251   tree *ptrail = &trail;
12252   tree length;
12253
12254   while (expr != NULL)
12255     {
12256       tree texpr = ffecom_arg_expr (ffebld_head (expr), &length);
12257
12258       if (texpr == error_mark_node)
12259         return error_mark_node;
12260
12261       *plist = build_tree_list (NULL_TREE, texpr);
12262       plist = &TREE_CHAIN (*plist);
12263       expr = ffebld_trail (expr);
12264       if (length != NULL_TREE)
12265         {
12266           *ptrail = build_tree_list (NULL_TREE, length);
12267           ptrail = &TREE_CHAIN (*ptrail);
12268         }
12269     }
12270
12271   *plist = trail;
12272
12273   return list;
12274 }
12275
12276 #endif
12277 /* ffecom_list_ptr_to_expr -- Transform list of exprs into gcc tree
12278
12279    tree t;
12280    ffebld expr;  // FFE opITEM list.
12281    tree = ffecom_list_ptr_to_expr(expr);
12282
12283    List of actual args is transformed into corresponding gcc backend list for
12284    use in calling an external procedure (vs. a statement function).  */
12285
12286 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12287 tree
12288 ffecom_list_ptr_to_expr (ffebld expr)
12289 {
12290   tree list;
12291   tree *plist = &list;
12292   tree trail = NULL_TREE;       /* Append char length args here. */
12293   tree *ptrail = &trail;
12294   tree length;
12295
12296   while (expr != NULL)
12297     {
12298       tree texpr = ffecom_arg_ptr_to_expr (ffebld_head (expr), &length);
12299
12300       if (texpr == error_mark_node)
12301         return error_mark_node;
12302
12303       *plist = build_tree_list (NULL_TREE, texpr);
12304       plist = &TREE_CHAIN (*plist);
12305       expr = ffebld_trail (expr);
12306       if (length != NULL_TREE)
12307         {
12308           *ptrail = build_tree_list (NULL_TREE, length);
12309           ptrail = &TREE_CHAIN (*ptrail);
12310         }
12311     }
12312
12313   *plist = trail;
12314
12315   return list;
12316 }
12317
12318 #endif
12319 /* Obtain gcc's LABEL_DECL tree for label.  */
12320
12321 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12322 tree
12323 ffecom_lookup_label (ffelab label)
12324 {
12325   tree glabel;
12326
12327   if (ffelab_hook (label) == NULL_TREE)
12328     {
12329       char labelname[16];
12330
12331       switch (ffelab_type (label))
12332         {
12333         case FFELAB_typeLOOPEND:
12334         case FFELAB_typeNOTLOOP:
12335         case FFELAB_typeENDIF:
12336           sprintf (labelname, "%" ffelabValue_f "u", ffelab_value (label));
12337           glabel = build_decl (LABEL_DECL, get_identifier (labelname),
12338                                void_type_node);
12339           DECL_CONTEXT (glabel) = current_function_decl;
12340           DECL_MODE (glabel) = VOIDmode;
12341           break;
12342
12343         case FFELAB_typeFORMAT:
12344           glabel = build_decl (VAR_DECL,
12345                                ffecom_get_invented_identifier
12346                                ("__g77_format_%d", (int) ffelab_value (label)),
12347                                build_type_variant (build_array_type
12348                                                    (char_type_node,
12349                                                     NULL_TREE),
12350                                                    1, 0));
12351           TREE_CONSTANT (glabel) = 1;
12352           TREE_STATIC (glabel) = 1;
12353           DECL_CONTEXT (glabel) = 0;
12354           DECL_INITIAL (glabel) = NULL;
12355           make_decl_rtl (glabel, NULL, 0);
12356           expand_decl (glabel);
12357
12358           ffecom_save_tree_forever (glabel);
12359
12360           break;
12361
12362         case FFELAB_typeANY:
12363           glabel = error_mark_node;
12364           break;
12365
12366         default:
12367           assert ("bad label type" == NULL);
12368           glabel = NULL;
12369           break;
12370         }
12371       ffelab_set_hook (label, glabel);
12372     }
12373   else
12374     {
12375       glabel = ffelab_hook (label);
12376     }
12377
12378   return glabel;
12379 }
12380
12381 #endif
12382 /* Stabilizes the arguments.  Don't use this if the lhs and rhs come from
12383    a single source specification (as in the fourth argument of MVBITS).
12384    If the type is NULL_TREE, the type of lhs is used to make the type of
12385    the MODIFY_EXPR.  */
12386
12387 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12388 tree
12389 ffecom_modify (tree newtype, tree lhs,
12390                tree rhs)
12391 {
12392   if (lhs == error_mark_node || rhs == error_mark_node)
12393     return error_mark_node;
12394
12395   if (newtype == NULL_TREE)
12396     newtype = TREE_TYPE (lhs);
12397
12398   if (TREE_SIDE_EFFECTS (lhs))
12399     lhs = stabilize_reference (lhs);
12400
12401   return ffecom_2s (MODIFY_EXPR, newtype, lhs, rhs);
12402 }
12403
12404 #endif
12405
12406 /* Register source file name.  */
12407
12408 void
12409 ffecom_file (const char *name)
12410 {
12411 #if FFECOM_GCC_INCLUDE
12412   ffecom_file_ (name);
12413 #endif
12414 }
12415
12416 /* ffecom_notify_init_storage -- An aggregate storage is now fully init'ed
12417
12418    ffestorag st;
12419    ffecom_notify_init_storage(st);
12420
12421    Gets called when all possible units in an aggregate storage area (a LOCAL
12422    with equivalences or a COMMON) have been initialized.  The initialization
12423    info either is in ffestorag_init or, if that is NULL,
12424    ffestorag_accretion:
12425
12426    ffestorag_init may contain an opCONTER or opARRTER.  opCONTER may occur
12427    even for an array if the array is one element in length!
12428
12429    ffestorag_accretion will contain an opACCTER.  It is much like an
12430    opARRTER except it has an ffebit object in it instead of just a size.
12431    The back end can use the info in the ffebit object, if it wants, to
12432    reduce the amount of actual initialization, but in any case it should
12433    kill the ffebit object when done.  Also, set accretion to NULL but
12434    init to a non-NULL value.
12435
12436    After performing initialization, DO NOT set init to NULL, because that'll
12437    tell the front end it is ok for more initialization to happen.  Instead,
12438    set init to an opANY expression or some such thing that you can use to
12439    tell that you've already initialized the object.
12440
12441    27-Oct-91  JCB  1.1
12442       Support two-pass FFE.  */
12443
12444 void
12445 ffecom_notify_init_storage (ffestorag st)
12446 {
12447   ffebld init;                  /* The initialization expression. */
12448 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12449   ffetargetOffset size;         /* The size of the entity. */
12450   ffetargetAlign pad;           /* Its initial padding. */
12451 #endif
12452
12453   if (ffestorag_init (st) == NULL)
12454     {
12455       init = ffestorag_accretion (st);
12456       assert (init != NULL);
12457       ffestorag_set_accretion (st, NULL);
12458       ffestorag_set_accretes (st, 0);
12459
12460 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12461       /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12462       size = ffebld_accter_size (init);
12463       pad = ffebld_accter_pad (init);
12464       ffebit_kill (ffebld_accter_bits (init));
12465       ffebld_set_op (init, FFEBLD_opARRTER);
12466       ffebld_set_arrter (init, ffebld_accter (init));
12467       ffebld_arrter_set_size (init, size);
12468       ffebld_arrter_set_pad (init, size);
12469 #endif
12470
12471 #if FFECOM_TWOPASS
12472       ffestorag_set_init (st, init);
12473 #endif
12474     }
12475 #if FFECOM_ONEPASS
12476   else
12477     init = ffestorag_init (st);
12478 #endif
12479
12480 #if FFECOM_ONEPASS              /* Process the inits, wipe 'em out. */
12481   ffestorag_set_init (st, ffebld_new_any ());
12482
12483   if (ffebld_op (init) == FFEBLD_opANY)
12484     return;                     /* Oh, we already did this! */
12485
12486 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12487   {
12488     ffesymbol s;
12489
12490     if (ffestorag_symbol (st) != NULL)
12491       s = ffestorag_symbol (st);
12492     else
12493       s = ffestorag_typesymbol (st);
12494
12495     fprintf (dmpout, "= initialize_storage \"%s\" ",
12496              (s != NULL) ? ffesymbol_text (s) : "(unnamed)");
12497     ffebld_dump (init);
12498     fputc ('\n', dmpout);
12499   }
12500 #endif
12501
12502 #endif /* if FFECOM_ONEPASS */
12503 }
12504
12505 /* ffecom_notify_init_symbol -- A symbol is now fully init'ed
12506
12507    ffesymbol s;
12508    ffecom_notify_init_symbol(s);
12509
12510    Gets called when all possible units in a symbol (not placed in COMMON
12511    or involved in EQUIVALENCE, unless it as yet has no ffestorag object)
12512    have been initialized.  The initialization info either is in
12513    ffesymbol_init or, if that is NULL, ffesymbol_accretion:
12514
12515    ffesymbol_init may contain an opCONTER or opARRTER.  opCONTER may occur
12516    even for an array if the array is one element in length!
12517
12518    ffesymbol_accretion will contain an opACCTER.  It is much like an
12519    opARRTER except it has an ffebit object in it instead of just a size.
12520    The back end can use the info in the ffebit object, if it wants, to
12521    reduce the amount of actual initialization, but in any case it should
12522    kill the ffebit object when done.  Also, set accretion to NULL but
12523    init to a non-NULL value.
12524
12525    After performing initialization, DO NOT set init to NULL, because that'll
12526    tell the front end it is ok for more initialization to happen.  Instead,
12527    set init to an opANY expression or some such thing that you can use to
12528    tell that you've already initialized the object.
12529
12530    27-Oct-91  JCB  1.1
12531       Support two-pass FFE.  */
12532
12533 void
12534 ffecom_notify_init_symbol (ffesymbol s)
12535 {
12536   ffebld init;                  /* The initialization expression. */
12537 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12538   ffetargetOffset size;         /* The size of the entity. */
12539   ffetargetAlign pad;           /* Its initial padding. */
12540 #endif
12541
12542   if (ffesymbol_storage (s) == NULL)
12543     return;                     /* Do nothing until COMMON/EQUIVALENCE
12544                                    possibilities checked. */
12545
12546   if ((ffesymbol_init (s) == NULL)
12547       && ((init = ffesymbol_accretion (s)) != NULL))
12548     {
12549       ffesymbol_set_accretion (s, NULL);
12550       ffesymbol_set_accretes (s, 0);
12551
12552 #if 0 && FFECOM_targetCURRENT == FFECOM_targetGCC
12553       /* For GNU backend, just turn ACCTER into ARRTER and proceed. */
12554       size = ffebld_accter_size (init);
12555       pad = ffebld_accter_pad (init);
12556       ffebit_kill (ffebld_accter_bits (init));
12557       ffebld_set_op (init, FFEBLD_opARRTER);
12558       ffebld_set_arrter (init, ffebld_accter (init));
12559       ffebld_arrter_set_size (init, size);
12560       ffebld_arrter_set_pad (init, size);
12561 #endif
12562
12563 #if FFECOM_TWOPASS
12564       ffesymbol_set_init (s, init);
12565 #endif
12566     }
12567 #if FFECOM_ONEPASS
12568   else
12569     init = ffesymbol_init (s);
12570 #endif
12571
12572 #if FFECOM_ONEPASS
12573   ffesymbol_set_init (s, ffebld_new_any ());
12574
12575   if (ffebld_op (init) == FFEBLD_opANY)
12576     return;                     /* Oh, we already did this! */
12577
12578 #if FFECOM_targetCURRENT == FFECOM_targetFFE
12579   fprintf (dmpout, "= initialize_symbol \"%s\" ", ffesymbol_text (s));
12580   ffebld_dump (init);
12581   fputc ('\n', dmpout);
12582 #endif
12583
12584 #endif /* if FFECOM_ONEPASS */
12585 }
12586
12587 /* ffecom_notify_primary_entry -- Learn which is the primary entry point
12588
12589    ffesymbol s;
12590    ffecom_notify_primary_entry(s);
12591
12592    Gets called when implicit or explicit PROGRAM statement seen or when
12593    FUNCTION, SUBROUTINE, or BLOCK DATA statement seen, with the primary
12594    global symbol that serves as the entry point.  */
12595
12596 void
12597 ffecom_notify_primary_entry (ffesymbol s)
12598 {
12599   ffecom_primary_entry_ = s;
12600   ffecom_primary_entry_kind_ = ffesymbol_kind (s);
12601
12602   if ((ffecom_primary_entry_kind_ == FFEINFO_kindFUNCTION)
12603       || (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE))
12604     ffecom_primary_entry_is_proc_ = TRUE;
12605   else
12606     ffecom_primary_entry_is_proc_ = FALSE;
12607
12608   if (!ffe_is_silent ())
12609     {
12610       if (ffecom_primary_entry_kind_ == FFEINFO_kindPROGRAM)
12611         fprintf (stderr, "%s:\n", ffesymbol_text (s));
12612       else
12613         fprintf (stderr, "  %s:\n", ffesymbol_text (s));
12614     }
12615
12616 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12617   if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE)
12618     {
12619       ffebld list;
12620       ffebld arg;
12621
12622       for (list = ffesymbol_dummyargs (s);
12623            list != NULL;
12624            list = ffebld_trail (list))
12625         {
12626           arg = ffebld_head (list);
12627           if (ffebld_op (arg) == FFEBLD_opSTAR)
12628             {
12629               ffecom_is_altreturning_ = TRUE;
12630               break;
12631             }
12632         }
12633     }
12634 #endif
12635 }
12636
12637 FILE *
12638 ffecom_open_include (char *name, ffewhereLine l, ffewhereColumn c)
12639 {
12640 #if FFECOM_GCC_INCLUDE
12641   return ffecom_open_include_ (name, l, c);
12642 #else
12643   return fopen (name, "r");
12644 #endif
12645 }
12646
12647 /* ffecom_ptr_to_expr -- Transform expr into gcc tree with & in front
12648
12649    tree t;
12650    ffebld expr;  // FFE expression.
12651    tree = ffecom_ptr_to_expr(expr);
12652
12653    Like ffecom_expr, but sticks address-of in front of most things.  */
12654
12655 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12656 tree
12657 ffecom_ptr_to_expr (ffebld expr)
12658 {
12659   tree item;
12660   ffeinfoBasictype bt;
12661   ffeinfoKindtype kt;
12662   ffesymbol s;
12663
12664   assert (expr != NULL);
12665
12666   switch (ffebld_op (expr))
12667     {
12668     case FFEBLD_opSYMTER:
12669       s = ffebld_symter (expr);
12670       if (ffesymbol_where (s) == FFEINFO_whereINTRINSIC)
12671         {
12672           ffecomGfrt ix;
12673
12674           ix = ffeintrin_gfrt_indirect (ffebld_symter_implementation (expr));
12675           assert (ix != FFECOM_gfrt);
12676           if ((item = ffecom_gfrt_[ix]) == NULL_TREE)
12677             {
12678               ffecom_make_gfrt_ (ix);
12679               item = ffecom_gfrt_[ix];
12680             }
12681         }
12682       else
12683         {
12684           item = ffesymbol_hook (s).decl_tree;
12685           if (item == NULL_TREE)
12686             {
12687               s = ffecom_sym_transform_ (s);
12688               item = ffesymbol_hook (s).decl_tree;
12689             }
12690         }
12691       assert (item != NULL);
12692       if (item == error_mark_node)
12693         return item;
12694       if (!ffesymbol_hook (s).addr)
12695         item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12696                          item);
12697       return item;
12698
12699     case FFEBLD_opARRAYREF:
12700       return ffecom_arrayref_ (NULL_TREE, expr, 1);
12701
12702     case FFEBLD_opCONTER:
12703
12704       bt = ffeinfo_basictype (ffebld_info (expr));
12705       kt = ffeinfo_kindtype (ffebld_info (expr));
12706
12707       item = ffecom_constantunion (&ffebld_constant_union
12708                                    (ffebld_conter (expr)), bt, kt,
12709                                    ffecom_tree_type[bt][kt]);
12710       if (item == error_mark_node)
12711         return error_mark_node;
12712       item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12713                        item);
12714       return item;
12715
12716     case FFEBLD_opANY:
12717       return error_mark_node;
12718
12719     default:
12720       bt = ffeinfo_basictype (ffebld_info (expr));
12721       kt = ffeinfo_kindtype (ffebld_info (expr));
12722
12723       item = ffecom_expr (expr);
12724       if (item == error_mark_node)
12725         return error_mark_node;
12726
12727       /* The back end currently optimizes a bit too zealously for us, in that
12728          we fail JCB001 if the following block of code is omitted.  It checks
12729          to see if the transformed expression is a symbol or array reference,
12730          and encloses it in a SAVE_EXPR if that is the case.  */
12731
12732       STRIP_NOPS (item);
12733       if ((TREE_CODE (item) == VAR_DECL)
12734           || (TREE_CODE (item) == PARM_DECL)
12735           || (TREE_CODE (item) == RESULT_DECL)
12736           || (TREE_CODE (item) == INDIRECT_REF)
12737           || (TREE_CODE (item) == ARRAY_REF)
12738           || (TREE_CODE (item) == COMPONENT_REF)
12739 #ifdef OFFSET_REF
12740           || (TREE_CODE (item) == OFFSET_REF)
12741 #endif
12742           || (TREE_CODE (item) == BUFFER_REF)
12743           || (TREE_CODE (item) == REALPART_EXPR)
12744           || (TREE_CODE (item) == IMAGPART_EXPR))
12745         {
12746           item = ffecom_save_tree (item);
12747         }
12748
12749       item = ffecom_1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (item)),
12750                        item);
12751       return item;
12752     }
12753
12754   assert ("fall-through error" == NULL);
12755   return error_mark_node;
12756 }
12757
12758 #endif
12759 /* Obtain a temp var with given data type.
12760
12761    size is FFETARGET_charactersizeNONE for a non-CHARACTER type
12762    or >= 0 for a CHARACTER type.
12763
12764    elements is -1 for a scalar or > 0 for an array of type.  */
12765
12766 #if FFECOM_targetCURRENT == FFECOM_targetGCC
12767 tree
12768 ffecom_make_tempvar (const char *commentary, tree type,
12769                      ffetargetCharacterSize size, int elements)
12770 {
12771   int yes;
12772   tree t;
12773   static int mynumber;
12774
12775   assert (current_binding_level->prep_state < 2);
12776
12777   if (type == error_mark_node)
12778     return error_mark_node;
12779
12780   yes = suspend_momentary ();
12781
12782   if (size != FFETARGET_charactersizeNONE)
12783     type = build_array_type (type,
12784                              build_range_type (ffecom_f2c_ftnlen_type_node,
12785                                                ffecom_f2c_ftnlen_one_node,
12786                                                build_int_2 (size, 0)));
12787   if (elements != -1)
12788     type = build_array_type (type,
12789                              build_range_type (integer_type_node,
12790                                                integer_zero_node,
12791                                                build_int_2 (elements - 1,
12792                                                             0)));
12793   t = build_decl (VAR_DECL,
12794                   ffecom_get_invented_identifier ("__g77_%s_%d",
12795                                                   commentary,
12796                                                   mynumber++),
12797                   type);
12798
12799   t = start_decl (t, FALSE);
12800   finish_decl (t, NULL_TREE, FALSE);
12801
12802   resume_momentary (yes);
12803
12804   return t;
12805 }
12806 #endif
12807
12808 /* Prepare argument pointer to expression.
12809
12810    Like ffecom_prepare_expr, except for expressions to be evaluated
12811    via ffecom_arg_ptr_to_expr.  */
12812
12813 void
12814 ffecom_prepare_arg_ptr_to_expr (ffebld expr)
12815 {
12816   /* ~~For now, it seems to be the same thing.  */
12817   ffecom_prepare_expr (expr);
12818   return;
12819 }
12820
12821 /* End of preparations.  */
12822
12823 bool
12824 ffecom_prepare_end (void)
12825 {
12826   int prep_state = current_binding_level->prep_state;
12827
12828   assert (prep_state < 2);
12829   current_binding_level->prep_state = 2;
12830
12831   return (prep_state == 1) ? TRUE : FALSE;
12832 }
12833
12834 /* Prepare expression.
12835
12836    This is called before any code is generated for the current block.
12837    It scans the expression, declares any temporaries that might be needed
12838    during evaluation of the expression, and stores those temporaries in
12839    the appropriate "hook" fields of the expression.  `dest', if not NULL,
12840    specifies the destination that ffecom_expr_ will see, in case that
12841    helps avoid generating unused temporaries.
12842
12843    ~~Improve to avoid allocating unused temporaries by taking `dest'
12844    into account vis-a-vis aliasing requirements of complex/character
12845    functions.  */
12846
12847 void
12848 ffecom_prepare_expr_ (ffebld expr, ffebld dest UNUSED)
12849 {
12850   ffeinfoBasictype bt;
12851   ffeinfoKindtype kt;
12852   ffetargetCharacterSize sz;
12853   tree tempvar = NULL_TREE;
12854
12855   assert (current_binding_level->prep_state < 2);
12856
12857   if (! expr)
12858     return;
12859
12860   bt = ffeinfo_basictype (ffebld_info (expr));
12861   kt = ffeinfo_kindtype (ffebld_info (expr));
12862   sz = ffeinfo_size (ffebld_info (expr));
12863
12864   /* Generate whatever temporaries are needed to represent the result
12865      of the expression.  */
12866
12867   if (bt == FFEINFO_basictypeCHARACTER)
12868     {
12869       while (ffebld_op (expr) == FFEBLD_opPAREN)
12870         expr = ffebld_left (expr);
12871     }
12872
12873   switch (ffebld_op (expr))
12874     {
12875     default:
12876       /* Don't make temps for SYMTER, CONTER, etc.  */
12877       if (ffebld_arity (expr) == 0)
12878         break;
12879
12880       switch (bt)
12881         {
12882         case FFEINFO_basictypeCOMPLEX:
12883           if (ffebld_op (expr) == FFEBLD_opFUNCREF)
12884             {
12885               ffesymbol s;
12886
12887               if (ffebld_op (ffebld_left (expr)) != FFEBLD_opSYMTER)
12888                 break;
12889
12890               s = ffebld_symter (ffebld_left (expr));
12891               if (ffesymbol_where (s) == FFEINFO_whereCONSTANT
12892                   || (ffesymbol_where (s) != FFEINFO_whereINTRINSIC
12893                       && ! ffesymbol_is_f2c (s))
12894                   || (ffesymbol_where (s) == FFEINFO_whereINTRINSIC
12895                       && ! ffe_is_f2c_library ()))
12896                 break;
12897             }
12898           else if (ffebld_op (expr) == FFEBLD_opPOWER)
12899             {
12900               /* Requires special treatment.  There's no POW_CC function
12901                  in libg2c, so POW_ZZ is used, which means we always
12902                  need a double-complex temp, not a single-complex.  */
12903               kt = FFEINFO_kindtypeREAL2;
12904             }
12905           else if (ffebld_op (expr) != FFEBLD_opDIVIDE)
12906             /* The other ops don't need temps for complex operands.  */
12907             break;
12908
12909           /* ~~~Avoid making temps for some intrinsics, such as AIMAG(C),
12910              REAL(C).  See 19990325-0.f, routine `check', for cases.  */
12911           tempvar = ffecom_make_tempvar ("complex",
12912                                          ffecom_tree_type
12913                                          [FFEINFO_basictypeCOMPLEX][kt],
12914                                          FFETARGET_charactersizeNONE,
12915                                          -1);
12916           break;
12917
12918         case FFEINFO_basictypeCHARACTER:
12919           if (ffebld_op (expr) != FFEBLD_opFUNCREF)
12920             break;
12921
12922           if (sz == FFETARGET_charactersizeNONE)
12923             /* ~~Kludge alert!  This should someday be fixed. */
12924             sz = 24;
12925
12926           tempvar = ffecom_make_tempvar ("char", char_type_node, sz, -1);
12927           break;
12928
12929         default:
12930           break;
12931         }
12932       break;
12933
12934 #ifdef HAHA
12935     case FFEBLD_opPOWER:
12936       {
12937         tree rtype, ltype;
12938         tree rtmp, ltmp, result;
12939
12940         ltype = ffecom_type_expr (ffebld_left (expr));
12941         rtype = ffecom_type_expr (ffebld_right (expr));
12942
12943         rtmp = ffecom_make_tempvar (rtype, FFETARGET_charactersizeNONE, -1);
12944         ltmp = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12945         result = ffecom_make_tempvar (ltype, FFETARGET_charactersizeNONE, -1);
12946
12947         tempvar = make_tree_vec (3);
12948         TREE_VEC_ELT (tempvar, 0) = rtmp;
12949         TREE_VEC_ELT (tempvar, 1) = ltmp;
12950         TREE_VEC_ELT (tempvar, 2) = result;
12951       }
12952       break;
12953 #endif  /* HAHA */
12954
12955     case FFEBLD_opCONCATENATE:
12956       {
12957         /* This gets special handling, because only one set of temps
12958            is needed for a tree of these -- the tree is treated as
12959            a flattened list of concatenations when generating code.  */
12960
12961         ffecomConcatList_ catlist;
12962         tree ltmp, itmp, result;
12963         int count;
12964         int i;
12965
12966         catlist = ffecom_concat_list_new_ (expr, FFETARGET_charactersizeNONE);
12967         count = ffecom_concat_list_count_ (catlist);
12968
12969         if (count >= 2)
12970           {
12971             ltmp
12972               = ffecom_make_tempvar ("concat_len",
12973                                      ffecom_f2c_ftnlen_type_node,
12974                                      FFETARGET_charactersizeNONE, count);
12975             itmp
12976               = ffecom_make_tempvar ("concat_item",
12977                                      ffecom_f2c_address_type_node,
12978                                      FFETARGET_charactersizeNONE, count);
12979             result
12980               = ffecom_make_tempvar ("concat_res",
12981                                      char_type_node,
12982                                      ffecom_concat_list_maxlen_ (catlist),
12983                                      -1);
12984
12985             tempvar = make_tree_vec (3);
12986             TREE_VEC_ELT (tempvar, 0) = ltmp;
12987             TREE_VEC_ELT (tempvar, 1) = itmp;
12988             TREE_VEC_ELT (tempvar, 2) = result;
12989           }
12990
12991         for (i = 0; i < count; ++i)
12992           ffecom_prepare_arg_ptr_to_expr (ffecom_concat_list_expr_ (catlist,
12993                                                                     i));
12994
12995         ffecom_concat_list_kill_ (catlist);
12996
12997         if (tempvar)
12998           {
12999             ffebld_nonter_set_hook (expr, tempvar);
13000             current_binding_level->prep_state = 1;
13001           }
13002       }
13003       return;
13004
13005     case FFEBLD_opCONVERT:
13006       if (bt == FFEINFO_basictypeCHARACTER
13007           && ((ffebld_size_known (ffebld_left (expr))
13008                == FFETARGET_charactersizeNONE)
13009               || (ffebld_size_known (ffebld_left (expr)) >= sz)))
13010         tempvar = ffecom_make_tempvar ("convert", char_type_node, sz, -1);
13011       break;
13012     }
13013
13014   if (tempvar)
13015     {
13016       ffebld_nonter_set_hook (expr, tempvar);
13017       current_binding_level->prep_state = 1;
13018     }
13019
13020   /* Prepare subexpressions for this expr.  */
13021
13022   switch (ffebld_op (expr))
13023     {
13024     case FFEBLD_opPERCENT_LOC:
13025       ffecom_prepare_ptr_to_expr (ffebld_left (expr));
13026       break;
13027
13028     case FFEBLD_opPERCENT_VAL:
13029     case FFEBLD_opPERCENT_REF:
13030       ffecom_prepare_expr (ffebld_left (expr));
13031       break;
13032
13033     case FFEBLD_opPERCENT_DESCR:
13034       ffecom_prepare_arg_ptr_to_expr (ffebld_left (expr));
13035       break;
13036
13037     case FFEBLD_opITEM:
13038       {
13039         ffebld item;
13040
13041         for (item = expr;
13042              item != NULL;
13043              item = ffebld_trail (item))
13044           if (ffebld_head (item) != NULL)
13045             ffecom_prepare_expr (ffebld_head (item));
13046       }
13047       break;
13048
13049     default:
13050       /* Need to handle character conversion specially.  */
13051       switch (ffebld_arity (expr))
13052         {
13053         case 2:
13054           ffecom_prepare_expr (ffebld_left (expr));
13055           ffecom_prepare_expr (ffebld_right (expr));
13056           break;
13057
13058         case 1:
13059           ffecom_prepare_expr (ffebld_left (expr));
13060           break;
13061
13062         default:
13063           break;
13064         }
13065     }
13066
13067   return;
13068 }
13069
13070 /* Prepare expression for reading and writing.
13071
13072    Like ffecom_prepare_expr, except for expressions to be evaluated
13073    via ffecom_expr_rw.  */
13074
13075 void
13076 ffecom_prepare_expr_rw (tree type, ffebld expr)
13077 {
13078   /* This is all we support for now.  */
13079   assert (type == NULL_TREE || type == ffecom_type_expr (expr));
13080
13081   /* ~~For now, it seems to be the same thing.  */
13082   ffecom_prepare_expr (expr);
13083   return;
13084 }
13085
13086 /* Prepare expression for writing.
13087
13088    Like ffecom_prepare_expr, except for expressions to be evaluated
13089    via ffecom_expr_w.  */
13090
13091 void
13092 ffecom_prepare_expr_w (tree type, ffebld expr)
13093 {
13094   /* This is all we support for now.  */
13095   assert (type == NULL_TREE || type == ffecom_type_expr (expr));
13096
13097   /* ~~For now, it seems to be the same thing.  */
13098   ffecom_prepare_expr (expr);
13099   return;
13100 }
13101
13102 /* Prepare expression for returning.
13103
13104    Like ffecom_prepare_expr, except for expressions to be evaluated
13105    via ffecom_return_expr.  */
13106
13107 void
13108 ffecom_prepare_return_expr (ffebld expr)
13109 {
13110   assert (current_binding_level->prep_state < 2);
13111
13112   if (ffecom_primary_entry_kind_ == FFEINFO_kindSUBROUTINE
13113       && ffecom_is_altreturning_
13114       && expr != NULL)
13115     ffecom_prepare_expr (expr);
13116 }
13117
13118 /* Prepare pointer to expression.
13119
13120    Like ffecom_prepare_expr, except for expressions to be evaluated
13121    via ffecom_ptr_to_expr.  */
13122
13123 void
13124 ffecom_prepare_ptr_to_expr (ffebld expr)
13125 {
13126   /* ~~For now, it seems to be the same thing.  */
13127   ffecom_prepare_expr (expr);
13128   return;
13129 }
13130
13131 /* Transform expression into constant pointer-to-expression tree.
13132
13133    If the expression can be transformed into a pointer-to-expression tree
13134    that is constant, that is done, and the tree returned.  Else NULL_TREE
13135    is returned.
13136
13137    That way, a caller can attempt to provide compile-time initialization
13138    of a variable and, if that fails, *then* choose to start a new block
13139    and resort to using temporaries, as appropriate.  */
13140
13141 tree
13142 ffecom_ptr_to_const_expr (ffebld expr)
13143 {
13144   if (! expr)
13145     return integer_zero_node;
13146
13147   if (ffebld_op (expr) == FFEBLD_opANY)
13148     return error_mark_node;
13149
13150   if (ffebld_arity (expr) == 0
13151       && (ffebld_op (expr) != FFEBLD_opSYMTER
13152           || ffebld_where (expr) == FFEINFO_whereCOMMON
13153           || ffebld_where (expr) == FFEINFO_whereGLOBAL
13154           || ffebld_where (expr) == FFEINFO_whereINTRINSIC))
13155     {
13156       tree t;
13157
13158       t = ffecom_ptr_to_expr (expr);
13159       assert (TREE_CONSTANT (t));
13160       return t;
13161     }
13162
13163   return NULL_TREE;
13164 }
13165
13166 /* ffecom_return_expr -- Returns return-value expr given alt return expr
13167
13168    tree rtn;  // NULL_TREE means use expand_null_return()
13169    ffebld expr;  // NULL if no alt return expr to RETURN stmt
13170    rtn = ffecom_return_expr(expr);
13171
13172    Based on the program unit type and other info (like return function
13173    type, return master function type when alternate ENTRY points,
13174    whether subroutine has any alternate RETURN points, etc), returns the
13175    appropriate expression to be returned to the caller, or NULL_TREE
13176    meaning no return value or the caller expects it to be returned somewhere
13177    else (which is handled by other parts of this module).  */
13178
13179 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13180 tree
13181 ffecom_return_expr (ffebld expr)
13182 {
13183   tree rtn;
13184
13185   switch (ffecom_primary_entry_kind_)
13186     {
13187     case FFEINFO_kindPROGRAM:
13188     case FFEINFO_kindBLOCKDATA:
13189       rtn = NULL_TREE;
13190       break;
13191
13192     case FFEINFO_kindSUBROUTINE:
13193       if (!ffecom_is_altreturning_)
13194         rtn = NULL_TREE;        /* No alt returns, never an expr. */
13195       else if (expr == NULL)
13196         rtn = integer_zero_node;
13197       else
13198         rtn = ffecom_expr (expr);
13199       break;
13200
13201     case FFEINFO_kindFUNCTION:
13202       if ((ffecom_multi_retval_ != NULL_TREE)
13203           || (ffesymbol_basictype (ffecom_primary_entry_)
13204               == FFEINFO_basictypeCHARACTER)
13205           || ((ffesymbol_basictype (ffecom_primary_entry_)
13206                == FFEINFO_basictypeCOMPLEX)
13207               && (ffecom_num_entrypoints_ == 0)
13208               && ffesymbol_is_f2c (ffecom_primary_entry_)))
13209         {                       /* Value is returned by direct assignment
13210                                    into (implicit) dummy. */
13211           rtn = NULL_TREE;
13212           break;
13213         }
13214       rtn = ffecom_func_result_;
13215 #if 0
13216       /* Spurious error if RETURN happens before first reference!  So elide
13217          this code.  In particular, for debugging registry, rtn should always
13218          be non-null after all, but TREE_USED won't be set until we encounter
13219          a reference in the code.  Perfectly okay (but weird) code that,
13220          e.g., has "GOTO 20;10 RETURN;20 RTN=0;GOTO 10", would result in
13221          this diagnostic for no reason.  Have people use -O -Wuninitialized
13222          and leave it to the back end to find obviously weird cases.  */
13223
13224       /* Used to "assert(rtn != NULL_TREE);" here, but it's kind of a valid
13225          situation; if the return value has never been referenced, it won't
13226          have a tree under 2pass mode. */
13227       if ((rtn == NULL_TREE)
13228           || !TREE_USED (rtn))
13229         {
13230           ffebad_start (FFEBAD_RETURN_VALUE_UNSET);
13231           ffebad_here (0, ffesymbol_where_line (ffecom_primary_entry_),
13232                        ffesymbol_where_column (ffecom_primary_entry_));
13233           ffebad_string (ffesymbol_text (ffesymbol_funcresult
13234                                          (ffecom_primary_entry_)));
13235           ffebad_finish ();
13236         }
13237 #endif
13238       break;
13239
13240     default:
13241       assert ("bad unit kind" == NULL);
13242     case FFEINFO_kindANY:
13243       rtn = error_mark_node;
13244       break;
13245     }
13246
13247   return rtn;
13248 }
13249
13250 #endif
13251 /* Do save_expr only if tree is not error_mark_node.  */
13252
13253 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13254 tree
13255 ffecom_save_tree (tree t)
13256 {
13257   return save_expr (t);
13258 }
13259 #endif
13260
13261 /* Start a compound statement (block).  */
13262
13263 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13264 void
13265 ffecom_start_compstmt (void)
13266 {
13267   bison_rule_pushlevel_ ();
13268 }
13269 #endif  /* FFECOM_targetCURRENT == FFECOM_targetGCC */
13270
13271 /* Public entry point for front end to access start_decl.  */
13272
13273 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13274 tree
13275 ffecom_start_decl (tree decl, bool is_initialized)
13276 {
13277   DECL_INITIAL (decl) = is_initialized ? error_mark_node : NULL_TREE;
13278   return start_decl (decl, FALSE);
13279 }
13280
13281 #endif
13282 /* ffecom_sym_commit -- Symbol's state being committed to reality
13283
13284    ffesymbol s;
13285    ffecom_sym_commit(s);
13286
13287    Does whatever the backend needs when a symbol is committed after having
13288    been backtrackable for a period of time.  */
13289
13290 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13291 void
13292 ffecom_sym_commit (ffesymbol s UNUSED)
13293 {
13294   assert (!ffesymbol_retractable ());
13295 }
13296
13297 #endif
13298 /* ffecom_sym_end_transition -- Perform end transition on all symbols
13299
13300    ffecom_sym_end_transition();
13301
13302    Does backend-specific stuff and also calls ffest_sym_end_transition
13303    to do the necessary FFE stuff.
13304
13305    Backtracking is never enabled when this fn is called, so don't worry
13306    about it.  */
13307
13308 ffesymbol
13309 ffecom_sym_end_transition (ffesymbol s)
13310 {
13311   ffestorag st;
13312
13313   assert (!ffesymbol_retractable ());
13314
13315   s = ffest_sym_end_transition (s);
13316
13317 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13318   if ((ffesymbol_kind (s) == FFEINFO_kindBLOCKDATA)
13319       && (ffesymbol_where (s) == FFEINFO_whereGLOBAL))
13320     {
13321       ffecom_list_blockdata_
13322         = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13323                                               FFEINTRIN_specNONE,
13324                                               FFEINTRIN_impNONE),
13325                            ffecom_list_blockdata_);
13326     }
13327 #endif
13328
13329   /* This is where we finally notice that a symbol has partial initialization
13330      and finalize it. */
13331
13332   if (ffesymbol_accretion (s) != NULL)
13333     {
13334       assert (ffesymbol_init (s) == NULL);
13335       ffecom_notify_init_symbol (s);
13336     }
13337   else if (((st = ffesymbol_storage (s)) != NULL)
13338            && ((st = ffestorag_parent (st)) != NULL)
13339            && (ffestorag_accretion (st) != NULL))
13340     {
13341       assert (ffestorag_init (st) == NULL);
13342       ffecom_notify_init_storage (st);
13343     }
13344
13345 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13346   if ((ffesymbol_kind (s) == FFEINFO_kindCOMMON)
13347       && (ffesymbol_where (s) == FFEINFO_whereLOCAL)
13348       && (ffesymbol_storage (s) != NULL))
13349     {
13350       ffecom_list_common_
13351         = ffebld_new_item (ffebld_new_symter (s, FFEINTRIN_genNONE,
13352                                               FFEINTRIN_specNONE,
13353                                               FFEINTRIN_impNONE),
13354                            ffecom_list_common_);
13355     }
13356 #endif
13357
13358   return s;
13359 }
13360
13361 /* ffecom_sym_exec_transition -- Perform exec transition on all symbols
13362
13363    ffecom_sym_exec_transition();
13364
13365    Does backend-specific stuff and also calls ffest_sym_exec_transition
13366    to do the necessary FFE stuff.
13367
13368    See the long-winded description in ffecom_sym_learned for info
13369    on handling the situation where backtracking is inhibited.  */
13370
13371 ffesymbol
13372 ffecom_sym_exec_transition (ffesymbol s)
13373 {
13374   s = ffest_sym_exec_transition (s);
13375
13376   return s;
13377 }
13378
13379 /* ffecom_sym_learned -- Initial or more info gained on symbol after exec
13380
13381    ffesymbol s;
13382    s = ffecom_sym_learned(s);
13383
13384    Called when a new symbol is seen after the exec transition or when more
13385    info (perhaps) is gained for an UNCERTAIN symbol.  The symbol state when
13386    it arrives here is that all its latest info is updated already, so its
13387    state may be UNCERTAIN or UNDERSTOOD, it might already have the hook
13388    field filled in if its gone through here or exec_transition first, and
13389    so on.
13390
13391    The backend probably wants to check ffesymbol_retractable() to see if
13392    backtracking is in effect.  If so, the FFE's changes to the symbol may
13393    be retracted (undone) or committed (ratified), at which time the
13394    appropriate ffecom_sym_retract or _commit function will be called
13395    for that function.
13396
13397    If the backend has its own backtracking mechanism, great, use it so that
13398    committal is a simple operation.  Though it doesn't make much difference,
13399    I suppose: the reason for tentative symbol evolution in the FFE is to
13400    enable error detection in weird incorrect statements early and to disable
13401    incorrect error detection on a correct statement.  The backend is not
13402    likely to introduce any information that'll get involved in these
13403    considerations, so it is probably just fine that the implementation
13404    model for this fn and for _exec_transition is to not do anything
13405    (besides the required FFE stuff) if ffesymbol_retractable() returns TRUE
13406    and instead wait until ffecom_sym_commit is called (which it never
13407    will be as long as we're using ambiguity-detecting statement analysis in
13408    the FFE, which we are initially to shake out the code, but don't depend
13409    on this), otherwise go ahead and do whatever is needed.
13410
13411    In essence, then, when this fn and _exec_transition get called while
13412    backtracking is enabled, a general mechanism would be to flag which (or
13413    both) of these were called (and in what order? neat question as to what
13414    might happen that I'm too lame to think through right now) and then when
13415    _commit is called reproduce the original calling sequence, if any, for
13416    the two fns (at which point backtracking will, of course, be disabled).  */
13417
13418 ffesymbol
13419 ffecom_sym_learned (ffesymbol s)
13420 {
13421   ffestorag_exec_layout (s);
13422
13423   return s;
13424 }
13425
13426 /* ffecom_sym_retract -- Symbol's state being retracted from reality
13427
13428    ffesymbol s;
13429    ffecom_sym_retract(s);
13430
13431    Does whatever the backend needs when a symbol is retracted after having
13432    been backtrackable for a period of time.  */
13433
13434 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13435 void
13436 ffecom_sym_retract (ffesymbol s UNUSED)
13437 {
13438   assert (!ffesymbol_retractable ());
13439
13440 #if 0                           /* GCC doesn't commit any backtrackable sins,
13441                                    so nothing needed here. */
13442   switch (ffesymbol_hook (s).state)
13443     {
13444     case 0:                     /* nothing happened yet. */
13445       break;
13446
13447     case 1:                     /* exec transition happened. */
13448       break;
13449
13450     case 2:                     /* learned happened. */
13451       break;
13452
13453     case 3:                     /* learned then exec. */
13454       break;
13455
13456     case 4:                     /* exec then learned. */
13457       break;
13458
13459     default:
13460       assert ("bad hook state" == NULL);
13461       break;
13462     }
13463 #endif
13464 }
13465
13466 #endif
13467 /* Create temporary gcc label.  */
13468
13469 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13470 tree
13471 ffecom_temp_label ()
13472 {
13473   tree glabel;
13474   static int mynumber = 0;
13475
13476   glabel = build_decl (LABEL_DECL,
13477                        ffecom_get_invented_identifier ("__g77_label_%d",
13478                                                        mynumber++),
13479                        void_type_node);
13480   DECL_CONTEXT (glabel) = current_function_decl;
13481   DECL_MODE (glabel) = VOIDmode;
13482
13483   return glabel;
13484 }
13485
13486 #endif
13487 /* Return an expression that is usable as an arg in a conditional context
13488    (IF, DO WHILE, .NOT., and so on).
13489
13490    Use the one provided for the back end as of >2.6.0.  */
13491
13492 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13493 tree
13494 ffecom_truth_value (tree expr)
13495 {
13496   return truthvalue_conversion (expr);
13497 }
13498
13499 #endif
13500 /* Return the inversion of a truth value (the inversion of what
13501    ffecom_truth_value builds).
13502
13503    Apparently invert_truthvalue, which is properly in the back end, is
13504    enough for now, so just use it.  */
13505
13506 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13507 tree
13508 ffecom_truth_value_invert (tree expr)
13509 {
13510   return invert_truthvalue (ffecom_truth_value (expr));
13511 }
13512
13513 #endif
13514
13515 /* Return the tree that is the type of the expression, as would be
13516    returned in TREE_TYPE(ffecom_expr(expr)), without otherwise
13517    transforming the expression, generating temporaries, etc.  */
13518
13519 tree
13520 ffecom_type_expr (ffebld expr)
13521 {
13522   ffeinfoBasictype bt;
13523   ffeinfoKindtype kt;
13524   tree tree_type;
13525
13526   assert (expr != NULL);
13527
13528   bt = ffeinfo_basictype (ffebld_info (expr));
13529   kt = ffeinfo_kindtype (ffebld_info (expr));
13530   tree_type = ffecom_tree_type[bt][kt];
13531
13532   switch (ffebld_op (expr))
13533     {
13534     case FFEBLD_opCONTER:
13535     case FFEBLD_opSYMTER:
13536     case FFEBLD_opARRAYREF:
13537     case FFEBLD_opUPLUS:
13538     case FFEBLD_opPAREN:
13539     case FFEBLD_opUMINUS:
13540     case FFEBLD_opADD:
13541     case FFEBLD_opSUBTRACT:
13542     case FFEBLD_opMULTIPLY:
13543     case FFEBLD_opDIVIDE:
13544     case FFEBLD_opPOWER:
13545     case FFEBLD_opNOT:
13546     case FFEBLD_opFUNCREF:
13547     case FFEBLD_opSUBRREF:
13548     case FFEBLD_opAND:
13549     case FFEBLD_opOR:
13550     case FFEBLD_opXOR:
13551     case FFEBLD_opNEQV:
13552     case FFEBLD_opEQV:
13553     case FFEBLD_opCONVERT:
13554     case FFEBLD_opLT:
13555     case FFEBLD_opLE:
13556     case FFEBLD_opEQ:
13557     case FFEBLD_opNE:
13558     case FFEBLD_opGT:
13559     case FFEBLD_opGE:
13560     case FFEBLD_opPERCENT_LOC:
13561       return tree_type;
13562
13563     case FFEBLD_opACCTER:
13564     case FFEBLD_opARRTER:
13565     case FFEBLD_opITEM:
13566     case FFEBLD_opSTAR:
13567     case FFEBLD_opBOUNDS:
13568     case FFEBLD_opREPEAT:
13569     case FFEBLD_opLABTER:
13570     case FFEBLD_opLABTOK:
13571     case FFEBLD_opIMPDO:
13572     case FFEBLD_opCONCATENATE:
13573     case FFEBLD_opSUBSTR:
13574     default:
13575       assert ("bad op for ffecom_type_expr" == NULL);
13576       /* Fall through. */
13577     case FFEBLD_opANY:
13578       return error_mark_node;
13579     }
13580 }
13581
13582 /* Return PARM_DECL for arg#1 of master fn containing alternate ENTRY points
13583
13584    If the PARM_DECL already exists, return it, else create it.  It's an
13585    integer_type_node argument for the master function that implements a
13586    subroutine or function with more than one entrypoint and is bound at
13587    run time with the entrypoint number (0 for SUBROUTINE/FUNCTION, 1 for
13588    first ENTRY statement, and so on).  */
13589
13590 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13591 tree
13592 ffecom_which_entrypoint_decl ()
13593 {
13594   assert (ffecom_which_entrypoint_decl_ != NULL_TREE);
13595
13596   return ffecom_which_entrypoint_decl_;
13597 }
13598
13599 #endif
13600 \f
13601 /* The following sections consists of private and public functions
13602    that have the same names and perform roughly the same functions
13603    as counterparts in the C front end.  Changes in the C front end
13604    might affect how things should be done here.  Only functions
13605    needed by the back end should be public here; the rest should
13606    be private (static in the C sense).  Functions needed by other
13607    g77 front-end modules should be accessed by them via public
13608    ffecom_* names, which should themselves call private versions
13609    in this section so the private versions are easy to recognize
13610    when upgrading to a new gcc and finding interesting changes
13611    in the front end.
13612
13613    Functions named after rule "foo:" in c-parse.y are named
13614    "bison_rule_foo_" so they are easy to find.  */
13615
13616 #if FFECOM_targetCURRENT == FFECOM_targetGCC
13617
13618 static void
13619 bison_rule_pushlevel_ ()
13620 {
13621   emit_line_note (input_filename, lineno);
13622   pushlevel (0);
13623   clear_last_expr ();
13624   push_momentary ();
13625   expand_start_bindings (0);
13626 }
13627
13628 static tree
13629 bison_rule_compstmt_ ()
13630 {
13631   tree t;
13632   int keep = kept_level_p ();
13633
13634   /* Make the temps go away.  */
13635   if (! keep)
13636     current_binding_level->names = NULL_TREE;
13637
13638   emit_line_note (input_filename, lineno);
13639   expand_end_bindings (getdecls (), keep, 0);
13640   t = poplevel (keep, 1, 0);
13641   pop_momentary ();
13642
13643   return t;
13644 }
13645
13646 /* Return a definition for a builtin function named NAME and whose data type
13647    is TYPE.  TYPE should be a function type with argument types.
13648    FUNCTION_CODE tells later passes how to compile calls to this function.
13649    See tree.h for its possible values.
13650
13651    If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
13652    the name to be called if we can't opencode the function.  */
13653
13654 tree
13655 builtin_function (const char *name, tree type, int function_code,
13656                   enum built_in_class class,
13657                   const char *library_name)
13658 {
13659   tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
13660   DECL_EXTERNAL (decl) = 1;
13661   TREE_PUBLIC (decl) = 1;
13662   if (library_name)
13663     DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
13664   make_decl_rtl (decl, NULL_PTR, 1);
13665   pushdecl (decl);
13666   DECL_BUILT_IN_CLASS (decl) = class;
13667   DECL_FUNCTION_CODE (decl) = function_code;
13668
13669   return decl;
13670 }
13671
13672 /* Handle when a new declaration NEWDECL
13673    has the same name as an old one OLDDECL
13674    in the same binding contour.
13675    Prints an error message if appropriate.
13676
13677    If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
13678    Otherwise, return 0.  */
13679
13680 static int
13681 duplicate_decls (tree newdecl, tree olddecl)
13682 {
13683   int types_match = 1;
13684   int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
13685                            && DECL_INITIAL (newdecl) != 0);
13686   tree oldtype = TREE_TYPE (olddecl);
13687   tree newtype = TREE_TYPE (newdecl);
13688
13689   if (olddecl == newdecl)
13690     return 1;
13691
13692   if (TREE_CODE (newtype) == ERROR_MARK
13693       || TREE_CODE (oldtype) == ERROR_MARK)
13694     types_match = 0;
13695
13696   /* New decl is completely inconsistent with the old one =>
13697      tell caller to replace the old one.
13698      This is always an error except in the case of shadowing a builtin.  */
13699   if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
13700     return 0;
13701
13702   /* For real parm decl following a forward decl,
13703      return 1 so old decl will be reused.  */
13704   if (types_match && TREE_CODE (newdecl) == PARM_DECL
13705       && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
13706     return 1;
13707
13708   /* The new declaration is the same kind of object as the old one.
13709      The declarations may partially match.  Print warnings if they don't
13710      match enough.  Ultimately, copy most of the information from the new
13711      decl to the old one, and keep using the old one.  */
13712
13713   if (TREE_CODE (olddecl) == FUNCTION_DECL
13714       && DECL_BUILT_IN (olddecl))
13715     {
13716       /* A function declaration for a built-in function.  */
13717       if (!TREE_PUBLIC (newdecl))
13718         return 0;
13719       else if (!types_match)
13720         {
13721           /* Accept the return type of the new declaration if same modes.  */
13722           tree oldreturntype = TREE_TYPE (TREE_TYPE (olddecl));
13723           tree newreturntype = TREE_TYPE (TREE_TYPE (newdecl));
13724
13725           if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
13726             {
13727               /* Function types may be shared, so we can't just modify
13728                  the return type of olddecl's function type.  */
13729               tree newtype
13730                 = build_function_type (newreturntype,
13731                                        TYPE_ARG_TYPES (TREE_TYPE (olddecl)));
13732
13733               types_match = 1;
13734               if (types_match)
13735                 TREE_TYPE (olddecl) = newtype;
13736             }
13737         }
13738       if (!types_match)
13739         return 0;
13740     }
13741   else if (TREE_CODE (olddecl) == FUNCTION_DECL
13742            && DECL_SOURCE_LINE (olddecl) == 0)
13743     {
13744       /* A function declaration for a predeclared function
13745          that isn't actually built in.  */
13746       if (!TREE_PUBLIC (newdecl))
13747         return 0;
13748       else if (!types_match)
13749         {
13750           /* If the types don't match, preserve volatility indication.
13751              Later on, we will discard everything else about the
13752              default declaration.  */
13753           TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
13754         }
13755     }
13756
13757   /* Copy all the DECL_... slots specified in the new decl
13758      except for any that we copy here from the old type.
13759
13760      Past this point, we don't change OLDTYPE and NEWTYPE
13761      even if we change the types of NEWDECL and OLDDECL.  */
13762
13763   if (types_match)
13764     {
13765       /* Merge the data types specified in the two decls.  */
13766       if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
13767         TREE_TYPE (newdecl)
13768           = TREE_TYPE (olddecl)
13769             = TREE_TYPE (newdecl);
13770
13771       /* Lay the type out, unless already done.  */
13772       if (oldtype != TREE_TYPE (newdecl))
13773         {
13774           if (TREE_TYPE (newdecl) != error_mark_node)
13775             layout_type (TREE_TYPE (newdecl));
13776           if (TREE_CODE (newdecl) != FUNCTION_DECL
13777               && TREE_CODE (newdecl) != TYPE_DECL
13778               && TREE_CODE (newdecl) != CONST_DECL)
13779             layout_decl (newdecl, 0);
13780         }
13781       else
13782         {
13783           /* Since the type is OLDDECL's, make OLDDECL's size go with.  */
13784           DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
13785           DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
13786           if (TREE_CODE (olddecl) != FUNCTION_DECL)
13787             if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
13788               DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
13789         }
13790
13791       /* Keep the old rtl since we can safely use it.  */
13792       DECL_RTL (newdecl) = DECL_RTL (olddecl);
13793
13794       /* Merge the type qualifiers.  */
13795       if (DECL_BUILT_IN_NONANSI (olddecl) && TREE_THIS_VOLATILE (olddecl)
13796           && !TREE_THIS_VOLATILE (newdecl))
13797         TREE_THIS_VOLATILE (olddecl) = 0;
13798       if (TREE_READONLY (newdecl))
13799         TREE_READONLY (olddecl) = 1;
13800       if (TREE_THIS_VOLATILE (newdecl))
13801         {
13802           TREE_THIS_VOLATILE (olddecl) = 1;
13803           if (TREE_CODE (newdecl) == VAR_DECL)
13804             make_var_volatile (newdecl);
13805         }
13806
13807       /* Keep source location of definition rather than declaration.
13808          Likewise, keep decl at outer scope.  */
13809       if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
13810           || (DECL_CONTEXT (newdecl) != 0 && DECL_CONTEXT (olddecl) == 0))
13811         {
13812           DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
13813           DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
13814
13815           if (DECL_CONTEXT (olddecl) == 0
13816               && TREE_CODE (newdecl) != FUNCTION_DECL)
13817             DECL_CONTEXT (newdecl) = 0;
13818         }
13819
13820       /* Merge the unused-warning information.  */
13821       if (DECL_IN_SYSTEM_HEADER (olddecl))
13822         DECL_IN_SYSTEM_HEADER (newdecl) = 1;
13823       else if (DECL_IN_SYSTEM_HEADER (newdecl))
13824         DECL_IN_SYSTEM_HEADER (olddecl) = 1;
13825
13826       /* Merge the initialization information.  */
13827       if (DECL_INITIAL (newdecl) == 0)
13828         DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13829
13830       /* Merge the section attribute.
13831          We want to issue an error if the sections conflict but that must be
13832          done later in decl_attributes since we are called before attributes
13833          are assigned.  */
13834       if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
13835         DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
13836
13837 #if BUILT_FOR_270
13838       if (TREE_CODE (newdecl) == FUNCTION_DECL)
13839         {
13840           DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
13841           DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
13842         }
13843 #endif
13844     }
13845   /* If cannot merge, then use the new type and qualifiers,
13846      and don't preserve the old rtl.  */
13847   else
13848     {
13849       TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13850       TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
13851       TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
13852       TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
13853     }
13854
13855   /* Merge the storage class information.  */
13856   /* For functions, static overrides non-static.  */
13857   if (TREE_CODE (newdecl) == FUNCTION_DECL)
13858     {
13859       TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
13860       /* This is since we don't automatically
13861          copy the attributes of NEWDECL into OLDDECL.  */
13862       TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13863       /* If this clears `static', clear it in the identifier too.  */
13864       if (! TREE_PUBLIC (olddecl))
13865         TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
13866     }
13867   if (DECL_EXTERNAL (newdecl))
13868     {
13869       TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
13870       DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
13871       /* An extern decl does not override previous storage class.  */
13872       TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
13873     }
13874   else
13875     {
13876       TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
13877       TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
13878     }
13879
13880   /* If either decl says `inline', this fn is inline,
13881      unless its definition was passed already.  */
13882   if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == 0)
13883     DECL_INLINE (olddecl) = 1;
13884   DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
13885
13886   /* Get rid of any built-in function if new arg types don't match it
13887      or if we have a function definition.  */
13888   if (TREE_CODE (newdecl) == FUNCTION_DECL
13889       && DECL_BUILT_IN (olddecl)
13890       && (!types_match || new_is_definition))
13891     {
13892       TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
13893       DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
13894     }
13895
13896   /* If redeclaring a builtin function, and not a definition,
13897      it stays built in.
13898      Also preserve various other info from the definition.  */
13899   if (TREE_CODE (newdecl) == FUNCTION_DECL && !new_is_definition)
13900     {
13901       if (DECL_BUILT_IN (olddecl))
13902         {
13903           DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
13904           DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
13905         }
13906       else
13907         DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
13908
13909       DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
13910       DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
13911       DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
13912       DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
13913     }
13914
13915   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
13916      But preserve olddecl's DECL_UID.  */
13917   {
13918     register unsigned olddecl_uid = DECL_UID (olddecl);
13919
13920     memcpy ((char *) olddecl + sizeof (struct tree_common),
13921             (char *) newdecl + sizeof (struct tree_common),
13922             sizeof (struct tree_decl) - sizeof (struct tree_common));
13923     DECL_UID (olddecl) = olddecl_uid;
13924   }
13925
13926   return 1;
13927 }
13928
13929 /* Finish processing of a declaration;
13930    install its initial value.
13931    If the length of an array type is not known before,
13932    it must be determined now, from the initial value, or it is an error.  */
13933
13934 static void
13935 finish_decl (tree decl, tree init, bool is_top_level)
13936 {
13937   register tree type = TREE_TYPE (decl);
13938   int was_incomplete = (DECL_SIZE (decl) == 0);
13939   int temporary = allocation_temporary_p ();
13940   bool at_top_level = (current_binding_level == global_binding_level);
13941   bool top_level = is_top_level || at_top_level;
13942
13943   /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
13944      level anyway.  */
13945   assert (!is_top_level || !at_top_level);
13946
13947   if (TREE_CODE (decl) == PARM_DECL)
13948     assert (init == NULL_TREE);
13949   /* Remember that PARM_DECL doesn't have a DECL_INITIAL field per se -- it
13950      overlaps DECL_ARG_TYPE.  */
13951   else if (init == NULL_TREE)
13952     assert (DECL_INITIAL (decl) == NULL_TREE);
13953   else
13954     assert (DECL_INITIAL (decl) == error_mark_node);
13955
13956   if (init != NULL_TREE)
13957     {
13958       if (TREE_CODE (decl) != TYPE_DECL)
13959         DECL_INITIAL (decl) = init;
13960       else
13961         {
13962           /* typedef foo = bar; store the type of bar as the type of foo.  */
13963           TREE_TYPE (decl) = TREE_TYPE (init);
13964           DECL_INITIAL (decl) = init = 0;
13965         }
13966     }
13967
13968   /* Pop back to the obstack that is current for this binding level. This is
13969      because MAXINDEX, rtl, etc. to be made below must go in the permanent
13970      obstack.  But don't discard the temporary data yet.  */
13971   pop_obstacks ();
13972
13973   /* Deduce size of array from initialization, if not already known */
13974
13975   if (TREE_CODE (type) == ARRAY_TYPE
13976       && TYPE_DOMAIN (type) == 0
13977       && TREE_CODE (decl) != TYPE_DECL)
13978     {
13979       assert (top_level);
13980       assert (was_incomplete);
13981
13982       layout_decl (decl, 0);
13983     }
13984
13985   if (TREE_CODE (decl) == VAR_DECL)
13986     {
13987       if (DECL_SIZE (decl) == NULL_TREE
13988           && TYPE_SIZE (TREE_TYPE (decl)) != NULL_TREE)
13989         layout_decl (decl, 0);
13990
13991       if (DECL_SIZE (decl) == NULL_TREE
13992           && (TREE_STATIC (decl)
13993               ?
13994       /* A static variable with an incomplete type is an error if it is
13995          initialized. Also if it is not file scope. Otherwise, let it
13996          through, but if it is not `extern' then it may cause an error
13997          message later.  */
13998               (DECL_INITIAL (decl) != 0 || DECL_CONTEXT (decl) != 0)
13999               :
14000       /* An automatic variable with an incomplete type is an error.  */
14001               !DECL_EXTERNAL (decl)))
14002         {
14003           assert ("storage size not known" == NULL);
14004           abort ();
14005         }
14006
14007       if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
14008           && (DECL_SIZE (decl) != 0)
14009           && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST))
14010         {
14011           assert ("storage size not constant" == NULL);
14012           abort ();
14013         }
14014     }
14015
14016   /* Output the assembler code and/or RTL code for variables and functions,
14017      unless the type is an undefined structure or union. If not, it will get
14018      done when the type is completed.  */
14019
14020   if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
14021     {
14022       rest_of_decl_compilation (decl, NULL,
14023                                 DECL_CONTEXT (decl) == 0,
14024                                 0);
14025
14026       if (DECL_CONTEXT (decl) != 0)
14027         {
14028           /* Recompute the RTL of a local array now if it used to be an
14029              incomplete type.  */
14030           if (was_incomplete
14031               && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
14032             {
14033               /* If we used it already as memory, it must stay in memory.  */
14034               TREE_ADDRESSABLE (decl) = TREE_USED (decl);
14035               /* If it's still incomplete now, no init will save it.  */
14036               if (DECL_SIZE (decl) == 0)
14037                 DECL_INITIAL (decl) = 0;
14038               expand_decl (decl);
14039             }
14040           /* Compute and store the initial value.  */
14041           if (TREE_CODE (decl) != FUNCTION_DECL)
14042             expand_decl_init (decl);
14043         }
14044     }
14045   else if (TREE_CODE (decl) == TYPE_DECL)
14046     {
14047       rest_of_decl_compilation (decl, NULL_PTR,
14048                                 DECL_CONTEXT (decl) == 0,
14049                                 0);
14050     }
14051
14052   if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
14053       && temporary
14054   /* DECL_INITIAL is not defined in PARM_DECLs, since it shares space with
14055      DECL_ARG_TYPE.  */
14056       && TREE_CODE (decl) != PARM_DECL)
14057     {
14058       /* We need to remember that this array HAD an initialization, but
14059          discard the actual temporary nodes, since we can't have a permanent
14060          node keep pointing to them.  */
14061       /* We make an exception for inline functions, since it's normal for a
14062          local extern redeclaration of an inline function to have a copy of
14063          the top-level decl's DECL_INLINE.  */
14064       if ((DECL_INITIAL (decl) != 0)
14065           && (DECL_INITIAL (decl) != error_mark_node))
14066         {
14067           /* If this is a const variable, then preserve the
14068              initializer instead of discarding it so that we can optimize
14069              references to it.  */
14070           /* This test used to include TREE_STATIC, but this won't be set
14071              for function level initializers.  */
14072           if (TREE_READONLY (decl))
14073             {
14074               preserve_initializer ();
14075
14076               /* The initializer and DECL must have the same (or equivalent
14077                  types), but if the initializer is a STRING_CST, its type
14078                  might not be on the right obstack, so copy the type
14079                  of DECL.  */
14080               TREE_TYPE (DECL_INITIAL (decl)) = type;
14081             }
14082           else
14083             DECL_INITIAL (decl) = error_mark_node;
14084         }
14085     }
14086
14087   /* If we have gone back from temporary to permanent allocation, actually
14088      free the temporary space that we no longer need.  */
14089   if (temporary && !allocation_temporary_p ())
14090     permanent_allocation (0);
14091
14092   /* At the end of a declaration, throw away any variable type sizes of types
14093      defined inside that declaration.  There is no use computing them in the
14094      following function definition.  */
14095   if (current_binding_level == global_binding_level)
14096     get_pending_sizes ();
14097 }
14098
14099 /* Finish up a function declaration and compile that function
14100    all the way to assembler language output.  The free the storage
14101    for the function definition.
14102
14103    This is called after parsing the body of the function definition.
14104
14105    NESTED is nonzero if the function being finished is nested in another.  */
14106
14107 static void
14108 finish_function (int nested)
14109 {
14110   register tree fndecl = current_function_decl;
14111
14112   assert (fndecl != NULL_TREE);
14113   if (TREE_CODE (fndecl) != ERROR_MARK)
14114     {
14115       if (nested)
14116         assert (DECL_CONTEXT (fndecl) != NULL_TREE);
14117       else
14118         assert (DECL_CONTEXT (fndecl) == NULL_TREE);
14119     }
14120
14121 /*  TREE_READONLY (fndecl) = 1;
14122     This caused &foo to be of type ptr-to-const-function
14123     which then got a warning when stored in a ptr-to-function variable.  */
14124
14125   poplevel (1, 0, 1);
14126
14127   if (TREE_CODE (fndecl) != ERROR_MARK)
14128     {
14129       BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
14130
14131       /* Must mark the RESULT_DECL as being in this function.  */
14132
14133       DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
14134
14135       /* Obey `register' declarations if `setjmp' is called in this fn.  */
14136       /* Generate rtl for function exit.  */
14137       expand_function_end (input_filename, lineno, 0);
14138
14139       /* So we can tell if jump_optimize sets it to 1.  */
14140       can_reach_end = 0;
14141
14142       /* If this is a nested function, protect the local variables in the stack
14143          above us from being collected while we're compiling this function.  */
14144       if (ggc_p && nested)
14145         ggc_push_context ();
14146
14147       /* Run the optimizers and output the assembler code for this function.  */
14148       rest_of_compilation (fndecl);
14149
14150       /* Undo the GC context switch.  */
14151       if (ggc_p && nested)
14152         ggc_pop_context ();
14153     }
14154
14155   /* Free all the tree nodes making up this function.  */
14156   /* Switch back to allocating nodes permanently until we start another
14157      function.  */
14158   if (!nested)
14159     permanent_allocation (1);
14160
14161   if (TREE_CODE (fndecl) != ERROR_MARK
14162       && !nested
14163       && DECL_SAVED_INSNS (fndecl) == 0)
14164     {
14165       /* Stop pointing to the local nodes about to be freed.  */
14166       /* But DECL_INITIAL must remain nonzero so we know this was an actual
14167          function definition.  */
14168       /* For a nested function, this is done in pop_f_function_context.  */
14169       /* If rest_of_compilation set this to 0, leave it 0.  */
14170       if (DECL_INITIAL (fndecl) != 0)
14171         DECL_INITIAL (fndecl) = error_mark_node;
14172       DECL_ARGUMENTS (fndecl) = 0;
14173     }
14174
14175   if (!nested)
14176     {
14177       /* Let the error reporting routines know that we're outside a function.
14178          For a nested function, this value is used in pop_c_function_context
14179          and then reset via pop_function_context.  */
14180       ffecom_outer_function_decl_ = current_function_decl = NULL;
14181     }
14182 }
14183
14184 /* Plug-in replacement for identifying the name of a decl and, for a
14185    function, what we call it in diagnostics.  For now, "program unit"
14186    should suffice, since it's a bit of a hassle to figure out which
14187    of several kinds of things it is.  Note that it could conceivably
14188    be a statement function, which probably isn't really a program unit
14189    per se, but if that comes up, it should be easy to check (being a
14190    nested function and all).  */
14191
14192 static const char *
14193 lang_printable_name (tree decl, int v)
14194 {
14195   /* Just to keep GCC quiet about the unused variable.
14196      In theory, differing values of V should produce different
14197      output.  */
14198   switch (v)
14199     {
14200     default:
14201       if (TREE_CODE (decl) == ERROR_MARK)
14202         return "erroneous code";
14203       return IDENTIFIER_POINTER (DECL_NAME (decl));
14204     }
14205 }
14206
14207 /* g77's function to print out name of current function that caused
14208    an error.  */
14209
14210 #if BUILT_FOR_270
14211 static void
14212 lang_print_error_function (const char *file)
14213 {
14214   static ffeglobal last_g = NULL;
14215   static ffesymbol last_s = NULL;
14216   ffeglobal g;
14217   ffesymbol s;
14218   const char *kind;
14219
14220   if ((ffecom_primary_entry_ == NULL)
14221       || (ffesymbol_global (ffecom_primary_entry_) == NULL))
14222     {
14223       g = NULL;
14224       s = NULL;
14225       kind = NULL;
14226     }
14227   else
14228     {
14229       g = ffesymbol_global (ffecom_primary_entry_);
14230       if (ffecom_nested_entry_ == NULL)
14231         {
14232           s = ffecom_primary_entry_;
14233           switch (ffesymbol_kind (s))
14234             {
14235             case FFEINFO_kindFUNCTION:
14236               kind = "function";
14237               break;
14238
14239             case FFEINFO_kindSUBROUTINE:
14240               kind = "subroutine";
14241               break;
14242
14243             case FFEINFO_kindPROGRAM:
14244               kind = "program";
14245               break;
14246
14247             case FFEINFO_kindBLOCKDATA:
14248               kind = "block-data";
14249               break;
14250
14251             default:
14252               kind = ffeinfo_kind_message (ffesymbol_kind (s));
14253               break;
14254             }
14255         }
14256       else
14257         {
14258           s = ffecom_nested_entry_;
14259           kind = "statement function";
14260         }
14261     }
14262
14263   if ((last_g != g) || (last_s != s))
14264     {
14265       if (file)
14266         fprintf (stderr, "%s: ", file);
14267
14268       if (s == NULL)
14269         fprintf (stderr, "Outside of any program unit:\n");
14270       else
14271         {
14272           const char *name = ffesymbol_text (s);
14273
14274           fprintf (stderr, "In %s `%s':\n", kind, name);
14275         }
14276
14277       last_g = g;
14278       last_s = s;
14279     }
14280 }
14281 #endif
14282
14283 /* Similar to `lookup_name' but look only at current binding level.  */
14284
14285 static tree
14286 lookup_name_current_level (tree name)
14287 {
14288   register tree t;
14289
14290   if (current_binding_level == global_binding_level)
14291     return IDENTIFIER_GLOBAL_VALUE (name);
14292
14293   if (IDENTIFIER_LOCAL_VALUE (name) == 0)
14294     return 0;
14295
14296   for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
14297     if (DECL_NAME (t) == name)
14298       break;
14299
14300   return t;
14301 }
14302
14303 /* Create a new `struct binding_level'.  */
14304
14305 static struct binding_level *
14306 make_binding_level ()
14307 {
14308   /* NOSTRICT */
14309   return (struct binding_level *) xmalloc (sizeof (struct binding_level));
14310 }
14311
14312 /* Save and restore the variables in this file and elsewhere
14313    that keep track of the progress of compilation of the current function.
14314    Used for nested functions.  */
14315
14316 struct f_function
14317 {
14318   struct f_function *next;
14319   tree named_labels;
14320   tree shadowed_labels;
14321   struct binding_level *binding_level;
14322 };
14323
14324 struct f_function *f_function_chain;
14325
14326 /* Restore the variables used during compilation of a C function.  */
14327
14328 static void
14329 pop_f_function_context ()
14330 {
14331   struct f_function *p = f_function_chain;
14332   tree link;
14333
14334   /* Bring back all the labels that were shadowed.  */
14335   for (link = shadowed_labels; link; link = TREE_CHAIN (link))
14336     if (DECL_NAME (TREE_VALUE (link)) != 0)
14337       IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
14338         = TREE_VALUE (link);
14339
14340   if (current_function_decl != error_mark_node
14341       && DECL_SAVED_INSNS (current_function_decl) == 0)
14342     {
14343       /* Stop pointing to the local nodes about to be freed.  */
14344       /* But DECL_INITIAL must remain nonzero so we know this was an actual
14345          function definition.  */
14346       DECL_INITIAL (current_function_decl) = error_mark_node;
14347       DECL_ARGUMENTS (current_function_decl) = 0;
14348     }
14349
14350   pop_function_context ();
14351
14352   f_function_chain = p->next;
14353
14354   named_labels = p->named_labels;
14355   shadowed_labels = p->shadowed_labels;
14356   current_binding_level = p->binding_level;
14357
14358   free (p);
14359 }
14360
14361 /* Save and reinitialize the variables
14362    used during compilation of a C function.  */
14363
14364 static void
14365 push_f_function_context ()
14366 {
14367   struct f_function *p
14368   = (struct f_function *) xmalloc (sizeof (struct f_function));
14369
14370   push_function_context ();
14371
14372   p->next = f_function_chain;
14373   f_function_chain = p;
14374
14375   p->named_labels = named_labels;
14376   p->shadowed_labels = shadowed_labels;
14377   p->binding_level = current_binding_level;
14378 }
14379
14380 static void
14381 push_parm_decl (tree parm)
14382 {
14383   int old_immediate_size_expand = immediate_size_expand;
14384
14385   /* Don't try computing parm sizes now -- wait till fn is called.  */
14386
14387   immediate_size_expand = 0;
14388
14389   push_obstacks_nochange ();
14390
14391   /* Fill in arg stuff.  */
14392
14393   DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
14394   DECL_ARG_TYPE_AS_WRITTEN (parm) = TREE_TYPE (parm);
14395   TREE_READONLY (parm) = 1;     /* All implementation args are read-only. */
14396
14397   parm = pushdecl (parm);
14398
14399   immediate_size_expand = old_immediate_size_expand;
14400
14401   finish_decl (parm, NULL_TREE, FALSE);
14402 }
14403
14404 /* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL, if appropriate.  */
14405
14406 static tree
14407 pushdecl_top_level (x)
14408      tree x;
14409 {
14410   register tree t;
14411   register struct binding_level *b = current_binding_level;
14412   register tree f = current_function_decl;
14413
14414   current_binding_level = global_binding_level;
14415   current_function_decl = NULL_TREE;
14416   t = pushdecl (x);
14417   current_binding_level = b;
14418   current_function_decl = f;
14419   return t;
14420 }
14421
14422 /* Store the list of declarations of the current level.
14423    This is done for the parameter declarations of a function being defined,
14424    after they are modified in the light of any missing parameters.  */
14425
14426 static tree
14427 storedecls (decls)
14428      tree decls;
14429 {
14430   return current_binding_level->names = decls;
14431 }
14432
14433 /* Store the parameter declarations into the current function declaration.
14434    This is called after parsing the parameter declarations, before
14435    digesting the body of the function.
14436
14437    For an old-style definition, modify the function's type
14438    to specify at least the number of arguments.  */
14439
14440 static void
14441 store_parm_decls (int is_main_program UNUSED)
14442 {
14443   register tree fndecl = current_function_decl;
14444
14445   if (fndecl == error_mark_node)
14446     return;
14447
14448   /* This is a chain of PARM_DECLs from old-style parm declarations.  */
14449   DECL_ARGUMENTS (fndecl) = storedecls (nreverse (getdecls ()));
14450
14451   /* Initialize the RTL code for the function.  */
14452
14453   init_function_start (fndecl, input_filename, lineno);
14454
14455   /* Set up parameters and prepare for return, for the function.  */
14456
14457   expand_function_start (fndecl, 0);
14458 }
14459
14460 static tree
14461 start_decl (tree decl, bool is_top_level)
14462 {
14463   register tree tem;
14464   bool at_top_level = (current_binding_level == global_binding_level);
14465   bool top_level = is_top_level || at_top_level;
14466
14467   /* Caller should pass TRUE for is_top_level only if we wouldn't be at top
14468      level anyway.  */
14469   assert (!is_top_level || !at_top_level);
14470
14471   /* The corresponding pop_obstacks is in finish_decl.  */
14472   push_obstacks_nochange ();
14473
14474   if (DECL_INITIAL (decl) != NULL_TREE)
14475     {
14476       assert (DECL_INITIAL (decl) == error_mark_node);
14477       assert (!DECL_EXTERNAL (decl));
14478     }
14479   else if (top_level)
14480     assert ((TREE_STATIC (decl) == 1) || DECL_EXTERNAL (decl) == 1);
14481
14482   /* For Fortran, we by default put things in .common when possible.  */
14483   DECL_COMMON (decl) = 1;
14484
14485   /* Add this decl to the current binding level. TEM may equal DECL or it may
14486      be a previous decl of the same name.  */
14487   if (is_top_level)
14488     tem = pushdecl_top_level (decl);
14489   else
14490     tem = pushdecl (decl);
14491
14492   /* For a local variable, define the RTL now.  */
14493   if (!top_level
14494   /* But not if this is a duplicate decl and we preserved the rtl from the
14495      previous one (which may or may not happen).  */
14496       && DECL_RTL (tem) == 0)
14497     {
14498       if (TYPE_SIZE (TREE_TYPE (tem)) != 0)
14499         expand_decl (tem);
14500       else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
14501                && DECL_INITIAL (tem) != 0)
14502         expand_decl (tem);
14503     }
14504
14505   if (DECL_INITIAL (tem) != NULL_TREE)
14506     {
14507       /* When parsing and digesting the initializer, use temporary storage.
14508          Do this even if we will ignore the value.  */
14509       if (at_top_level)
14510         temporary_allocation ();
14511     }
14512
14513   return tem;
14514 }
14515
14516 /* Create the FUNCTION_DECL for a function definition.
14517    DECLSPECS and DECLARATOR are the parts of the declaration;
14518    they describe the function's name and the type it returns,
14519    but twisted together in a fashion that parallels the syntax of C.
14520
14521    This function creates a binding context for the function body
14522    as well as setting up the FUNCTION_DECL in current_function_decl.
14523
14524    Returns 1 on success.  If the DECLARATOR is not suitable for a function
14525    (it defines a datum instead), we return 0, which tells
14526    yyparse to report a parse error.
14527
14528    NESTED is nonzero for a function nested within another function.  */
14529
14530 static void
14531 start_function (tree name, tree type, int nested, int public)
14532 {
14533   tree decl1;
14534   tree restype;
14535   int old_immediate_size_expand = immediate_size_expand;
14536
14537   named_labels = 0;
14538   shadowed_labels = 0;
14539
14540   /* Don't expand any sizes in the return type of the function.  */
14541   immediate_size_expand = 0;
14542
14543   if (nested)
14544     {
14545       assert (!public);
14546       assert (current_function_decl != NULL_TREE);
14547       assert (DECL_CONTEXT (current_function_decl) == NULL_TREE);
14548     }
14549   else
14550     {
14551       assert (current_function_decl == NULL_TREE);
14552     }
14553
14554   if (TREE_CODE (type) == ERROR_MARK)
14555     decl1 = current_function_decl = error_mark_node;
14556   else
14557     {
14558       decl1 = build_decl (FUNCTION_DECL,
14559                           name,
14560                           type);
14561       TREE_PUBLIC (decl1) = public ? 1 : 0;
14562       if (nested)
14563         DECL_INLINE (decl1) = 1;
14564       TREE_STATIC (decl1) = 1;
14565       DECL_EXTERNAL (decl1) = 0;
14566
14567       announce_function (decl1);
14568
14569       /* Make the init_value nonzero so pushdecl knows this is not tentative.
14570          error_mark_node is replaced below (in poplevel) with the BLOCK.  */
14571       DECL_INITIAL (decl1) = error_mark_node;
14572
14573       /* Record the decl so that the function name is defined. If we already have
14574          a decl for this name, and it is a FUNCTION_DECL, use the old decl.  */
14575
14576       current_function_decl = pushdecl (decl1);
14577     }
14578
14579   if (!nested)
14580     ffecom_outer_function_decl_ = current_function_decl;
14581
14582   pushlevel (0);
14583   current_binding_level->prep_state = 2;
14584
14585   if (TREE_CODE (current_function_decl) != ERROR_MARK)
14586     {
14587       make_function_rtl (current_function_decl);
14588
14589       restype = TREE_TYPE (TREE_TYPE (current_function_decl));
14590       DECL_RESULT (current_function_decl)
14591         = build_decl (RESULT_DECL, NULL_TREE, restype);
14592     }
14593
14594   if (!nested)
14595     /* Allocate further tree nodes temporarily during compilation of this
14596        function only.  */
14597     temporary_allocation ();
14598
14599   if (!nested && (TREE_CODE (current_function_decl) != ERROR_MARK))
14600     TREE_ADDRESSABLE (current_function_decl) = 1;
14601
14602   immediate_size_expand = old_immediate_size_expand;
14603 }
14604 \f
14605 /* Here are the public functions the GNU back end needs.  */
14606
14607 tree
14608 convert (type, expr)
14609      tree type, expr;
14610 {
14611   register tree e = expr;
14612   register enum tree_code code = TREE_CODE (type);
14613
14614   if (type == TREE_TYPE (e)
14615       || TREE_CODE (e) == ERROR_MARK)
14616     return e;
14617   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
14618     return fold (build1 (NOP_EXPR, type, e));
14619   if (TREE_CODE (TREE_TYPE (e)) == ERROR_MARK
14620       || code == ERROR_MARK)
14621     return error_mark_node;
14622   if (TREE_CODE (TREE_TYPE (e)) == VOID_TYPE)
14623     {
14624       assert ("void value not ignored as it ought to be" == NULL);
14625       return error_mark_node;
14626     }
14627   if (code == VOID_TYPE)
14628     return build1 (CONVERT_EXPR, type, e);
14629   if ((code != RECORD_TYPE)
14630       && (TREE_CODE (TREE_TYPE (e)) == RECORD_TYPE))
14631     e = ffecom_1 (REALPART_EXPR, TREE_TYPE (TYPE_FIELDS (TREE_TYPE (e))),
14632                   e);
14633   if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
14634     return fold (convert_to_integer (type, e));
14635   if (code == POINTER_TYPE)
14636     return fold (convert_to_pointer (type, e));
14637   if (code == REAL_TYPE)
14638     return fold (convert_to_real (type, e));
14639   if (code == COMPLEX_TYPE)
14640     return fold (convert_to_complex (type, e));
14641   if (code == RECORD_TYPE)
14642     return fold (ffecom_convert_to_complex_ (type, e));
14643
14644   assert ("conversion to non-scalar type requested" == NULL);
14645   return error_mark_node;
14646 }
14647
14648 /* integrate_decl_tree calls this function, but since we don't use the
14649    DECL_LANG_SPECIFIC field, this is a no-op.  */
14650
14651 void
14652 copy_lang_decl (node)
14653      tree node UNUSED;
14654 {
14655 }
14656
14657 /* Return the list of declarations of the current level.
14658    Note that this list is in reverse order unless/until
14659    you nreverse it; and when you do nreverse it, you must
14660    store the result back using `storedecls' or you will lose.  */
14661
14662 tree
14663 getdecls ()
14664 {
14665   return current_binding_level->names;
14666 }
14667
14668 /* Nonzero if we are currently in the global binding level.  */
14669
14670 int
14671 global_bindings_p ()
14672 {
14673   return current_binding_level == global_binding_level;
14674 }
14675
14676 /* Print an error message for invalid use of an incomplete type.
14677    VALUE is the expression that was used (or 0 if that isn't known)
14678    and TYPE is the type that was invalid.  */
14679
14680 void
14681 incomplete_type_error (value, type)
14682      tree value UNUSED;
14683      tree type;
14684 {
14685   if (TREE_CODE (type) == ERROR_MARK)
14686     return;
14687
14688   assert ("incomplete type?!?" == NULL);
14689 }
14690
14691 /* Mark ARG for GC.  */
14692 static void 
14693 mark_binding_level (void *arg)
14694 {
14695   struct binding_level *level = *(struct binding_level **) arg;
14696
14697   while (level)
14698     {
14699       ggc_mark_tree (level->names);
14700       ggc_mark_tree (level->blocks);
14701       ggc_mark_tree (level->this_block);
14702       level = level->level_chain;
14703     }
14704 }
14705
14706 void
14707 init_decl_processing ()
14708 {
14709   static tree *const tree_roots[] = {
14710     &current_function_decl,
14711     &string_type_node,
14712     &ffecom_tree_fun_type_void,
14713     &ffecom_integer_zero_node,
14714     &ffecom_integer_one_node,
14715     &ffecom_tree_subr_type,
14716     &ffecom_tree_ptr_to_subr_type,
14717     &ffecom_tree_blockdata_type,
14718     &ffecom_tree_xargc_,
14719     &ffecom_f2c_integer_type_node,
14720     &ffecom_f2c_ptr_to_integer_type_node,
14721     &ffecom_f2c_address_type_node,
14722     &ffecom_f2c_real_type_node,
14723     &ffecom_f2c_ptr_to_real_type_node,
14724     &ffecom_f2c_doublereal_type_node,
14725     &ffecom_f2c_complex_type_node,
14726     &ffecom_f2c_doublecomplex_type_node,
14727     &ffecom_f2c_longint_type_node,
14728     &ffecom_f2c_logical_type_node,
14729     &ffecom_f2c_flag_type_node,
14730     &ffecom_f2c_ftnlen_type_node,
14731     &ffecom_f2c_ftnlen_zero_node,
14732     &ffecom_f2c_ftnlen_one_node,
14733     &ffecom_f2c_ftnlen_two_node,
14734     &ffecom_f2c_ptr_to_ftnlen_type_node,
14735     &ffecom_f2c_ftnint_type_node,
14736     &ffecom_f2c_ptr_to_ftnint_type_node,
14737     &ffecom_outer_function_decl_,
14738     &ffecom_previous_function_decl_,
14739     &ffecom_which_entrypoint_decl_,
14740     &ffecom_float_zero_,
14741     &ffecom_float_half_,
14742     &ffecom_double_zero_,
14743     &ffecom_double_half_,
14744     &ffecom_func_result_,
14745     &ffecom_func_length_,
14746     &ffecom_multi_type_node_,
14747     &ffecom_multi_retval_,
14748     &named_labels,
14749     &shadowed_labels
14750   };
14751   size_t i;
14752
14753   malloc_init ();
14754
14755   /* Record our roots.  */
14756   for (i = 0; i < sizeof(tree_roots)/sizeof(tree_roots[0]); i++)
14757     ggc_add_tree_root (tree_roots[i], 1);
14758   ggc_add_tree_root (&ffecom_tree_type[0][0], 
14759                      FFEINFO_basictype*FFEINFO_kindtype);
14760   ggc_add_tree_root (&ffecom_tree_fun_type[0][0], 
14761                      FFEINFO_basictype*FFEINFO_kindtype);
14762   ggc_add_tree_root (&ffecom_tree_ptr_to_fun_type[0][0], 
14763                      FFEINFO_basictype*FFEINFO_kindtype);
14764   ggc_add_tree_root (ffecom_gfrt_, FFECOM_gfrt);
14765   ggc_add_root (&current_binding_level, 1, sizeof current_binding_level,
14766                 mark_binding_level);
14767   ggc_add_root (&free_binding_level, 1, sizeof current_binding_level,
14768                 mark_binding_level);
14769   ggc_add_root (&tracker_head, 1, sizeof tracker_head, mark_tracker_head);
14770
14771   ffe_init_0 ();
14772 }
14773
14774 char *
14775 init_parse (filename)
14776      char *filename;
14777 {
14778   /* Open input file.  */
14779   if (filename == 0 || !strcmp (filename, "-"))
14780     {
14781       finput = stdin;
14782       filename = "stdin";
14783     }
14784   else
14785     finput = fopen (filename, "r");
14786   if (finput == 0)
14787     pfatal_with_name (filename);
14788
14789 #ifdef IO_BUFFER_SIZE
14790   setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
14791 #endif
14792
14793   /* Make identifier nodes long enough for the language-specific slots.  */
14794   set_identifier_size (sizeof (struct lang_identifier));
14795   decl_printable_name = lang_printable_name;
14796 #if BUILT_FOR_270
14797   print_error_function = lang_print_error_function;
14798 #endif
14799
14800   return filename;
14801 }
14802
14803 void
14804 finish_parse ()
14805 {
14806   fclose (finput);
14807 }
14808
14809 /* Delete the node BLOCK from the current binding level.
14810    This is used for the block inside a stmt expr ({...})
14811    so that the block can be reinserted where appropriate.  */
14812
14813 static void
14814 delete_block (block)
14815      tree block;
14816 {
14817   tree t;
14818   if (current_binding_level->blocks == block)
14819     current_binding_level->blocks = TREE_CHAIN (block);
14820   for (t = current_binding_level->blocks; t;)
14821     {
14822       if (TREE_CHAIN (t) == block)
14823         TREE_CHAIN (t) = TREE_CHAIN (block);
14824       else
14825         t = TREE_CHAIN (t);
14826     }
14827   TREE_CHAIN (block) = NULL;
14828   /* Clear TREE_USED which is always set by poplevel.
14829      The flag is set again if insert_block is called.  */
14830   TREE_USED (block) = 0;
14831 }
14832
14833 void
14834 insert_block (block)
14835      tree block;
14836 {
14837   TREE_USED (block) = 1;
14838   current_binding_level->blocks
14839     = chainon (current_binding_level->blocks, block);
14840 }
14841
14842 int
14843 lang_decode_option (argc, argv)
14844      int argc;
14845      char **argv;
14846 {
14847   return ffe_decode_option (argc, argv);
14848 }
14849
14850 /* used by print-tree.c */
14851
14852 void
14853 lang_print_xnode (file, node, indent)
14854      FILE *file UNUSED;
14855      tree node UNUSED;
14856      int indent UNUSED;
14857 {
14858 }
14859
14860 void
14861 lang_finish ()
14862 {
14863   ffe_terminate_0 ();
14864
14865   if (ffe_is_ffedebug ())
14866     malloc_pool_display (malloc_pool_image ());
14867 }
14868
14869 const char *
14870 lang_identify ()
14871 {
14872   return "f77";
14873 }
14874
14875 void
14876 lang_init_options ()
14877 {
14878   /* Set default options for Fortran.  */
14879   flag_move_all_movables = 1;
14880   flag_reduce_all_givs = 1;
14881   flag_argument_noalias = 2;
14882   flag_errno_math = 0;
14883   flag_complex_divide_method = 1;
14884 }
14885
14886 void
14887 lang_init ()
14888 {
14889   /* If the file is output from cpp, it should contain a first line
14890      `# 1 "real-filename"', and the current design of gcc (toplev.c
14891      in particular and the way it sets up information relied on by
14892      INCLUDE) requires that we read this now, and store the
14893      "real-filename" info in master_input_filename.  Ask the lexer
14894      to try doing this.  */
14895   ffelex_hash_kludge (finput);
14896 }
14897
14898 int
14899 mark_addressable (exp)
14900      tree exp;
14901 {
14902   register tree x = exp;
14903   while (1)
14904     switch (TREE_CODE (x))
14905       {
14906       case ADDR_EXPR:
14907       case COMPONENT_REF:
14908       case ARRAY_REF:
14909         x = TREE_OPERAND (x, 0);
14910         break;
14911
14912       case CONSTRUCTOR:
14913         TREE_ADDRESSABLE (x) = 1;
14914         return 1;
14915
14916       case VAR_DECL:
14917       case CONST_DECL:
14918       case PARM_DECL:
14919       case RESULT_DECL:
14920         if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
14921             && DECL_NONLOCAL (x))
14922           {
14923             if (TREE_PUBLIC (x))
14924               {
14925                 assert ("address of global register var requested" == NULL);
14926                 return 0;
14927               }
14928             assert ("address of register variable requested" == NULL);
14929           }
14930         else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x))
14931           {
14932             if (TREE_PUBLIC (x))
14933               {
14934                 assert ("address of global register var requested" == NULL);
14935                 return 0;
14936               }
14937             assert ("address of register var requested" == NULL);
14938           }
14939         put_var_into_stack (x);
14940
14941         /* drops in */
14942       case FUNCTION_DECL:
14943         TREE_ADDRESSABLE (x) = 1;
14944 #if 0                           /* poplevel deals with this now.  */
14945         if (DECL_CONTEXT (x) == 0)
14946           TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
14947 #endif
14948
14949       default:
14950         return 1;
14951       }
14952 }
14953
14954 /* If DECL has a cleanup, build and return that cleanup here.
14955    This is a callback called by expand_expr.  */
14956
14957 tree
14958 maybe_build_cleanup (decl)
14959      tree decl UNUSED;
14960 {
14961   /* There are no cleanups in Fortran.  */
14962   return NULL_TREE;
14963 }
14964
14965 /* Exit a binding level.
14966    Pop the level off, and restore the state of the identifier-decl mappings
14967    that were in effect when this level was entered.
14968
14969    If KEEP is nonzero, this level had explicit declarations, so
14970    and create a "block" (a BLOCK node) for the level
14971    to record its declarations and subblocks for symbol table output.
14972
14973    If FUNCTIONBODY is nonzero, this level is the body of a function,
14974    so create a block as if KEEP were set and also clear out all
14975    label names.
14976
14977    If REVERSE is nonzero, reverse the order of decls before putting
14978    them into the BLOCK.  */
14979
14980 tree
14981 poplevel (keep, reverse, functionbody)
14982      int keep;
14983      int reverse;
14984      int functionbody;
14985 {
14986   register tree link;
14987   /* The chain of decls was accumulated in reverse order.
14988      Put it into forward order, just for cleanliness.  */
14989   tree decls;
14990   tree subblocks = current_binding_level->blocks;
14991   tree block = 0;
14992   tree decl;
14993   int block_previously_created;
14994
14995   /* Get the decls in the order they were written.
14996      Usually current_binding_level->names is in reverse order.
14997      But parameter decls were previously put in forward order.  */
14998
14999   if (reverse)
15000     current_binding_level->names
15001       = decls = nreverse (current_binding_level->names);
15002   else
15003     decls = current_binding_level->names;
15004
15005   /* Output any nested inline functions within this block
15006      if they weren't already output.  */
15007
15008   for (decl = decls; decl; decl = TREE_CHAIN (decl))
15009     if (TREE_CODE (decl) == FUNCTION_DECL
15010         && ! TREE_ASM_WRITTEN (decl)
15011         && DECL_INITIAL (decl) != 0
15012         && TREE_ADDRESSABLE (decl))
15013       {
15014         /* If this decl was copied from a file-scope decl
15015            on account of a block-scope extern decl,
15016            propagate TREE_ADDRESSABLE to the file-scope decl.
15017
15018            DECL_ABSTRACT_ORIGIN can be set to itself if warn_return_type is
15019            true, since then the decl goes through save_for_inline_copying.  */
15020         if (DECL_ABSTRACT_ORIGIN (decl) != 0
15021             && DECL_ABSTRACT_ORIGIN (decl) != decl)
15022           TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
15023         else if (DECL_SAVED_INSNS (decl) != 0)
15024           {
15025             push_function_context ();
15026             output_inline_function (decl);
15027             pop_function_context ();
15028           }
15029       }
15030
15031   /* If there were any declarations or structure tags in that level,
15032      or if this level is a function body,
15033      create a BLOCK to record them for the life of this function.  */
15034
15035   block = 0;
15036   block_previously_created = (current_binding_level->this_block != 0);
15037   if (block_previously_created)
15038     block = current_binding_level->this_block;
15039   else if (keep || functionbody)
15040     block = make_node (BLOCK);
15041   if (block != 0)
15042     {
15043       BLOCK_VARS (block) = decls;
15044       BLOCK_SUBBLOCKS (block) = subblocks;
15045     }
15046
15047   /* In each subblock, record that this is its superior.  */
15048
15049   for (link = subblocks; link; link = TREE_CHAIN (link))
15050     BLOCK_SUPERCONTEXT (link) = block;
15051
15052   /* Clear out the meanings of the local variables of this level.  */
15053
15054   for (link = decls; link; link = TREE_CHAIN (link))
15055     {
15056       if (DECL_NAME (link) != 0)
15057         {
15058           /* If the ident. was used or addressed via a local extern decl,
15059              don't forget that fact.  */
15060           if (DECL_EXTERNAL (link))
15061             {
15062               if (TREE_USED (link))
15063                 TREE_USED (DECL_NAME (link)) = 1;
15064               if (TREE_ADDRESSABLE (link))
15065                 TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
15066             }
15067           IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
15068         }
15069     }
15070
15071   /* If the level being exited is the top level of a function,
15072      check over all the labels, and clear out the current
15073      (function local) meanings of their names.  */
15074
15075   if (functionbody)
15076     {
15077       /* If this is the top level block of a function,
15078          the vars are the function's parameters.
15079          Don't leave them in the BLOCK because they are
15080          found in the FUNCTION_DECL instead.  */
15081
15082       BLOCK_VARS (block) = 0;
15083     }
15084
15085   /* Pop the current level, and free the structure for reuse.  */
15086
15087   {
15088     register struct binding_level *level = current_binding_level;
15089     current_binding_level = current_binding_level->level_chain;
15090
15091     level->level_chain = free_binding_level;
15092     free_binding_level = level;
15093   }
15094
15095   /* Dispose of the block that we just made inside some higher level.  */
15096   if (functionbody
15097       && current_function_decl != error_mark_node)
15098     DECL_INITIAL (current_function_decl) = block;
15099   else if (block)
15100     {
15101       if (!block_previously_created)
15102         current_binding_level->blocks
15103           = chainon (current_binding_level->blocks, block);
15104     }
15105   /* If we did not make a block for the level just exited,
15106      any blocks made for inner levels
15107      (since they cannot be recorded as subblocks in that level)
15108      must be carried forward so they will later become subblocks
15109      of something else.  */
15110   else if (subblocks)
15111     current_binding_level->blocks
15112       = chainon (current_binding_level->blocks, subblocks);
15113
15114   if (block)
15115     TREE_USED (block) = 1;
15116   return block;
15117 }
15118
15119 void
15120 print_lang_decl (file, node, indent)
15121      FILE *file UNUSED;
15122      tree node UNUSED;
15123      int indent UNUSED;
15124 {
15125 }
15126
15127 void
15128 print_lang_identifier (file, node, indent)
15129      FILE *file;
15130      tree node;
15131      int indent;
15132 {
15133   print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
15134   print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
15135 }
15136
15137 void
15138 print_lang_statistics ()
15139 {
15140 }
15141
15142 void
15143 print_lang_type (file, node, indent)
15144      FILE *file UNUSED;
15145      tree node UNUSED;
15146      int indent UNUSED;
15147 {
15148 }
15149
15150 /* Record a decl-node X as belonging to the current lexical scope.
15151    Check for errors (such as an incompatible declaration for the same
15152    name already seen in the same scope).
15153
15154    Returns either X or an old decl for the same name.
15155    If an old decl is returned, it may have been smashed
15156    to agree with what X says.  */
15157
15158 tree
15159 pushdecl (x)
15160      tree x;
15161 {
15162   register tree t;
15163   register tree name = DECL_NAME (x);
15164   register struct binding_level *b = current_binding_level;
15165
15166   if ((TREE_CODE (x) == FUNCTION_DECL)
15167       && (DECL_INITIAL (x) == 0)
15168       && DECL_EXTERNAL (x))
15169     DECL_CONTEXT (x) = NULL_TREE;
15170   else
15171     DECL_CONTEXT (x) = current_function_decl;
15172
15173   if (name)
15174     {
15175       if (IDENTIFIER_INVENTED (name))
15176         {
15177 #if BUILT_FOR_270
15178           DECL_ARTIFICIAL (x) = 1;
15179 #endif
15180           DECL_IN_SYSTEM_HEADER (x) = 1;
15181         }
15182
15183       t = lookup_name_current_level (name);
15184
15185       assert ((t == NULL_TREE) || (DECL_CONTEXT (x) == NULL_TREE));
15186
15187       /* Don't push non-parms onto list for parms until we understand
15188          why we're doing this and whether it works.  */
15189
15190       assert ((b == global_binding_level)
15191               || !ffecom_transform_only_dummies_
15192               || TREE_CODE (x) == PARM_DECL);
15193
15194       if ((t != NULL_TREE) && duplicate_decls (x, t))
15195         return t;
15196
15197       /* If we are processing a typedef statement, generate a whole new
15198          ..._TYPE node (which will be just an variant of the existing
15199          ..._TYPE node with identical properties) and then install the
15200          TYPE_DECL node generated to represent the typedef name as the
15201          TYPE_NAME of this brand new (duplicate) ..._TYPE node.
15202
15203          The whole point here is to end up with a situation where each and every
15204          ..._TYPE node the compiler creates will be uniquely associated with
15205          AT MOST one node representing a typedef name. This way, even though
15206          the compiler substitutes corresponding ..._TYPE nodes for TYPE_DECL
15207          (i.e. "typedef name") nodes very early on, later parts of the
15208          compiler can always do the reverse translation and get back the
15209          corresponding typedef name.  For example, given:
15210
15211          typedef struct S MY_TYPE; MY_TYPE object;
15212
15213          Later parts of the compiler might only know that `object' was of type
15214          `struct S' if it were not for code just below.  With this code
15215          however, later parts of the compiler see something like:
15216
15217          struct S' == struct S typedef struct S' MY_TYPE; struct S' object;
15218
15219          And they can then deduce (from the node for type struct S') that the
15220          original object declaration was:
15221
15222          MY_TYPE object;
15223
15224          Being able to do this is important for proper support of protoize, and
15225          also for generating precise symbolic debugging information which
15226          takes full account of the programmer's (typedef) vocabulary.
15227
15228          Obviously, we don't want to generate a duplicate ..._TYPE node if the
15229          TYPE_DECL node that we are now processing really represents a
15230          standard built-in type.
15231
15232          Since all standard types are effectively declared at line zero in the
15233          source file, we can easily check to see if we are working on a
15234          standard type by checking the current value of lineno.  */
15235
15236       if (TREE_CODE (x) == TYPE_DECL)
15237         {
15238           if (DECL_SOURCE_LINE (x) == 0)
15239             {
15240               if (TYPE_NAME (TREE_TYPE (x)) == 0)
15241                 TYPE_NAME (TREE_TYPE (x)) = x;
15242             }
15243           else if (TREE_TYPE (x) != error_mark_node)
15244             {
15245               tree tt = TREE_TYPE (x);
15246
15247               tt = build_type_copy (tt);
15248               TYPE_NAME (tt) = x;
15249               TREE_TYPE (x) = tt;
15250             }
15251         }
15252
15253       /* This name is new in its binding level. Install the new declaration
15254          and return it.  */
15255       if (b == global_binding_level)
15256         IDENTIFIER_GLOBAL_VALUE (name) = x;
15257       else
15258         IDENTIFIER_LOCAL_VALUE (name) = x;
15259     }
15260
15261   /* Put decls on list in reverse order. We will reverse them later if
15262      necessary.  */
15263   TREE_CHAIN (x) = b->names;
15264   b->names = x;
15265
15266   return x;
15267 }
15268
15269 /* Nonzero if the current level needs to have a BLOCK made.  */
15270
15271 static int
15272 kept_level_p ()
15273 {
15274   tree decl;
15275
15276   for (decl = current_binding_level->names;
15277        decl;
15278        decl = TREE_CHAIN (decl))
15279     {
15280       if (TREE_USED (decl) || TREE_CODE (decl) != VAR_DECL
15281           || (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl)))
15282         /* Currently, there aren't supposed to be non-artificial names
15283            at other than the top block for a function -- they're
15284            believed to always be temps.  But it's wise to check anyway.  */
15285         return 1;
15286     }
15287   return 0;
15288 }
15289
15290 /* Enter a new binding level.
15291    If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
15292    not for that of tags.  */
15293
15294 void
15295 pushlevel (tag_transparent)
15296      int tag_transparent;
15297 {
15298   register struct binding_level *newlevel = NULL_BINDING_LEVEL;
15299
15300   assert (! tag_transparent);
15301
15302   if (current_binding_level == global_binding_level)
15303     {
15304       named_labels = 0;
15305     }
15306
15307   /* Reuse or create a struct for this binding level.  */
15308
15309   if (free_binding_level)
15310     {
15311       newlevel = free_binding_level;
15312       free_binding_level = free_binding_level->level_chain;
15313     }
15314   else
15315     {
15316       newlevel = make_binding_level ();
15317     }
15318
15319   /* Add this level to the front of the chain (stack) of levels that
15320      are active.  */
15321
15322   *newlevel = clear_binding_level;
15323   newlevel->level_chain = current_binding_level;
15324   current_binding_level = newlevel;
15325 }
15326
15327 /* Set the BLOCK node for the innermost scope
15328    (the one we are currently in).  */
15329
15330 void
15331 set_block (block)
15332      register tree block;
15333 {
15334   current_binding_level->this_block = block;
15335 }
15336
15337 /* ~~gcc/tree.h *should* declare this, because toplev.c references it.  */
15338
15339 /* Can't 'yydebug' a front end not generated by yacc/bison!  */
15340
15341 void
15342 set_yydebug (value)
15343      int value;
15344 {
15345   if (value)
15346     fprintf (stderr, "warning: no yacc/bison-generated output to debug!\n");
15347 }
15348
15349 tree
15350 signed_or_unsigned_type (unsignedp, type)
15351      int unsignedp;
15352      tree type;
15353 {
15354   tree type2;
15355
15356   if (! INTEGRAL_TYPE_P (type))
15357     return type;
15358   if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
15359     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15360   if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
15361     return unsignedp ? unsigned_type_node : integer_type_node;
15362   if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
15363     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15364   if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
15365     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15366   if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
15367     return (unsignedp ? long_long_unsigned_type_node
15368             : long_long_integer_type_node);
15369
15370   type2 = type_for_size (TYPE_PRECISION (type), unsignedp);
15371   if (type2 == NULL_TREE)
15372     return type;
15373
15374   return type2;
15375 }
15376
15377 tree
15378 signed_type (type)
15379      tree type;
15380 {
15381   tree type1 = TYPE_MAIN_VARIANT (type);
15382   ffeinfoKindtype kt;
15383   tree type2;
15384
15385   if (type1 == unsigned_char_type_node || type1 == char_type_node)
15386     return signed_char_type_node;
15387   if (type1 == unsigned_type_node)
15388     return integer_type_node;
15389   if (type1 == short_unsigned_type_node)
15390     return short_integer_type_node;
15391   if (type1 == long_unsigned_type_node)
15392     return long_integer_type_node;
15393   if (type1 == long_long_unsigned_type_node)
15394     return long_long_integer_type_node;
15395 #if 0   /* gcc/c-* files only */
15396   if (type1 == unsigned_intDI_type_node)
15397     return intDI_type_node;
15398   if (type1 == unsigned_intSI_type_node)
15399     return intSI_type_node;
15400   if (type1 == unsigned_intHI_type_node)
15401     return intHI_type_node;
15402   if (type1 == unsigned_intQI_type_node)
15403     return intQI_type_node;
15404 #endif
15405
15406   type2 = type_for_size (TYPE_PRECISION (type1), 0);
15407   if (type2 != NULL_TREE)
15408     return type2;
15409
15410   for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15411     {
15412       type2 = ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15413
15414       if (type1 == type2)
15415         return ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15416     }
15417
15418   return type;
15419 }
15420
15421 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
15422    or validate its data type for an `if' or `while' statement or ?..: exp.
15423
15424    This preparation consists of taking the ordinary
15425    representation of an expression expr and producing a valid tree
15426    boolean expression describing whether expr is nonzero.  We could
15427    simply always do build_binary_op (NE_EXPR, expr, integer_zero_node, 1),
15428    but we optimize comparisons, &&, ||, and !.
15429
15430    The resulting type should always be `integer_type_node'.  */
15431
15432 tree
15433 truthvalue_conversion (expr)
15434      tree expr;
15435 {
15436   if (TREE_CODE (expr) == ERROR_MARK)
15437     return expr;
15438
15439 #if 0 /* This appears to be wrong for C++.  */
15440   /* These really should return error_mark_node after 2.4 is stable.
15441      But not all callers handle ERROR_MARK properly.  */
15442   switch (TREE_CODE (TREE_TYPE (expr)))
15443     {
15444     case RECORD_TYPE:
15445       error ("struct type value used where scalar is required");
15446       return integer_zero_node;
15447
15448     case UNION_TYPE:
15449       error ("union type value used where scalar is required");
15450       return integer_zero_node;
15451
15452     case ARRAY_TYPE:
15453       error ("array type value used where scalar is required");
15454       return integer_zero_node;
15455
15456     default:
15457       break;
15458     }
15459 #endif /* 0 */
15460
15461   switch (TREE_CODE (expr))
15462     {
15463       /* It is simpler and generates better code to have only TRUTH_*_EXPR
15464          or comparison expressions as truth values at this level.  */
15465 #if 0
15466     case COMPONENT_REF:
15467       /* A one-bit unsigned bit-field is already acceptable.  */
15468       if (1 == TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (expr, 1)))
15469           && TREE_UNSIGNED (TREE_OPERAND (expr, 1)))
15470         return expr;
15471       break;
15472 #endif
15473
15474     case EQ_EXPR:
15475       /* It is simpler and generates better code to have only TRUTH_*_EXPR
15476          or comparison expressions as truth values at this level.  */
15477 #if 0
15478       if (integer_zerop (TREE_OPERAND (expr, 1)))
15479         return build_unary_op (TRUTH_NOT_EXPR, TREE_OPERAND (expr, 0), 0);
15480 #endif
15481     case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
15482     case TRUTH_ANDIF_EXPR:
15483     case TRUTH_ORIF_EXPR:
15484     case TRUTH_AND_EXPR:
15485     case TRUTH_OR_EXPR:
15486     case TRUTH_XOR_EXPR:
15487       TREE_TYPE (expr) = integer_type_node;
15488       return expr;
15489
15490     case ERROR_MARK:
15491       return expr;
15492
15493     case INTEGER_CST:
15494       return integer_zerop (expr) ? integer_zero_node : integer_one_node;
15495
15496     case REAL_CST:
15497       return real_zerop (expr) ? integer_zero_node : integer_one_node;
15498
15499     case ADDR_EXPR:
15500       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
15501         return build (COMPOUND_EXPR, integer_type_node,
15502                       TREE_OPERAND (expr, 0), integer_one_node);
15503       else
15504         return integer_one_node;
15505
15506     case COMPLEX_EXPR:
15507       return ffecom_2 ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
15508                         ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15509                        integer_type_node,
15510                        truthvalue_conversion (TREE_OPERAND (expr, 0)),
15511                        truthvalue_conversion (TREE_OPERAND (expr, 1)));
15512
15513     case NEGATE_EXPR:
15514     case ABS_EXPR:
15515     case FLOAT_EXPR:
15516     case FFS_EXPR:
15517       /* These don't change whether an object is non-zero or zero.  */
15518       return truthvalue_conversion (TREE_OPERAND (expr, 0));
15519
15520     case LROTATE_EXPR:
15521     case RROTATE_EXPR:
15522       /* These don't change whether an object is zero or non-zero, but
15523          we can't ignore them if their second arg has side-effects.  */
15524       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
15525         return build (COMPOUND_EXPR, integer_type_node, TREE_OPERAND (expr, 1),
15526                       truthvalue_conversion (TREE_OPERAND (expr, 0)));
15527       else
15528         return truthvalue_conversion (TREE_OPERAND (expr, 0));
15529
15530     case COND_EXPR:
15531       /* Distribute the conversion into the arms of a COND_EXPR.  */
15532       return fold (build (COND_EXPR, integer_type_node, TREE_OPERAND (expr, 0),
15533                           truthvalue_conversion (TREE_OPERAND (expr, 1)),
15534                           truthvalue_conversion (TREE_OPERAND (expr, 2))));
15535
15536     case CONVERT_EXPR:
15537       /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
15538          since that affects how `default_conversion' will behave.  */
15539       if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
15540           || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
15541         break;
15542       /* fall through... */
15543     case NOP_EXPR:
15544       /* If this is widening the argument, we can ignore it.  */
15545       if (TYPE_PRECISION (TREE_TYPE (expr))
15546           >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
15547         return truthvalue_conversion (TREE_OPERAND (expr, 0));
15548       break;
15549
15550     case MINUS_EXPR:
15551       /* With IEEE arithmetic, x - x may not equal 0, so we can't optimize
15552          this case.  */
15553       if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
15554           && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE)
15555         break;
15556       /* fall through... */
15557     case BIT_XOR_EXPR:
15558       /* This and MINUS_EXPR can be changed into a comparison of the
15559          two objects.  */
15560       if (TREE_TYPE (TREE_OPERAND (expr, 0))
15561           == TREE_TYPE (TREE_OPERAND (expr, 1)))
15562         return ffecom_2 (NE_EXPR, integer_type_node,
15563                          TREE_OPERAND (expr, 0),
15564                          TREE_OPERAND (expr, 1));
15565       return ffecom_2 (NE_EXPR, integer_type_node,
15566                        TREE_OPERAND (expr, 0),
15567                        fold (build1 (NOP_EXPR,
15568                                      TREE_TYPE (TREE_OPERAND (expr, 0)),
15569                                      TREE_OPERAND (expr, 1))));
15570
15571     case BIT_AND_EXPR:
15572       if (integer_onep (TREE_OPERAND (expr, 1)))
15573         return expr;
15574       break;
15575
15576     case MODIFY_EXPR:
15577 #if 0                           /* No such thing in Fortran. */
15578       if (warn_parentheses && C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR)
15579         warning ("suggest parentheses around assignment used as truth value");
15580 #endif
15581       break;
15582
15583     default:
15584       break;
15585     }
15586
15587   if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
15588     return (ffecom_2
15589             ((TREE_SIDE_EFFECTS (expr)
15590               ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
15591              integer_type_node,
15592              truthvalue_conversion (ffecom_1 (REALPART_EXPR,
15593                                               TREE_TYPE (TREE_TYPE (expr)),
15594                                               expr)),
15595              truthvalue_conversion (ffecom_1 (IMAGPART_EXPR,
15596                                               TREE_TYPE (TREE_TYPE (expr)),
15597                                               expr))));
15598
15599   return ffecom_2 (NE_EXPR, integer_type_node,
15600                    expr,
15601                    convert (TREE_TYPE (expr), integer_zero_node));
15602 }
15603
15604 tree
15605 type_for_mode (mode, unsignedp)
15606      enum machine_mode mode;
15607      int unsignedp;
15608 {
15609   int i;
15610   int j;
15611   tree t;
15612
15613   if (mode == TYPE_MODE (integer_type_node))
15614     return unsignedp ? unsigned_type_node : integer_type_node;
15615
15616   if (mode == TYPE_MODE (signed_char_type_node))
15617     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15618
15619   if (mode == TYPE_MODE (short_integer_type_node))
15620     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15621
15622   if (mode == TYPE_MODE (long_integer_type_node))
15623     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15624
15625   if (mode == TYPE_MODE (long_long_integer_type_node))
15626     return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
15627
15628 #if HOST_BITS_PER_WIDE_INT >= 64
15629   if (mode == TYPE_MODE (intTI_type_node))
15630     return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
15631 #endif
15632
15633   if (mode == TYPE_MODE (float_type_node))
15634     return float_type_node;
15635
15636   if (mode == TYPE_MODE (double_type_node))
15637     return double_type_node;
15638
15639   if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
15640     return build_pointer_type (char_type_node);
15641
15642   if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
15643     return build_pointer_type (integer_type_node);
15644
15645   for (i = 0; ((size_t) i) < ARRAY_SIZE (ffecom_tree_type); ++i)
15646     for (j = 0; ((size_t) j) < ARRAY_SIZE (ffecom_tree_type[0]); ++j)
15647       {
15648         if (((t = ffecom_tree_type[i][j]) != NULL_TREE)
15649             && (mode == TYPE_MODE (t)))
15650           {
15651             if ((i == FFEINFO_basictypeINTEGER) && unsignedp)
15652               return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][j];
15653             else
15654               return t;
15655           }
15656       }
15657
15658   return 0;
15659 }
15660
15661 tree
15662 type_for_size (bits, unsignedp)
15663      unsigned bits;
15664      int unsignedp;
15665 {
15666   ffeinfoKindtype kt;
15667   tree type_node;
15668
15669   if (bits == TYPE_PRECISION (integer_type_node))
15670     return unsignedp ? unsigned_type_node : integer_type_node;
15671
15672   if (bits == TYPE_PRECISION (signed_char_type_node))
15673     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
15674
15675   if (bits == TYPE_PRECISION (short_integer_type_node))
15676     return unsignedp ? short_unsigned_type_node : short_integer_type_node;
15677
15678   if (bits == TYPE_PRECISION (long_integer_type_node))
15679     return unsignedp ? long_unsigned_type_node : long_integer_type_node;
15680
15681   if (bits == TYPE_PRECISION (long_long_integer_type_node))
15682     return (unsignedp ? long_long_unsigned_type_node
15683             : long_long_integer_type_node);
15684
15685   for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15686     {
15687       type_node = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15688
15689       if ((type_node != NULL_TREE) && (bits == TYPE_PRECISION (type_node)))
15690         return unsignedp ? ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt]
15691           : type_node;
15692     }
15693
15694   return 0;
15695 }
15696
15697 tree
15698 unsigned_type (type)
15699      tree type;
15700 {
15701   tree type1 = TYPE_MAIN_VARIANT (type);
15702   ffeinfoKindtype kt;
15703   tree type2;
15704
15705   if (type1 == signed_char_type_node || type1 == char_type_node)
15706     return unsigned_char_type_node;
15707   if (type1 == integer_type_node)
15708     return unsigned_type_node;
15709   if (type1 == short_integer_type_node)
15710     return short_unsigned_type_node;
15711   if (type1 == long_integer_type_node)
15712     return long_unsigned_type_node;
15713   if (type1 == long_long_integer_type_node)
15714     return long_long_unsigned_type_node;
15715 #if 0   /* gcc/c-* files only */
15716   if (type1 == intDI_type_node)
15717     return unsigned_intDI_type_node;
15718   if (type1 == intSI_type_node)
15719     return unsigned_intSI_type_node;
15720   if (type1 == intHI_type_node)
15721     return unsigned_intHI_type_node;
15722   if (type1 == intQI_type_node)
15723     return unsigned_intQI_type_node;
15724 #endif
15725
15726   type2 = type_for_size (TYPE_PRECISION (type1), 1);
15727   if (type2 != NULL_TREE)
15728     return type2;
15729
15730   for (kt = 0; kt < ARRAY_SIZE (ffecom_tree_type[0]); ++kt)
15731     {
15732       type2 = ffecom_tree_type[FFEINFO_basictypeINTEGER][kt];
15733
15734       if (type1 == type2)
15735         return ffecom_tree_type[FFEINFO_basictypeHOLLERITH][kt];
15736     }
15737
15738   return type;
15739 }
15740
15741 /* Callback routines for garbage collection.  */
15742
15743 int ggc_p = 1;
15744
15745 void 
15746 lang_mark_tree (t)
15747      union tree_node *t ATTRIBUTE_UNUSED;
15748 {
15749   if (TREE_CODE (t) == IDENTIFIER_NODE)
15750     {
15751       struct lang_identifier *i = (struct lang_identifier *) t;
15752       ggc_mark_tree (IDENTIFIER_GLOBAL_VALUE (i));
15753       ggc_mark_tree (IDENTIFIER_LOCAL_VALUE (i));
15754       ggc_mark_tree (IDENTIFIER_LABEL_VALUE (i));
15755     }
15756   else if (TYPE_P (t) && TYPE_LANG_SPECIFIC (t))
15757     ggc_mark (TYPE_LANG_SPECIFIC (t));
15758 }
15759
15760 void
15761 lang_mark_false_label_stack (l)
15762      struct label_node *l;
15763 {
15764   /* Fortran doesn't use false_label_stack.  It better be NULL.  */
15765   if (l != NULL)
15766     abort();
15767 }
15768
15769 #endif /* FFECOM_targetCURRENT == FFECOM_targetGCC */
15770 \f
15771 #if FFECOM_GCC_INCLUDE
15772
15773 /* From gcc/cccp.c, the code to handle -I.  */
15774
15775 /* Skip leading "./" from a directory name.
15776    This may yield the empty string, which represents the current directory.  */
15777
15778 static const char *
15779 skip_redundant_dir_prefix (const char *dir)
15780 {
15781   while (dir[0] == '.' && dir[1] == '/')
15782     for (dir += 2; *dir == '/'; dir++)
15783       continue;
15784   if (dir[0] == '.' && !dir[1])
15785     dir++;
15786   return dir;
15787 }
15788
15789 /* The file_name_map structure holds a mapping of file names for a
15790    particular directory.  This mapping is read from the file named
15791    FILE_NAME_MAP_FILE in that directory.  Such a file can be used to
15792    map filenames on a file system with severe filename restrictions,
15793    such as DOS.  The format of the file name map file is just a series
15794    of lines with two tokens on each line.  The first token is the name
15795    to map, and the second token is the actual name to use.  */
15796
15797 struct file_name_map
15798 {
15799   struct file_name_map *map_next;
15800   char *map_from;
15801   char *map_to;
15802 };
15803
15804 #define FILE_NAME_MAP_FILE "header.gcc"
15805
15806 /* Current maximum length of directory names in the search path
15807    for include files.  (Altered as we get more of them.)  */
15808
15809 static int max_include_len = 0;
15810
15811 struct file_name_list
15812   {
15813     struct file_name_list *next;
15814     char *fname;
15815     /* Mapping of file names for this directory.  */
15816     struct file_name_map *name_map;
15817     /* Non-zero if name_map is valid.  */
15818     int got_name_map;
15819   };
15820
15821 static struct file_name_list *include = NULL;   /* First dir to search */
15822 static struct file_name_list *last_include = NULL;      /* Last in chain */
15823
15824 /* I/O buffer structure.
15825    The `fname' field is nonzero for source files and #include files
15826    and for the dummy text used for -D and -U.
15827    It is zero for rescanning results of macro expansion
15828    and for expanding macro arguments.  */
15829 #define INPUT_STACK_MAX 400
15830 static struct file_buf {
15831   const char *fname;
15832   /* Filename specified with #line command.  */
15833   const char *nominal_fname;
15834   /* Record where in the search path this file was found.
15835      For #include_next.  */
15836   struct file_name_list *dir;
15837   ffewhereLine line;
15838   ffewhereColumn column;
15839 } instack[INPUT_STACK_MAX];
15840
15841 static int last_error_tick = 0;    /* Incremented each time we print it.  */
15842 static int input_file_stack_tick = 0;  /* Incremented when status changes.  */
15843
15844 /* Current nesting level of input sources.
15845    `instack[indepth]' is the level currently being read.  */
15846 static int indepth = -1;
15847
15848 typedef struct file_buf FILE_BUF;
15849
15850 typedef unsigned char U_CHAR;
15851
15852 /* table to tell if char can be part of a C identifier. */
15853 U_CHAR is_idchar[256];
15854 /* table to tell if char can be first char of a c identifier. */
15855 U_CHAR is_idstart[256];
15856 /* table to tell if c is horizontal space.  */
15857 U_CHAR is_hor_space[256];
15858 /* table to tell if c is horizontal or vertical space.  */
15859 static U_CHAR is_space[256];
15860
15861 #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
15862 #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
15863
15864 /* Nonzero means -I- has been seen,
15865    so don't look for #include "foo" the source-file directory.  */
15866 static int ignore_srcdir;
15867
15868 #ifndef INCLUDE_LEN_FUDGE
15869 #define INCLUDE_LEN_FUDGE 0
15870 #endif
15871
15872 static void append_include_chain (struct file_name_list *first,
15873                                   struct file_name_list *last);
15874 static FILE *open_include_file (char *filename,
15875                                 struct file_name_list *searchptr);
15876 static void print_containing_files (ffebadSeverity sev);
15877 static const char *skip_redundant_dir_prefix (const char *);
15878 static char *read_filename_string (int ch, FILE *f);
15879 static struct file_name_map *read_name_map (const char *dirname);
15880
15881 /* Append a chain of `struct file_name_list's
15882    to the end of the main include chain.
15883    FIRST is the beginning of the chain to append, and LAST is the end.  */
15884
15885 static void
15886 append_include_chain (first, last)
15887      struct file_name_list *first, *last;
15888 {
15889   struct file_name_list *dir;
15890
15891   if (!first || !last)
15892     return;
15893
15894   if (include == 0)
15895     include = first;
15896   else
15897     last_include->next = first;
15898
15899   for (dir = first; ; dir = dir->next) {
15900     int len = strlen (dir->fname) + INCLUDE_LEN_FUDGE;
15901     if (len > max_include_len)
15902       max_include_len = len;
15903     if (dir == last)
15904       break;
15905   }
15906
15907   last->next = NULL;
15908   last_include = last;
15909 }
15910
15911 /* Try to open include file FILENAME.  SEARCHPTR is the directory
15912    being tried from the include file search path.  This function maps
15913    filenames on file systems based on information read by
15914    read_name_map.  */
15915
15916 static FILE *
15917 open_include_file (filename, searchptr)
15918      char *filename;
15919      struct file_name_list *searchptr;
15920 {
15921   register struct file_name_map *map;
15922   register char *from;
15923   char *p, *dir;
15924
15925   if (searchptr && ! searchptr->got_name_map)
15926     {
15927       searchptr->name_map = read_name_map (searchptr->fname
15928                                            ? searchptr->fname : ".");
15929       searchptr->got_name_map = 1;
15930     }
15931
15932   /* First check the mapping for the directory we are using.  */
15933   if (searchptr && searchptr->name_map)
15934     {
15935       from = filename;
15936       if (searchptr->fname)
15937         from += strlen (searchptr->fname) + 1;
15938       for (map = searchptr->name_map; map; map = map->map_next)
15939         {
15940           if (! strcmp (map->map_from, from))
15941             {
15942               /* Found a match.  */
15943               return fopen (map->map_to, "r");
15944             }
15945         }
15946     }
15947
15948   /* Try to find a mapping file for the particular directory we are
15949      looking in.  Thus #include <sys/types.h> will look up sys/types.h
15950      in /usr/include/header.gcc and look up types.h in
15951      /usr/include/sys/header.gcc.  */
15952   p = rindex (filename, '/');
15953 #ifdef DIR_SEPARATOR
15954   if (! p) p = rindex (filename, DIR_SEPARATOR);
15955   else {
15956     char *tmp = rindex (filename, DIR_SEPARATOR);
15957     if (tmp != NULL && tmp > p) p = tmp;
15958   }
15959 #endif
15960   if (! p)
15961     p = filename;
15962   if (searchptr
15963       && searchptr->fname
15964       && strlen (searchptr->fname) == (size_t) (p - filename)
15965       && ! strncmp (searchptr->fname, filename, (int) (p - filename)))
15966     {
15967       /* FILENAME is in SEARCHPTR, which we've already checked.  */
15968       return fopen (filename, "r");
15969     }
15970
15971   if (p == filename)
15972     {
15973       from = filename;
15974       map = read_name_map (".");
15975     }
15976   else
15977     {
15978       dir = (char *) xmalloc (p - filename + 1);
15979       memcpy (dir, filename, p - filename);
15980       dir[p - filename] = '\0';
15981       from = p + 1;
15982       map = read_name_map (dir);
15983       free (dir);
15984     }
15985   for (; map; map = map->map_next)
15986     if (! strcmp (map->map_from, from))
15987       return fopen (map->map_to, "r");
15988
15989   return fopen (filename, "r");
15990 }
15991
15992 /* Print the file names and line numbers of the #include
15993    commands which led to the current file.  */
15994
15995 static void
15996 print_containing_files (ffebadSeverity sev)
15997 {
15998   FILE_BUF *ip = NULL;
15999   int i;
16000   int first = 1;
16001   const char *str1;
16002   const char *str2;
16003
16004   /* If stack of files hasn't changed since we last printed
16005      this info, don't repeat it.  */
16006   if (last_error_tick == input_file_stack_tick)
16007     return;
16008
16009   for (i = indepth; i >= 0; i--)
16010     if (instack[i].fname != NULL) {
16011       ip = &instack[i];
16012       break;
16013     }
16014
16015   /* Give up if we don't find a source file.  */
16016   if (ip == NULL)
16017     return;
16018
16019   /* Find the other, outer source files.  */
16020   for (i--; i >= 0; i--)
16021     if (instack[i].fname != NULL)
16022       {
16023         ip = &instack[i];
16024         if (first)
16025           {
16026             first = 0;
16027             str1 = "In file included";
16028           }
16029         else
16030           {
16031             str1 = "...          ...";
16032           }
16033
16034         if (i == 1)
16035           str2 = ":";
16036         else
16037           str2 = "";
16038
16039         ffebad_start_msg ("%A from %B at %0%C", sev);
16040         ffebad_here (0, ip->line, ip->column);
16041         ffebad_string (str1);
16042         ffebad_string (ip->nominal_fname);
16043         ffebad_string (str2);
16044         ffebad_finish ();
16045       }
16046
16047   /* Record we have printed the status as of this time.  */
16048   last_error_tick = input_file_stack_tick;
16049 }
16050
16051 /* Read a space delimited string of unlimited length from a stdio
16052    file.  */
16053
16054 static char *
16055 read_filename_string (ch, f)
16056      int ch;
16057      FILE *f;
16058 {
16059   char *alloc, *set;
16060   int len;
16061
16062   len = 20;
16063   set = alloc = xmalloc (len + 1);
16064   if (! is_space[ch])
16065     {
16066       *set++ = ch;
16067       while ((ch = getc (f)) != EOF && ! is_space[ch])
16068         {
16069           if (set - alloc == len)
16070             {
16071               len *= 2;
16072               alloc = xrealloc (alloc, len + 1);
16073               set = alloc + len / 2;
16074             }
16075           *set++ = ch;
16076         }
16077     }
16078   *set = '\0';
16079   ungetc (ch, f);
16080   return alloc;
16081 }
16082
16083 /* Read the file name map file for DIRNAME.  */
16084
16085 static struct file_name_map *
16086 read_name_map (dirname)
16087      const char *dirname;
16088 {
16089   /* This structure holds a linked list of file name maps, one per
16090      directory.  */
16091   struct file_name_map_list
16092     {
16093       struct file_name_map_list *map_list_next;
16094       char *map_list_name;
16095       struct file_name_map *map_list_map;
16096     };
16097   static struct file_name_map_list *map_list;
16098   register struct file_name_map_list *map_list_ptr;
16099   char *name;
16100   FILE *f;
16101   size_t dirlen;
16102   int separator_needed;
16103
16104   dirname = skip_redundant_dir_prefix (dirname);
16105
16106   for (map_list_ptr = map_list; map_list_ptr;
16107        map_list_ptr = map_list_ptr->map_list_next)
16108     if (! strcmp (map_list_ptr->map_list_name, dirname))
16109       return map_list_ptr->map_list_map;
16110
16111   map_list_ptr = ((struct file_name_map_list *)
16112                   xmalloc (sizeof (struct file_name_map_list)));
16113   map_list_ptr->map_list_name = xstrdup (dirname);
16114   map_list_ptr->map_list_map = NULL;
16115
16116   dirlen = strlen (dirname);
16117   separator_needed = dirlen != 0 && dirname[dirlen - 1] != '/';
16118   name = (char *) xmalloc (dirlen + strlen (FILE_NAME_MAP_FILE) + 2);
16119   strcpy (name, dirname);
16120   name[dirlen] = '/';
16121   strcpy (name + dirlen + separator_needed, FILE_NAME_MAP_FILE);
16122   f = fopen (name, "r");
16123   free (name);
16124   if (!f)
16125     map_list_ptr->map_list_map = NULL;
16126   else
16127     {
16128       int ch;
16129
16130       while ((ch = getc (f)) != EOF)
16131         {
16132           char *from, *to;
16133           struct file_name_map *ptr;
16134
16135           if (is_space[ch])
16136             continue;
16137           from = read_filename_string (ch, f);
16138           while ((ch = getc (f)) != EOF && is_hor_space[ch])
16139             ;
16140           to = read_filename_string (ch, f);
16141
16142           ptr = ((struct file_name_map *)
16143                  xmalloc (sizeof (struct file_name_map)));
16144           ptr->map_from = from;
16145
16146           /* Make the real filename absolute.  */
16147           if (*to == '/')
16148             ptr->map_to = to;
16149           else
16150             {
16151               ptr->map_to = xmalloc (dirlen + strlen (to) + 2);
16152               strcpy (ptr->map_to, dirname);
16153               ptr->map_to[dirlen] = '/';
16154               strcpy (ptr->map_to + dirlen + separator_needed, to);
16155               free (to);
16156             }
16157
16158           ptr->map_next = map_list_ptr->map_list_map;
16159           map_list_ptr->map_list_map = ptr;
16160
16161           while ((ch = getc (f)) != '\n')
16162             if (ch == EOF)
16163               break;
16164         }
16165       fclose (f);
16166     }
16167
16168   map_list_ptr->map_list_next = map_list;
16169   map_list = map_list_ptr;
16170
16171   return map_list_ptr->map_list_map;
16172 }
16173
16174 static void
16175 ffecom_file_ (const char *name)
16176 {
16177   FILE_BUF *fp;
16178
16179   /* Do partial setup of input buffer for the sake of generating
16180      early #line directives (when -g is in effect).  */
16181
16182   fp = &instack[++indepth];
16183   memset ((char *) fp, 0, sizeof (FILE_BUF));
16184   if (name == NULL)
16185     name = "";
16186   fp->nominal_fname = fp->fname = name;
16187 }
16188
16189 /* Initialize syntactic classifications of characters.  */
16190
16191 static void
16192 ffecom_initialize_char_syntax_ ()
16193 {
16194   register int i;
16195
16196   /*
16197    * Set up is_idchar and is_idstart tables.  These should be
16198    * faster than saying (is_alpha (c) || c == '_'), etc.
16199    * Set up these things before calling any routines tthat
16200    * refer to them.
16201    */
16202   for (i = 'a'; i <= 'z'; i++) {
16203     is_idchar[i - 'a' + 'A'] = 1;
16204     is_idchar[i] = 1;
16205     is_idstart[i - 'a' + 'A'] = 1;
16206     is_idstart[i] = 1;
16207   }
16208   for (i = '0'; i <= '9'; i++)
16209     is_idchar[i] = 1;
16210   is_idchar['_'] = 1;
16211   is_idstart['_'] = 1;
16212
16213   /* horizontal space table */
16214   is_hor_space[' '] = 1;
16215   is_hor_space['\t'] = 1;
16216   is_hor_space['\v'] = 1;
16217   is_hor_space['\f'] = 1;
16218   is_hor_space['\r'] = 1;
16219
16220   is_space[' '] = 1;
16221   is_space['\t'] = 1;
16222   is_space['\v'] = 1;
16223   is_space['\f'] = 1;
16224   is_space['\n'] = 1;
16225   is_space['\r'] = 1;
16226 }
16227
16228 static void
16229 ffecom_close_include_ (FILE *f)
16230 {
16231   fclose (f);
16232
16233   indepth--;
16234   input_file_stack_tick++;
16235
16236   ffewhere_line_kill (instack[indepth].line);
16237   ffewhere_column_kill (instack[indepth].column);
16238 }
16239
16240 static int
16241 ffecom_decode_include_option_ (char *spec)
16242 {
16243   struct file_name_list *dirtmp;
16244
16245   if (! ignore_srcdir && !strcmp (spec, "-"))
16246     ignore_srcdir = 1;
16247   else
16248     {
16249       dirtmp = (struct file_name_list *)
16250         xmalloc (sizeof (struct file_name_list));
16251       dirtmp->next = 0;         /* New one goes on the end */
16252       if (spec[0] != 0)
16253         dirtmp->fname = spec;
16254       else
16255         fatal ("Directory name must immediately follow -I option with no intervening spaces, as in `-Idir', not `-I dir'");
16256       dirtmp->got_name_map = 0;
16257       append_include_chain (dirtmp, dirtmp);
16258     }
16259   return 1;
16260 }
16261
16262 /* Open INCLUDEd file.  */
16263
16264 static FILE *
16265 ffecom_open_include_ (char *name, ffewhereLine l, ffewhereColumn c)
16266 {
16267   char *fbeg = name;
16268   size_t flen = strlen (fbeg);
16269   struct file_name_list *search_start = include; /* Chain of dirs to search */
16270   struct file_name_list dsp[1]; /* First in chain, if #include "..." */
16271   struct file_name_list *searchptr = 0;
16272   char *fname;          /* Dynamically allocated fname buffer */
16273   FILE *f;
16274   FILE_BUF *fp;
16275
16276   if (flen == 0)
16277     return NULL;
16278
16279   dsp[0].fname = NULL;
16280
16281   /* If -I- was specified, don't search current dir, only spec'd ones. */
16282   if (!ignore_srcdir)
16283     {
16284       for (fp = &instack[indepth]; fp >= instack; fp--)
16285         {
16286           int n;
16287           char *ep;
16288           const char *nam;
16289
16290           if ((nam = fp->nominal_fname) != NULL)
16291             {
16292               /* Found a named file.  Figure out dir of the file,
16293                  and put it in front of the search list.  */
16294               dsp[0].next = search_start;
16295               search_start = dsp;
16296 #ifndef VMS
16297               ep = rindex (nam, '/');
16298 #ifdef DIR_SEPARATOR
16299             if (ep == NULL) ep = rindex (nam, DIR_SEPARATOR);
16300             else {
16301               char *tmp = rindex (nam, DIR_SEPARATOR);
16302               if (tmp != NULL && tmp > ep) ep = tmp;
16303             }
16304 #endif
16305 #else                           /* VMS */
16306               ep = rindex (nam, ']');
16307               if (ep == NULL) ep = rindex (nam, '>');
16308               if (ep == NULL) ep = rindex (nam, ':');
16309               if (ep != NULL) ep++;
16310 #endif                          /* VMS */
16311               if (ep != NULL)
16312                 {
16313                   n = ep - nam;
16314                   dsp[0].fname = (char *) xmalloc (n + 1);
16315                   strncpy (dsp[0].fname, nam, n);
16316                   dsp[0].fname[n] = '\0';
16317                   if (n + INCLUDE_LEN_FUDGE > max_include_len)
16318                     max_include_len = n + INCLUDE_LEN_FUDGE;
16319                 }
16320               else
16321                 dsp[0].fname = NULL; /* Current directory */
16322               dsp[0].got_name_map = 0;
16323               break;
16324             }
16325         }
16326     }
16327
16328   /* Allocate this permanently, because it gets stored in the definitions
16329      of macros.  */
16330   fname = xmalloc (max_include_len + flen + 4);
16331   /* + 2 above for slash and terminating null.  */
16332   /* + 2 added for '.h' on VMS (to support '#include filename') (NOT USED
16333      for g77 yet).  */
16334
16335   /* If specified file name is absolute, just open it.  */
16336
16337   if (*fbeg == '/'
16338 #ifdef DIR_SEPARATOR
16339       || *fbeg == DIR_SEPARATOR
16340 #endif
16341       )
16342     {
16343       strncpy (fname, (char *) fbeg, flen);
16344       fname[flen] = 0;
16345       f = open_include_file (fname, NULL_PTR);
16346     }
16347   else
16348     {
16349       f = NULL;
16350
16351       /* Search directory path, trying to open the file.
16352          Copy each filename tried into FNAME.  */
16353
16354       for (searchptr = search_start; searchptr; searchptr = searchptr->next)
16355         {
16356           if (searchptr->fname)
16357             {
16358               /* The empty string in a search path is ignored.
16359                  This makes it possible to turn off entirely
16360                  a standard piece of the list.  */
16361               if (searchptr->fname[0] == 0)
16362                 continue;
16363               strcpy (fname, skip_redundant_dir_prefix (searchptr->fname));
16364               if (fname[0] && fname[strlen (fname) - 1] != '/')
16365                 strcat (fname, "/");
16366               fname[strlen (fname) + flen] = 0;
16367             }
16368           else
16369             fname[0] = 0;
16370
16371           strncat (fname, fbeg, flen);
16372 #ifdef VMS
16373           /* Change this 1/2 Unix 1/2 VMS file specification into a
16374              full VMS file specification */
16375           if (searchptr->fname && (searchptr->fname[0] != 0))
16376             {
16377               /* Fix up the filename */
16378               hack_vms_include_specification (fname);
16379             }
16380           else
16381             {
16382               /* This is a normal VMS filespec, so use it unchanged.  */
16383               strncpy (fname, (char *) fbeg, flen);
16384               fname[flen] = 0;
16385 #if 0   /* Not for g77.  */
16386               /* if it's '#include filename', add the missing .h */
16387               if (index (fname, '.') == NULL)
16388                 strcat (fname, ".h");
16389 #endif
16390             }
16391 #endif /* VMS */
16392           f = open_include_file (fname, searchptr);
16393 #ifdef EACCES
16394           if (f == NULL && errno == EACCES)
16395             {
16396               print_containing_files (FFEBAD_severityWARNING);
16397               ffebad_start_msg ("At %0, INCLUDE file %A exists, but is not readable",
16398                                 FFEBAD_severityWARNING);
16399               ffebad_string (fname);
16400               ffebad_here (0, l, c);
16401               ffebad_finish ();
16402             }
16403 #endif
16404           if (f != NULL)
16405             break;
16406         }
16407     }
16408
16409   if (f == NULL)
16410     {
16411       /* A file that was not found.  */
16412
16413       strncpy (fname, (char *) fbeg, flen);
16414       fname[flen] = 0;
16415       print_containing_files (ffebad_severity (FFEBAD_OPEN_INCLUDE));
16416       ffebad_start (FFEBAD_OPEN_INCLUDE);
16417       ffebad_here (0, l, c);
16418       ffebad_string (fname);
16419       ffebad_finish ();
16420     }
16421
16422   if (dsp[0].fname != NULL)
16423     free (dsp[0].fname);
16424
16425   if (f == NULL)
16426     return NULL;
16427
16428   if (indepth >= (INPUT_STACK_MAX - 1))
16429     {
16430       print_containing_files (FFEBAD_severityFATAL);
16431       ffebad_start_msg ("At %0, INCLUDE nesting too deep",
16432                         FFEBAD_severityFATAL);
16433       ffebad_string (fname);
16434       ffebad_here (0, l, c);
16435       ffebad_finish ();
16436       return NULL;
16437     }
16438
16439   instack[indepth].line = ffewhere_line_use (l);
16440   instack[indepth].column = ffewhere_column_use (c);
16441
16442   fp = &instack[indepth + 1];
16443   memset ((char *) fp, 0, sizeof (FILE_BUF));
16444   fp->nominal_fname = fp->fname = fname;
16445   fp->dir = searchptr;
16446
16447   indepth++;
16448   input_file_stack_tick++;
16449
16450   return f;
16451 }
16452 #endif  /* FFECOM_GCC_INCLUDE */
16453
16454 /**INDENT* (Do not reformat this comment even with -fca option.)
16455    Data-gathering files: Given the source file listed below, compiled with
16456    f2c I obtained the output file listed after that, and from the output
16457    file I derived the above code.
16458
16459 -------- (begin input file to f2c)
16460         implicit none
16461         character*10 A1,A2
16462         complex C1,C2
16463         integer I1,I2
16464         real R1,R2
16465         double precision D1,D2
16466 C
16467         call getem(A1,A2,C1,C2,I1,I2,R1,R2,D1,D2)
16468 c /
16469         call fooI(I1/I2)
16470         call fooR(R1/I1)
16471         call fooD(D1/I1)
16472         call fooC(C1/I1)
16473         call fooR(R1/R2)
16474         call fooD(R1/D1)
16475         call fooD(D1/D2)
16476         call fooD(D1/R1)
16477         call fooC(C1/C2)
16478         call fooC(C1/R1)
16479         call fooZ(C1/D1)
16480 c **
16481         call fooI(I1**I2)
16482         call fooR(R1**I1)
16483         call fooD(D1**I1)
16484         call fooC(C1**I1)
16485         call fooR(R1**R2)
16486         call fooD(R1**D1)
16487         call fooD(D1**D2)
16488         call fooD(D1**R1)
16489         call fooC(C1**C2)
16490         call fooC(C1**R1)
16491         call fooZ(C1**D1)
16492 c FFEINTRIN_impABS
16493         call fooR(ABS(R1))
16494 c FFEINTRIN_impACOS
16495         call fooR(ACOS(R1))
16496 c FFEINTRIN_impAIMAG
16497         call fooR(AIMAG(C1))
16498 c FFEINTRIN_impAINT
16499         call fooR(AINT(R1))
16500 c FFEINTRIN_impALOG
16501         call fooR(ALOG(R1))
16502 c FFEINTRIN_impALOG10
16503         call fooR(ALOG10(R1))
16504 c FFEINTRIN_impAMAX0
16505         call fooR(AMAX0(I1,I2))
16506 c FFEINTRIN_impAMAX1
16507         call fooR(AMAX1(R1,R2))
16508 c FFEINTRIN_impAMIN0
16509         call fooR(AMIN0(I1,I2))
16510 c FFEINTRIN_impAMIN1
16511         call fooR(AMIN1(R1,R2))
16512 c FFEINTRIN_impAMOD
16513         call fooR(AMOD(R1,R2))
16514 c FFEINTRIN_impANINT
16515         call fooR(ANINT(R1))
16516 c FFEINTRIN_impASIN
16517         call fooR(ASIN(R1))
16518 c FFEINTRIN_impATAN
16519         call fooR(ATAN(R1))
16520 c FFEINTRIN_impATAN2
16521         call fooR(ATAN2(R1,R2))
16522 c FFEINTRIN_impCABS
16523         call fooR(CABS(C1))
16524 c FFEINTRIN_impCCOS
16525         call fooC(CCOS(C1))
16526 c FFEINTRIN_impCEXP
16527         call fooC(CEXP(C1))
16528 c FFEINTRIN_impCHAR
16529         call fooA(CHAR(I1))
16530 c FFEINTRIN_impCLOG
16531         call fooC(CLOG(C1))
16532 c FFEINTRIN_impCONJG
16533         call fooC(CONJG(C1))
16534 c FFEINTRIN_impCOS
16535         call fooR(COS(R1))
16536 c FFEINTRIN_impCOSH
16537         call fooR(COSH(R1))
16538 c FFEINTRIN_impCSIN
16539         call fooC(CSIN(C1))
16540 c FFEINTRIN_impCSQRT
16541         call fooC(CSQRT(C1))
16542 c FFEINTRIN_impDABS
16543         call fooD(DABS(D1))
16544 c FFEINTRIN_impDACOS
16545         call fooD(DACOS(D1))
16546 c FFEINTRIN_impDASIN
16547         call fooD(DASIN(D1))
16548 c FFEINTRIN_impDATAN
16549         call fooD(DATAN(D1))
16550 c FFEINTRIN_impDATAN2
16551         call fooD(DATAN2(D1,D2))
16552 c FFEINTRIN_impDCOS
16553         call fooD(DCOS(D1))
16554 c FFEINTRIN_impDCOSH
16555         call fooD(DCOSH(D1))
16556 c FFEINTRIN_impDDIM
16557         call fooD(DDIM(D1,D2))
16558 c FFEINTRIN_impDEXP
16559         call fooD(DEXP(D1))
16560 c FFEINTRIN_impDIM
16561         call fooR(DIM(R1,R2))
16562 c FFEINTRIN_impDINT
16563         call fooD(DINT(D1))
16564 c FFEINTRIN_impDLOG
16565         call fooD(DLOG(D1))
16566 c FFEINTRIN_impDLOG10
16567         call fooD(DLOG10(D1))
16568 c FFEINTRIN_impDMAX1
16569         call fooD(DMAX1(D1,D2))
16570 c FFEINTRIN_impDMIN1
16571         call fooD(DMIN1(D1,D2))
16572 c FFEINTRIN_impDMOD
16573         call fooD(DMOD(D1,D2))
16574 c FFEINTRIN_impDNINT
16575         call fooD(DNINT(D1))
16576 c FFEINTRIN_impDPROD
16577         call fooD(DPROD(R1,R2))
16578 c FFEINTRIN_impDSIGN
16579         call fooD(DSIGN(D1,D2))
16580 c FFEINTRIN_impDSIN
16581         call fooD(DSIN(D1))
16582 c FFEINTRIN_impDSINH
16583         call fooD(DSINH(D1))
16584 c FFEINTRIN_impDSQRT
16585         call fooD(DSQRT(D1))
16586 c FFEINTRIN_impDTAN
16587         call fooD(DTAN(D1))
16588 c FFEINTRIN_impDTANH
16589         call fooD(DTANH(D1))
16590 c FFEINTRIN_impEXP
16591         call fooR(EXP(R1))
16592 c FFEINTRIN_impIABS
16593         call fooI(IABS(I1))
16594 c FFEINTRIN_impICHAR
16595         call fooI(ICHAR(A1))
16596 c FFEINTRIN_impIDIM
16597         call fooI(IDIM(I1,I2))
16598 c FFEINTRIN_impIDNINT
16599         call fooI(IDNINT(D1))
16600 c FFEINTRIN_impINDEX
16601         call fooI(INDEX(A1,A2))
16602 c FFEINTRIN_impISIGN
16603         call fooI(ISIGN(I1,I2))
16604 c FFEINTRIN_impLEN
16605         call fooI(LEN(A1))
16606 c FFEINTRIN_impLGE
16607         call fooL(LGE(A1,A2))
16608 c FFEINTRIN_impLGT
16609         call fooL(LGT(A1,A2))
16610 c FFEINTRIN_impLLE
16611         call fooL(LLE(A1,A2))
16612 c FFEINTRIN_impLLT
16613         call fooL(LLT(A1,A2))
16614 c FFEINTRIN_impMAX0
16615         call fooI(MAX0(I1,I2))
16616 c FFEINTRIN_impMAX1
16617         call fooI(MAX1(R1,R2))
16618 c FFEINTRIN_impMIN0
16619         call fooI(MIN0(I1,I2))
16620 c FFEINTRIN_impMIN1
16621         call fooI(MIN1(R1,R2))
16622 c FFEINTRIN_impMOD
16623         call fooI(MOD(I1,I2))
16624 c FFEINTRIN_impNINT
16625         call fooI(NINT(R1))
16626 c FFEINTRIN_impSIGN
16627         call fooR(SIGN(R1,R2))
16628 c FFEINTRIN_impSIN
16629         call fooR(SIN(R1))
16630 c FFEINTRIN_impSINH
16631         call fooR(SINH(R1))
16632 c FFEINTRIN_impSQRT
16633         call fooR(SQRT(R1))
16634 c FFEINTRIN_impTAN
16635         call fooR(TAN(R1))
16636 c FFEINTRIN_impTANH
16637         call fooR(TANH(R1))
16638 c FFEINTRIN_imp_CMPLX_C
16639         call fooC(cmplx(C1,C2))
16640 c FFEINTRIN_imp_CMPLX_D
16641         call fooZ(cmplx(D1,D2))
16642 c FFEINTRIN_imp_CMPLX_I
16643         call fooC(cmplx(I1,I2))
16644 c FFEINTRIN_imp_CMPLX_R
16645         call fooC(cmplx(R1,R2))
16646 c FFEINTRIN_imp_DBLE_C
16647         call fooD(dble(C1))
16648 c FFEINTRIN_imp_DBLE_D
16649         call fooD(dble(D1))
16650 c FFEINTRIN_imp_DBLE_I
16651         call fooD(dble(I1))
16652 c FFEINTRIN_imp_DBLE_R
16653         call fooD(dble(R1))
16654 c FFEINTRIN_imp_INT_C
16655         call fooI(int(C1))
16656 c FFEINTRIN_imp_INT_D
16657         call fooI(int(D1))
16658 c FFEINTRIN_imp_INT_I
16659         call fooI(int(I1))
16660 c FFEINTRIN_imp_INT_R
16661         call fooI(int(R1))
16662 c FFEINTRIN_imp_REAL_C
16663         call fooR(real(C1))
16664 c FFEINTRIN_imp_REAL_D
16665         call fooR(real(D1))
16666 c FFEINTRIN_imp_REAL_I
16667         call fooR(real(I1))
16668 c FFEINTRIN_imp_REAL_R
16669         call fooR(real(R1))
16670 c
16671 c FFEINTRIN_imp_INT_D:
16672 c
16673 c FFEINTRIN_specIDINT
16674         call fooI(IDINT(D1))
16675 c
16676 c FFEINTRIN_imp_INT_R:
16677 c
16678 c FFEINTRIN_specIFIX
16679         call fooI(IFIX(R1))
16680 c FFEINTRIN_specINT
16681         call fooI(INT(R1))
16682 c
16683 c FFEINTRIN_imp_REAL_D:
16684 c
16685 c FFEINTRIN_specSNGL
16686         call fooR(SNGL(D1))
16687 c
16688 c FFEINTRIN_imp_REAL_I:
16689 c
16690 c FFEINTRIN_specFLOAT
16691         call fooR(FLOAT(I1))
16692 c FFEINTRIN_specREAL
16693         call fooR(REAL(I1))
16694 c
16695         end
16696 -------- (end input file to f2c)
16697
16698 -------- (begin output from providing above input file as input to:
16699 --------  `f2c | gcc -E -C - | sed -e "s:/[*]*://:g" -e "s:[*]*[/]://:g" \
16700 --------     -e "s:^#.*$::g"')
16701
16702 //  -- translated by f2c (version 19950223).
16703    You must link the resulting object file with the libraries:
16704         -lf2c -lm   (in that order)
16705 //
16706
16707
16708 // f2c.h  --  Standard Fortran to C header file //
16709
16710 ///  barf  [ba:rf]  2.  "He suggested using FORTRAN, and everybody barfed."
16711
16712         - From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) //
16713
16714
16715
16716
16717 // F2C_INTEGER will normally be `int' but would be `long' on 16-bit systems //
16718 // we assume short, float are OK //
16719 typedef long int // long int // integer;
16720 typedef char *address;
16721 typedef short int shortint;
16722 typedef float real;
16723 typedef double doublereal;
16724 typedef struct { real r, i; } complex;
16725 typedef struct { doublereal r, i; } doublecomplex;
16726 typedef long int // long int // logical;
16727 typedef short int shortlogical;
16728 typedef char logical1;
16729 typedef char integer1;
16730 // typedef long long longint; // // system-dependent //
16731
16732
16733
16734
16735 // Extern is for use with -E //
16736
16737
16738
16739
16740 // I/O stuff //
16741
16742
16743
16744
16745
16746
16747
16748
16749 typedef long int // int or long int // flag;
16750 typedef long int // int or long int // ftnlen;
16751 typedef long int // int or long int // ftnint;
16752
16753
16754 //external read, write//
16755 typedef struct
16756 {       flag cierr;
16757         ftnint ciunit;
16758         flag ciend;
16759         char *cifmt;
16760         ftnint cirec;
16761 } cilist;
16762
16763 //internal read, write//
16764 typedef struct
16765 {       flag icierr;
16766         char *iciunit;
16767         flag iciend;
16768         char *icifmt;
16769         ftnint icirlen;
16770         ftnint icirnum;
16771 } icilist;
16772
16773 //open//
16774 typedef struct
16775 {       flag oerr;
16776         ftnint ounit;
16777         char *ofnm;
16778         ftnlen ofnmlen;
16779         char *osta;
16780         char *oacc;
16781         char *ofm;
16782         ftnint orl;
16783         char *oblnk;
16784 } olist;
16785
16786 //close//
16787 typedef struct
16788 {       flag cerr;
16789         ftnint cunit;
16790         char *csta;
16791 } cllist;
16792
16793 //rewind, backspace, endfile//
16794 typedef struct
16795 {       flag aerr;
16796         ftnint aunit;
16797 } alist;
16798
16799 // inquire //
16800 typedef struct
16801 {       flag inerr;
16802         ftnint inunit;
16803         char *infile;
16804         ftnlen infilen;
16805         ftnint  *inex;  //parameters in standard's order//
16806         ftnint  *inopen;
16807         ftnint  *innum;
16808         ftnint  *innamed;
16809         char    *inname;
16810         ftnlen  innamlen;
16811         char    *inacc;
16812         ftnlen  inacclen;
16813         char    *inseq;
16814         ftnlen  inseqlen;
16815         char    *indir;
16816         ftnlen  indirlen;
16817         char    *infmt;
16818         ftnlen  infmtlen;
16819         char    *inform;
16820         ftnint  informlen;
16821         char    *inunf;
16822         ftnlen  inunflen;
16823         ftnint  *inrecl;
16824         ftnint  *innrec;
16825         char    *inblank;
16826         ftnlen  inblanklen;
16827 } inlist;
16828
16829
16830
16831 union Multitype {       // for multiple entry points //
16832         integer1 g;
16833         shortint h;
16834         integer i;
16835         // longint j; //
16836         real r;
16837         doublereal d;
16838         complex c;
16839         doublecomplex z;
16840         };
16841
16842 typedef union Multitype Multitype;
16843
16844 typedef long Long;      // No longer used; formerly in Namelist //
16845
16846 struct Vardesc {        // for Namelist //
16847         char *name;
16848         char *addr;
16849         ftnlen *dims;
16850         int  type;
16851         };
16852 typedef struct Vardesc Vardesc;
16853
16854 struct Namelist {
16855         char *name;
16856         Vardesc **vars;
16857         int nvars;
16858         };
16859 typedef struct Namelist Namelist;
16860
16861
16862
16863
16864
16865
16866
16867
16868 // procedure parameter types for -A and -C++ //
16869
16870
16871
16872
16873 typedef int // Unknown procedure type // (*U_fp)();
16874 typedef shortint (*J_fp)();
16875 typedef integer (*I_fp)();
16876 typedef real (*R_fp)();
16877 typedef doublereal (*D_fp)(), (*E_fp)();
16878 typedef // Complex // void  (*C_fp)();
16879 typedef // Double Complex // void  (*Z_fp)();
16880 typedef logical (*L_fp)();
16881 typedef shortlogical (*K_fp)();
16882 typedef // Character // void  (*H_fp)();
16883 typedef // Subroutine // int (*S_fp)();
16884
16885 // E_fp is for real functions when -R is not specified //
16886 typedef void  C_f;      // complex function //
16887 typedef void  H_f;      // character function //
16888 typedef void  Z_f;      // double complex function //
16889 typedef doublereal E_f; // real function with -R not specified //
16890
16891 // undef any lower-case symbols that your C compiler predefines, e.g.: //
16892
16893
16894 // (No such symbols should be defined in a strict ANSI C compiler.
16895    We can avoid trouble with f2c-translated code by using
16896    gcc -ansi [-traditional].) //
16897
16898
16899
16900
16901
16902
16903
16904
16905
16906
16907
16908
16909
16910
16911
16912
16913
16914
16915
16916
16917
16918
16919
16920 // Main program // MAIN__()
16921 {
16922     // System generated locals //
16923     integer i__1;
16924     real r__1, r__2;
16925     doublereal d__1, d__2;
16926     complex q__1;
16927     doublecomplex z__1, z__2, z__3;
16928     logical L__1;
16929     char ch__1[1];
16930
16931     // Builtin functions //
16932     void c_div();
16933     integer pow_ii();
16934     double pow_ri(), pow_di();
16935     void pow_ci();
16936     double pow_dd();
16937     void pow_zz();
16938     double acos(), r_imag(), r_int(), log(), r_lg10(), r_mod(), r_nint(), 
16939             asin(), atan(), atan2(), c_abs();
16940     void c_cos(), c_exp(), c_log(), r_cnjg();
16941     double cos(), cosh();
16942     void c_sin(), c_sqrt();
16943     double d_dim(), exp(), r_dim(), d_int(), d_lg10(), d_mod(), d_nint(), 
16944             d_sign(), sin(), sinh(), sqrt(), tan(), tanh();
16945     integer i_dim(), i_dnnt(), i_indx(), i_sign(), i_len();
16946     logical l_ge(), l_gt(), l_le(), l_lt();
16947     integer i_nint();
16948     double r_sign();
16949
16950     // Local variables //
16951     extern // Subroutine // int fooa_(), fooc_(), food_(), fooi_(), foor_(), 
16952             fool_(), fooz_(), getem_();
16953     static char a1[10], a2[10];
16954     static complex c1, c2;
16955     static doublereal d1, d2;
16956     static integer i1, i2;
16957     static real r1, r2;
16958
16959
16960     getem_(a1, a2, &c1, &c2, &i1, &i2, &r1, &r2, &d1, &d2, 10L, 10L);
16961 // / //
16962     i__1 = i1 / i2;
16963     fooi_(&i__1);
16964     r__1 = r1 / i1;
16965     foor_(&r__1);
16966     d__1 = d1 / i1;
16967     food_(&d__1);
16968     d__1 = (doublereal) i1;
16969     q__1.r = c1.r / d__1, q__1.i = c1.i / d__1;
16970     fooc_(&q__1);
16971     r__1 = r1 / r2;
16972     foor_(&r__1);
16973     d__1 = r1 / d1;
16974     food_(&d__1);
16975     d__1 = d1 / d2;
16976     food_(&d__1);
16977     d__1 = d1 / r1;
16978     food_(&d__1);
16979     c_div(&q__1, &c1, &c2);
16980     fooc_(&q__1);
16981     q__1.r = c1.r / r1, q__1.i = c1.i / r1;
16982     fooc_(&q__1);
16983     z__1.r = c1.r / d1, z__1.i = c1.i / d1;
16984     fooz_(&z__1);
16985 // ** //
16986     i__1 = pow_ii(&i1, &i2);
16987     fooi_(&i__1);
16988     r__1 = pow_ri(&r1, &i1);
16989     foor_(&r__1);
16990     d__1 = pow_di(&d1, &i1);
16991     food_(&d__1);
16992     pow_ci(&q__1, &c1, &i1);
16993     fooc_(&q__1);
16994     d__1 = (doublereal) r1;
16995     d__2 = (doublereal) r2;
16996     r__1 = pow_dd(&d__1, &d__2);
16997     foor_(&r__1);
16998     d__2 = (doublereal) r1;
16999     d__1 = pow_dd(&d__2, &d1);
17000     food_(&d__1);
17001     d__1 = pow_dd(&d1, &d2);
17002     food_(&d__1);
17003     d__2 = (doublereal) r1;
17004     d__1 = pow_dd(&d1, &d__2);
17005     food_(&d__1);
17006     z__2.r = c1.r, z__2.i = c1.i;
17007     z__3.r = c2.r, z__3.i = c2.i;
17008     pow_zz(&z__1, &z__2, &z__3);
17009     q__1.r = z__1.r, q__1.i = z__1.i;
17010     fooc_(&q__1);
17011     z__2.r = c1.r, z__2.i = c1.i;
17012     z__3.r = r1, z__3.i = 0.;
17013     pow_zz(&z__1, &z__2, &z__3);
17014     q__1.r = z__1.r, q__1.i = z__1.i;
17015     fooc_(&q__1);
17016     z__2.r = c1.r, z__2.i = c1.i;
17017     z__3.r = d1, z__3.i = 0.;
17018     pow_zz(&z__1, &z__2, &z__3);
17019     fooz_(&z__1);
17020 // FFEINTRIN_impABS //
17021     r__1 = (doublereal)((  r1  ) >= 0 ? (  r1  ) : -(  r1  ))  ;
17022     foor_(&r__1);
17023 // FFEINTRIN_impACOS //
17024     r__1 = acos(r1);
17025     foor_(&r__1);
17026 // FFEINTRIN_impAIMAG //
17027     r__1 = r_imag(&c1);
17028     foor_(&r__1);
17029 // FFEINTRIN_impAINT //
17030     r__1 = r_int(&r1);
17031     foor_(&r__1);
17032 // FFEINTRIN_impALOG //
17033     r__1 = log(r1);
17034     foor_(&r__1);
17035 // FFEINTRIN_impALOG10 //
17036     r__1 = r_lg10(&r1);
17037     foor_(&r__1);
17038 // FFEINTRIN_impAMAX0 //
17039     r__1 = (real) (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17040     foor_(&r__1);
17041 // FFEINTRIN_impAMAX1 //
17042     r__1 = (doublereal)((  r1  ) >= (  r2  ) ? (  r1  ) : (  r2  ))  ;
17043     foor_(&r__1);
17044 // FFEINTRIN_impAMIN0 //
17045     r__1 = (real) (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17046     foor_(&r__1);
17047 // FFEINTRIN_impAMIN1 //
17048     r__1 = (doublereal)((  r1  ) <= (  r2  ) ? (  r1  ) : (  r2  ))  ;
17049     foor_(&r__1);
17050 // FFEINTRIN_impAMOD //
17051     r__1 = r_mod(&r1, &r2);
17052     foor_(&r__1);
17053 // FFEINTRIN_impANINT //
17054     r__1 = r_nint(&r1);
17055     foor_(&r__1);
17056 // FFEINTRIN_impASIN //
17057     r__1 = asin(r1);
17058     foor_(&r__1);
17059 // FFEINTRIN_impATAN //
17060     r__1 = atan(r1);
17061     foor_(&r__1);
17062 // FFEINTRIN_impATAN2 //
17063     r__1 = atan2(r1, r2);
17064     foor_(&r__1);
17065 // FFEINTRIN_impCABS //
17066     r__1 = c_abs(&c1);
17067     foor_(&r__1);
17068 // FFEINTRIN_impCCOS //
17069     c_cos(&q__1, &c1);
17070     fooc_(&q__1);
17071 // FFEINTRIN_impCEXP //
17072     c_exp(&q__1, &c1);
17073     fooc_(&q__1);
17074 // FFEINTRIN_impCHAR //
17075     *(unsigned char *)&ch__1[0] = i1;
17076     fooa_(ch__1, 1L);
17077 // FFEINTRIN_impCLOG //
17078     c_log(&q__1, &c1);
17079     fooc_(&q__1);
17080 // FFEINTRIN_impCONJG //
17081     r_cnjg(&q__1, &c1);
17082     fooc_(&q__1);
17083 // FFEINTRIN_impCOS //
17084     r__1 = cos(r1);
17085     foor_(&r__1);
17086 // FFEINTRIN_impCOSH //
17087     r__1 = cosh(r1);
17088     foor_(&r__1);
17089 // FFEINTRIN_impCSIN //
17090     c_sin(&q__1, &c1);
17091     fooc_(&q__1);
17092 // FFEINTRIN_impCSQRT //
17093     c_sqrt(&q__1, &c1);
17094     fooc_(&q__1);
17095 // FFEINTRIN_impDABS //
17096     d__1 = (( d1 ) >= 0 ? ( d1 ) : -( d1 )) ;
17097     food_(&d__1);
17098 // FFEINTRIN_impDACOS //
17099     d__1 = acos(d1);
17100     food_(&d__1);
17101 // FFEINTRIN_impDASIN //
17102     d__1 = asin(d1);
17103     food_(&d__1);
17104 // FFEINTRIN_impDATAN //
17105     d__1 = atan(d1);
17106     food_(&d__1);
17107 // FFEINTRIN_impDATAN2 //
17108     d__1 = atan2(d1, d2);
17109     food_(&d__1);
17110 // FFEINTRIN_impDCOS //
17111     d__1 = cos(d1);
17112     food_(&d__1);
17113 // FFEINTRIN_impDCOSH //
17114     d__1 = cosh(d1);
17115     food_(&d__1);
17116 // FFEINTRIN_impDDIM //
17117     d__1 = d_dim(&d1, &d2);
17118     food_(&d__1);
17119 // FFEINTRIN_impDEXP //
17120     d__1 = exp(d1);
17121     food_(&d__1);
17122 // FFEINTRIN_impDIM //
17123     r__1 = r_dim(&r1, &r2);
17124     foor_(&r__1);
17125 // FFEINTRIN_impDINT //
17126     d__1 = d_int(&d1);
17127     food_(&d__1);
17128 // FFEINTRIN_impDLOG //
17129     d__1 = log(d1);
17130     food_(&d__1);
17131 // FFEINTRIN_impDLOG10 //
17132     d__1 = d_lg10(&d1);
17133     food_(&d__1);
17134 // FFEINTRIN_impDMAX1 //
17135     d__1 = (( d1 ) >= ( d2 ) ? ( d1 ) : ( d2 )) ;
17136     food_(&d__1);
17137 // FFEINTRIN_impDMIN1 //
17138     d__1 = (( d1 ) <= ( d2 ) ? ( d1 ) : ( d2 )) ;
17139     food_(&d__1);
17140 // FFEINTRIN_impDMOD //
17141     d__1 = d_mod(&d1, &d2);
17142     food_(&d__1);
17143 // FFEINTRIN_impDNINT //
17144     d__1 = d_nint(&d1);
17145     food_(&d__1);
17146 // FFEINTRIN_impDPROD //
17147     d__1 = (doublereal) r1 * r2;
17148     food_(&d__1);
17149 // FFEINTRIN_impDSIGN //
17150     d__1 = d_sign(&d1, &d2);
17151     food_(&d__1);
17152 // FFEINTRIN_impDSIN //
17153     d__1 = sin(d1);
17154     food_(&d__1);
17155 // FFEINTRIN_impDSINH //
17156     d__1 = sinh(d1);
17157     food_(&d__1);
17158 // FFEINTRIN_impDSQRT //
17159     d__1 = sqrt(d1);
17160     food_(&d__1);
17161 // FFEINTRIN_impDTAN //
17162     d__1 = tan(d1);
17163     food_(&d__1);
17164 // FFEINTRIN_impDTANH //
17165     d__1 = tanh(d1);
17166     food_(&d__1);
17167 // FFEINTRIN_impEXP //
17168     r__1 = exp(r1);
17169     foor_(&r__1);
17170 // FFEINTRIN_impIABS //
17171     i__1 = (( i1 ) >= 0 ? ( i1 ) : -( i1 )) ;
17172     fooi_(&i__1);
17173 // FFEINTRIN_impICHAR //
17174     i__1 = *(unsigned char *)a1;
17175     fooi_(&i__1);
17176 // FFEINTRIN_impIDIM //
17177     i__1 = i_dim(&i1, &i2);
17178     fooi_(&i__1);
17179 // FFEINTRIN_impIDNINT //
17180     i__1 = i_dnnt(&d1);
17181     fooi_(&i__1);
17182 // FFEINTRIN_impINDEX //
17183     i__1 = i_indx(a1, a2, 10L, 10L);
17184     fooi_(&i__1);
17185 // FFEINTRIN_impISIGN //
17186     i__1 = i_sign(&i1, &i2);
17187     fooi_(&i__1);
17188 // FFEINTRIN_impLEN //
17189     i__1 = i_len(a1, 10L);
17190     fooi_(&i__1);
17191 // FFEINTRIN_impLGE //
17192     L__1 = l_ge(a1, a2, 10L, 10L);
17193     fool_(&L__1);
17194 // FFEINTRIN_impLGT //
17195     L__1 = l_gt(a1, a2, 10L, 10L);
17196     fool_(&L__1);
17197 // FFEINTRIN_impLLE //
17198     L__1 = l_le(a1, a2, 10L, 10L);
17199     fool_(&L__1);
17200 // FFEINTRIN_impLLT //
17201     L__1 = l_lt(a1, a2, 10L, 10L);
17202     fool_(&L__1);
17203 // FFEINTRIN_impMAX0 //
17204     i__1 = (( i1 ) >= ( i2 ) ? ( i1 ) : ( i2 )) ;
17205     fooi_(&i__1);
17206 // FFEINTRIN_impMAX1 //
17207     i__1 = (integer) (doublereal)((  r1  ) >= (  r2  ) ? (  r1  ) : (  r2  ))  ;
17208     fooi_(&i__1);
17209 // FFEINTRIN_impMIN0 //
17210     i__1 = (( i1 ) <= ( i2 ) ? ( i1 ) : ( i2 )) ;
17211     fooi_(&i__1);
17212 // FFEINTRIN_impMIN1 //
17213     i__1 = (integer) (doublereal)((  r1  ) <= (  r2  ) ? (  r1  ) : (  r2  ))  ;
17214     fooi_(&i__1);
17215 // FFEINTRIN_impMOD //
17216     i__1 = i1 % i2;
17217     fooi_(&i__1);
17218 // FFEINTRIN_impNINT //
17219     i__1 = i_nint(&r1);
17220     fooi_(&i__1);
17221 // FFEINTRIN_impSIGN //
17222     r__1 = r_sign(&r1, &r2);
17223     foor_(&r__1);
17224 // FFEINTRIN_impSIN //
17225     r__1 = sin(r1);
17226     foor_(&r__1);
17227 // FFEINTRIN_impSINH //
17228     r__1 = sinh(r1);
17229     foor_(&r__1);
17230 // FFEINTRIN_impSQRT //
17231     r__1 = sqrt(r1);
17232     foor_(&r__1);
17233 // FFEINTRIN_impTAN //
17234     r__1 = tan(r1);
17235     foor_(&r__1);
17236 // FFEINTRIN_impTANH //
17237     r__1 = tanh(r1);
17238     foor_(&r__1);
17239 // FFEINTRIN_imp_CMPLX_C //
17240     r__1 = c1.r;
17241     r__2 = c2.r;
17242     q__1.r = r__1, q__1.i = r__2;
17243     fooc_(&q__1);
17244 // FFEINTRIN_imp_CMPLX_D //
17245     z__1.r = d1, z__1.i = d2;
17246     fooz_(&z__1);
17247 // FFEINTRIN_imp_CMPLX_I //
17248     r__1 = (real) i1;
17249     r__2 = (real) i2;
17250     q__1.r = r__1, q__1.i = r__2;
17251     fooc_(&q__1);
17252 // FFEINTRIN_imp_CMPLX_R //
17253     q__1.r = r1, q__1.i = r2;
17254     fooc_(&q__1);
17255 // FFEINTRIN_imp_DBLE_C //
17256     d__1 = (doublereal) c1.r;
17257     food_(&d__1);
17258 // FFEINTRIN_imp_DBLE_D //
17259     d__1 = d1;
17260     food_(&d__1);
17261 // FFEINTRIN_imp_DBLE_I //
17262     d__1 = (doublereal) i1;
17263     food_(&d__1);
17264 // FFEINTRIN_imp_DBLE_R //
17265     d__1 = (doublereal) r1;
17266     food_(&d__1);
17267 // FFEINTRIN_imp_INT_C //
17268     i__1 = (integer) c1.r;
17269     fooi_(&i__1);
17270 // FFEINTRIN_imp_INT_D //
17271     i__1 = (integer) d1;
17272     fooi_(&i__1);
17273 // FFEINTRIN_imp_INT_I //
17274     i__1 = i1;
17275     fooi_(&i__1);
17276 // FFEINTRIN_imp_INT_R //
17277     i__1 = (integer) r1;
17278     fooi_(&i__1);
17279 // FFEINTRIN_imp_REAL_C //
17280     r__1 = c1.r;
17281     foor_(&r__1);
17282 // FFEINTRIN_imp_REAL_D //
17283     r__1 = (real) d1;
17284     foor_(&r__1);
17285 // FFEINTRIN_imp_REAL_I //
17286     r__1 = (real) i1;
17287     foor_(&r__1);
17288 // FFEINTRIN_imp_REAL_R //
17289     r__1 = r1;
17290     foor_(&r__1);
17291
17292 // FFEINTRIN_imp_INT_D: //
17293
17294 // FFEINTRIN_specIDINT //
17295     i__1 = (integer) d1;
17296     fooi_(&i__1);
17297
17298 // FFEINTRIN_imp_INT_R: //
17299
17300 // FFEINTRIN_specIFIX //
17301     i__1 = (integer) r1;
17302     fooi_(&i__1);
17303 // FFEINTRIN_specINT //
17304     i__1 = (integer) r1;
17305     fooi_(&i__1);
17306
17307 // FFEINTRIN_imp_REAL_D: //
17308
17309 // FFEINTRIN_specSNGL //
17310     r__1 = (real) d1;
17311     foor_(&r__1);
17312
17313 // FFEINTRIN_imp_REAL_I: //
17314
17315 // FFEINTRIN_specFLOAT //
17316     r__1 = (real) i1;
17317     foor_(&r__1);
17318 // FFEINTRIN_specREAL //
17319     r__1 = (real) i1;
17320     foor_(&r__1);
17321
17322 } // MAIN__ //
17323
17324 -------- (end output file from f2c)
17325
17326 */