OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / f / ste.c
1 /* ste.c -- Implementation File (module.c template V1.0)
2    Copyright (C) 1995, 1996, 2000, 2002 Free Software Foundation, Inc.
3    Contributed by James Craig Burley.
4
5 This file is part of GNU Fortran.
6
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21
22    Related Modules:
23       ste.c
24
25    Description:
26       Implements the various statements and such like.
27
28    Modifications:
29 */
30
31 /* Include files. */
32
33 #include "proj.h"
34 #include "rtl.h"
35 #include "toplev.h"
36 #include "ggc.h"
37 #include "ste.h"
38 #include "bld.h"
39 #include "com.h"
40 #include "expr.h"
41 #include "lab.h"
42 #include "lex.h"
43 #include "sta.h"
44 #include "stp.h"
45 #include "str.h"
46 #include "sts.h"
47 #include "stt.h"
48 #include "stv.h"
49 #include "stw.h"
50 #include "symbol.h"
51
52 /* Externals defined here. */
53
54
55 /* Simple definitions and enumerations. */
56
57 typedef enum
58   {
59     FFESTE_stateletSIMPLE_,     /* Expecting simple/start. */
60     FFESTE_stateletATTRIB_,     /* Expecting attrib/item/itemstart. */
61     FFESTE_stateletITEM_,       /* Expecting item/itemstart/finish. */
62     FFESTE_stateletITEMVALS_,   /* Expecting itemvalue/itemendvals. */
63     FFESTE_
64   } ffesteStatelet_;
65
66 /* Internal typedefs. */
67
68
69 /* Private include files. */
70
71
72 /* Internal structure definitions. */
73
74
75 /* Static objects accessed by functions in this module. */
76
77 static ffesteStatelet_ ffeste_statelet_ = FFESTE_stateletSIMPLE_;
78 static ffelab ffeste_label_formatdef_ = NULL;
79 static tree (*ffeste_io_driver_) (ffebld expr); /* do?io. */
80 static ffecomGfrt ffeste_io_endgfrt_;   /* end function to call. */
81 static tree ffeste_io_abort_;   /* abort-io label or NULL_TREE. */
82 static bool ffeste_io_abort_is_temp_;   /* abort-io label is a temp. */
83 static tree ffeste_io_end_;     /* END= label or NULL_TREE. */
84 static tree ffeste_io_err_;     /* ERR= label or NULL_TREE. */
85 static tree ffeste_io_iostat_;  /* IOSTAT= var or NULL_TREE. */
86 static bool ffeste_io_iostat_is_temp_;  /* IOSTAT= var is a temp. */
87
88 /* Static functions (internal). */
89
90 static void ffeste_begin_iterdo_ (ffestw block, tree *tvar, tree *tincr,
91                                   tree *xitersvar, ffebld var,
92                                   ffebld start, ffelexToken start_token,
93                                   ffebld end, ffelexToken end_token,
94                                   ffebld incr, ffelexToken incr_token,
95                                   const char *msg);
96 static void ffeste_end_iterdo_ (ffestw block, tree tvar, tree tincr,
97                                 tree itersvar);
98 static void ffeste_io_call_ (tree call, bool do_check);
99 static void ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token);
100 static tree ffeste_io_dofio_ (ffebld expr);
101 static tree ffeste_io_dolio_ (ffebld expr);
102 static tree ffeste_io_douio_ (ffebld expr);
103 static tree ffeste_io_ialist_ (bool have_err, ffestvUnit unit,
104                                ffebld unit_expr, int unit_dflt);
105 static tree ffeste_io_cilist_ (bool have_err, ffestvUnit unit,
106                                ffebld unit_expr, int unit_dflt,
107                                bool have_end, ffestvFormat format,
108                                ffestpFile *format_spec, bool rec,
109                                ffebld rec_expr);
110 static tree ffeste_io_cllist_ (bool have_err, ffebld unit_expr,
111                                ffestpFile *stat_spec);
112 static tree ffeste_io_icilist_ (bool have_err, ffebld unit_expr,
113                                 bool have_end, ffestvFormat format,
114                                 ffestpFile *format_spec);
115 static tree ffeste_io_inlist_ (bool have_err,
116                                ffestpFile *unit_spec,
117                                ffestpFile *file_spec,
118                                ffestpFile *exist_spec,
119                                ffestpFile *open_spec,
120                                ffestpFile *number_spec,
121                                ffestpFile *named_spec,
122                                ffestpFile *name_spec,
123                                ffestpFile *access_spec,
124                                ffestpFile *sequential_spec,
125                                ffestpFile *direct_spec,
126                                ffestpFile *form_spec,
127                                ffestpFile *formatted_spec,
128                                ffestpFile *unformatted_spec,
129                                ffestpFile *recl_spec,
130                                ffestpFile *nextrec_spec,
131                                ffestpFile *blank_spec);
132 static tree ffeste_io_olist_ (bool have_err, ffebld unit_expr,
133                               ffestpFile *file_spec,
134                               ffestpFile *stat_spec,
135                               ffestpFile *access_spec,
136                               ffestpFile *form_spec,
137                               ffestpFile *recl_spec,
138                               ffestpFile *blank_spec);
139 static void ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt);
140
141 /* Internal macros. */
142
143 #define ffeste_emit_line_note_() \
144   emit_line_note (input_filename, lineno)
145 #define ffeste_check_simple_() \
146   assert(ffeste_statelet_ == FFESTE_stateletSIMPLE_)
147 #define ffeste_check_start_() \
148   assert(ffeste_statelet_ == FFESTE_stateletSIMPLE_); \
149   ffeste_statelet_ = FFESTE_stateletATTRIB_
150 #define ffeste_check_attrib_() \
151   assert(ffeste_statelet_ == FFESTE_stateletATTRIB_)
152 #define ffeste_check_item_() \
153   assert(ffeste_statelet_ == FFESTE_stateletATTRIB_      \
154          || ffeste_statelet_ == FFESTE_stateletITEM_); \
155   ffeste_statelet_ = FFESTE_stateletITEM_
156 #define ffeste_check_item_startvals_() \
157   assert(ffeste_statelet_ == FFESTE_stateletATTRIB_      \
158          || ffeste_statelet_ == FFESTE_stateletITEM_); \
159   ffeste_statelet_ = FFESTE_stateletITEMVALS_
160 #define ffeste_check_item_value_() \
161   assert(ffeste_statelet_ == FFESTE_stateletITEMVALS_)
162 #define ffeste_check_item_endvals_() \
163   assert(ffeste_statelet_ == FFESTE_stateletITEMVALS_); \
164   ffeste_statelet_ = FFESTE_stateletITEM_
165 #define ffeste_check_finish_() \
166   assert(ffeste_statelet_ == FFESTE_stateletATTRIB_      \
167          || ffeste_statelet_ == FFESTE_stateletITEM_); \
168   ffeste_statelet_ = FFESTE_stateletSIMPLE_
169
170 #define ffeste_f2c_init_charnolen_(Exp,Init,Spec)                             \
171   do                                                                          \
172     {                                                                         \
173       if ((Spec)->kw_or_val_present)                                          \
174         Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, &ignore);         \
175       else                                                                    \
176         Exp = null_pointer_node;                                              \
177       if (Exp)                                                                \
178         Init = Exp;                                                           \
179       else                                                                    \
180         {                                                                     \
181           Init = null_pointer_node;                                           \
182           constantp = FALSE;                                                  \
183         }                                                                     \
184     } while(0)
185
186 #define ffeste_f2c_init_char_(Exp,Init,Lenexp,Leninit,Spec)                   \
187   do                                                                          \
188     {                                                                         \
189       if ((Spec)->kw_or_val_present)                                          \
190         Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, &Lenexp);         \
191       else                                                                    \
192         {                                                                     \
193           Exp = null_pointer_node;                                            \
194           Lenexp = ffecom_f2c_ftnlen_zero_node;                               \
195         }                                                                     \
196       if (Exp)                                                                \
197         Init = Exp;                                                           \
198       else                                                                    \
199         {                                                                     \
200           Init = null_pointer_node;                                           \
201           constantp = FALSE;                                                  \
202         }                                                                     \
203       if (Lenexp)                                                             \
204         Leninit = Lenexp;                                                     \
205       else                                                                    \
206         {                                                                     \
207           Leninit = ffecom_f2c_ftnlen_zero_node;                              \
208           constantp = FALSE;                                                  \
209         }                                                                     \
210     } while(0)
211
212 #define ffeste_f2c_init_flag_(Flag,Init)                                      \
213   do                                                                          \
214     {                                                                         \
215       Init = convert (ffecom_f2c_flag_type_node,                              \
216                       (Flag) ? integer_one_node : integer_zero_node);         \
217     } while(0)
218
219 #define ffeste_f2c_init_format_(Exp,Init,Spec)                                \
220   do                                                                          \
221     {                                                                         \
222       Exp = ffecom_arg_ptr_to_const_expr ((Spec)->u.expr, NULL);              \
223       if (Exp)                                                                \
224         Init = Exp;                                                           \
225       else                                                                    \
226         {                                                                     \
227           Init = null_pointer_node;                                           \
228           constantp = FALSE;                                                  \
229         }                                                                     \
230     } while(0)
231
232 #define ffeste_f2c_init_int_(Exp,Init,Spec)                                   \
233   do                                                                          \
234     {                                                                         \
235       if ((Spec)->kw_or_val_present)                                          \
236         Exp = ffecom_const_expr ((Spec)->u.expr);                             \
237       else                                                                    \
238         Exp = ffecom_integer_zero_node;                                       \
239       if (Exp)                                                                \
240         Init = Exp;                                                           \
241       else                                                                    \
242         {                                                                     \
243           Init = ffecom_integer_zero_node;                                    \
244           constantp = FALSE;                                                  \
245         }                                                                     \
246     } while(0)
247
248 #define ffeste_f2c_init_ptrtoint_(Exp,Init,Spec)                              \
249   do                                                                          \
250     {                                                                         \
251       if ((Spec)->kw_or_val_present)                                          \
252         Exp = ffecom_ptr_to_const_expr ((Spec)->u.expr);                      \
253       else                                                                    \
254         Exp = null_pointer_node;                                              \
255       if (Exp)                                                                \
256         Init = Exp;                                                           \
257       else                                                                    \
258         {                                                                     \
259           Init = null_pointer_node;                                           \
260           constantp = FALSE;                                                  \
261         }                                                                     \
262     } while(0)
263
264 #define ffeste_f2c_init_next_(Init)                                           \
265   do                                                                          \
266     {                                                                         \
267       TREE_CHAIN (initn) = build_tree_list ((field = TREE_CHAIN (field)),     \
268                                             (Init));                          \
269       initn = TREE_CHAIN(initn);                                              \
270     } while(0)
271
272 #define ffeste_f2c_prepare_charnolen_(Spec,Exp)                               \
273   do                                                                          \
274     {                                                                         \
275       if (! (Exp))                                                            \
276         ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr);                      \
277     } while(0)
278
279 #define ffeste_f2c_prepare_char_(Spec,Exp)                                    \
280   do                                                                          \
281     {                                                                         \
282       if (! (Exp))                                                            \
283         ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr);                      \
284     } while(0)
285
286 #define ffeste_f2c_prepare_format_(Spec,Exp)                                  \
287   do                                                                          \
288     {                                                                         \
289       if (! (Exp))                                                            \
290         ffecom_prepare_arg_ptr_to_expr ((Spec)->u.expr);                      \
291     } while(0)
292
293 #define ffeste_f2c_prepare_int_(Spec,Exp)                                     \
294   do                                                                          \
295     {                                                                         \
296       if (! (Exp))                                                            \
297         ffecom_prepare_expr ((Spec)->u.expr);                                 \
298     } while(0)
299
300 #define ffeste_f2c_prepare_ptrtoint_(Spec,Exp)                                \
301   do                                                                          \
302     {                                                                         \
303       if (! (Exp))                                                            \
304         ffecom_prepare_ptr_to_expr ((Spec)->u.expr);                          \
305     } while(0)
306
307 #define ffeste_f2c_compile_(Field,Exp)                                        \
308   do                                                                          \
309     {                                                                         \
310       tree exz;                                                               \
311       if ((Exp))                                                              \
312         {                                                                     \
313           exz = ffecom_modify (void_type_node,                                \
314                                ffecom_2 (COMPONENT_REF, TREE_TYPE (Field),    \
315                                          t, (Field)),                         \
316                                (Exp));                                        \
317           expand_expr_stmt (exz);                                             \
318         }                                                                     \
319     } while(0)
320
321 #define ffeste_f2c_compile_charnolen_(Field,Spec,Exp)                         \
322   do                                                                          \
323     {                                                                         \
324       tree exq;                                                               \
325       if (! (Exp))                                                            \
326         {                                                                     \
327           exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, &ignore);             \
328           ffeste_f2c_compile_ ((Field), exq);                                 \
329         }                                                                     \
330     } while(0)
331
332 #define ffeste_f2c_compile_char_(Field,Lenfield,Spec,Exp,Lenexp)              \
333   do                                                                          \
334     {                                                                         \
335       tree exq = (Exp);                                                       \
336       tree lenexq = (Lenexp);                                                 \
337       int need_exq = (! exq);                                                 \
338       int need_lenexq = (! lenexq);                                           \
339       if (need_exq || need_lenexq)                                            \
340         {                                                                     \
341           exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, &lenexq);             \
342           if (need_exq)                                                       \
343             ffeste_f2c_compile_ ((Field), exq);                               \
344           if (need_lenexq)                                                    \
345             ffeste_f2c_compile_ ((Lenfield), lenexq);                         \
346         }                                                                     \
347     } while(0)
348
349 #define ffeste_f2c_compile_format_(Field,Spec,Exp)                            \
350   do                                                                          \
351     {                                                                         \
352       tree exq;                                                               \
353       if (! (Exp))                                                            \
354         {                                                                     \
355           exq = ffecom_arg_ptr_to_expr ((Spec)->u.expr, NULL);                \
356           ffeste_f2c_compile_ ((Field), exq);                                 \
357         }                                                                     \
358     } while(0)
359
360 #define ffeste_f2c_compile_int_(Field,Spec,Exp)                               \
361   do                                                                          \
362     {                                                                         \
363       tree exq;                                                               \
364       if (! (Exp))                                                            \
365         {                                                                     \
366           exq = ffecom_expr ((Spec)->u.expr);                                 \
367           ffeste_f2c_compile_ ((Field), exq);                                 \
368         }                                                                     \
369     } while(0)
370
371 #define ffeste_f2c_compile_ptrtoint_(Field,Spec,Exp)                          \
372   do                                                                          \
373     {                                                                         \
374       tree exq;                                                               \
375       if (! (Exp))                                                            \
376         {                                                                     \
377           exq = ffecom_ptr_to_expr ((Spec)->u.expr);                          \
378           ffeste_f2c_compile_ ((Field), exq);                                 \
379         }                                                                     \
380     } while(0)
381 \f
382 /* Start a Fortran block.  */
383
384 #ifdef ENABLE_CHECKING
385
386 typedef struct gbe_block
387 {
388   struct gbe_block *outer;
389   ffestw block;
390   int lineno;
391   const char *input_filename;
392   bool is_stmt;
393 } *gbe_block;
394
395 gbe_block ffeste_top_block_ = NULL;
396
397 static void
398 ffeste_start_block_ (ffestw block)
399 {
400   gbe_block b = xmalloc (sizeof (*b));
401
402   b->outer = ffeste_top_block_;
403   b->block = block;
404   b->lineno = lineno;
405   b->input_filename = input_filename;
406   b->is_stmt = FALSE;
407
408   ffeste_top_block_ = b;
409
410   ffecom_start_compstmt ();
411 }
412
413 /* End a Fortran block.  */
414
415 static void
416 ffeste_end_block_ (ffestw block)
417 {
418   gbe_block b = ffeste_top_block_;
419
420   assert (b);
421   assert (! b->is_stmt);
422   assert (b->block == block);
423   assert (! b->is_stmt);
424
425   ffeste_top_block_ = b->outer;
426
427   free (b);
428
429   ffecom_end_compstmt ();
430 }
431
432 /* Start a Fortran statement.
433
434    Starts a back-end block, so temporaries can be managed, clean-ups
435    properly handled, etc.  Nesting of statements *is* allowed -- the
436    handling of I/O items, even implied-DO I/O lists, within a READ,
437    PRINT, or WRITE statement is one example.  */
438
439 static void
440 ffeste_start_stmt_(void)
441 {
442   gbe_block b = xmalloc (sizeof (*b));
443
444   b->outer = ffeste_top_block_;
445   b->block = NULL;
446   b->lineno = lineno;
447   b->input_filename = input_filename;
448   b->is_stmt = TRUE;
449
450   ffeste_top_block_ = b;
451
452   ffecom_start_compstmt ();
453 }
454
455 /* End a Fortran statement.  */
456
457 static void
458 ffeste_end_stmt_(void)
459 {
460   gbe_block b = ffeste_top_block_;
461
462   assert (b);
463   assert (b->is_stmt);
464
465   ffeste_top_block_ = b->outer;
466
467   free (b);
468
469   ffecom_end_compstmt ();
470 }
471
472 #else  /* ! defined (ENABLE_CHECKING) */
473
474 #define ffeste_start_block_(b) ffecom_start_compstmt ()
475 #define ffeste_end_block_(b)    \
476   do                            \
477     {                           \
478       ffecom_end_compstmt ();   \
479     } while(0)
480 #define ffeste_start_stmt_() ffeste_start_block_(NULL)
481 #define ffeste_end_stmt_() ffeste_end_block_(NULL)
482
483 #endif  /* ! defined (ENABLE_CHECKING) */
484
485 /* Begin an iterative DO loop.  Pass the block to start if
486    applicable.  */
487
488 static void
489 ffeste_begin_iterdo_ (ffestw block, tree *xtvar, tree *xtincr,
490                       tree *xitersvar, ffebld var,
491                       ffebld start, ffelexToken start_token,
492                       ffebld end, ffelexToken end_token,
493                       ffebld incr, ffelexToken incr_token,
494                       const char *msg)
495 {
496   tree tvar;
497   tree expr;
498   tree tstart;
499   tree tend;
500   tree tincr;
501   tree tincr_saved;
502   tree niters;
503   struct nesting *expanded_loop;
504
505   /* Want to have tvar, tincr, and niters for the whole loop body. */
506
507   if (block)
508     ffeste_start_block_ (block);
509   else
510     ffeste_start_stmt_ ();
511
512   niters = ffecom_make_tempvar (block ? "do" : "impdo",
513                                 ffecom_integer_type_node,
514                                 FFETARGET_charactersizeNONE, -1);
515
516   ffecom_prepare_expr (incr);
517   ffecom_prepare_expr_rw (NULL_TREE, var);
518
519   ffecom_prepare_end ();
520
521   tvar = ffecom_expr_rw (NULL_TREE, var);
522   tincr = ffecom_expr (incr);
523
524   if (TREE_CODE (tvar) == ERROR_MARK
525       || TREE_CODE (tincr) == ERROR_MARK)
526     {
527       if (block)
528         {
529           ffeste_end_block_ (block);
530           ffestw_set_do_tvar (block, error_mark_node);
531         }
532       else
533         {
534           ffeste_end_stmt_ ();
535           *xtvar = error_mark_node;
536         }
537       return;
538     }
539
540   /* Check whether incr is known to be zero, complain and fix.  */
541
542   if (integer_zerop (tincr) || real_zerop (tincr))
543     {
544       ffebad_start (FFEBAD_DO_STEP_ZERO);
545       ffebad_here (0, ffelex_token_where_line (incr_token),
546                    ffelex_token_where_column (incr_token));
547       ffebad_string (msg);
548       ffebad_finish ();
549       tincr = convert (TREE_TYPE (tvar), integer_one_node);
550     }
551
552   tincr_saved = ffecom_save_tree (tincr);
553
554   /* Want to have tstart, tend for just this statement. */
555
556   ffeste_start_stmt_ ();
557
558   ffecom_prepare_expr (start);
559   ffecom_prepare_expr (end);
560
561   ffecom_prepare_end ();
562
563   tstart = ffecom_expr (start);
564   tend = ffecom_expr (end);
565
566   if (TREE_CODE (tstart) == ERROR_MARK
567       || TREE_CODE (tend) == ERROR_MARK)
568     {
569       ffeste_end_stmt_ ();
570
571       if (block)
572         {
573           ffeste_end_block_ (block);
574           ffestw_set_do_tvar (block, error_mark_node);
575         }
576       else
577         {
578           ffeste_end_stmt_ ();
579           *xtvar = error_mark_node;
580         }
581       return;
582     }
583
584   /* For warnings only, nothing else happens here.  */
585   {
586     tree try;
587
588     if (! ffe_is_onetrip ())
589       {
590         try = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
591                         tend,
592                         tstart);
593
594         try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
595                         try,
596                         tincr);
597
598         if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
599           try = ffecom_2 (TRUNC_DIV_EXPR, integer_type_node, try,
600                           tincr);
601         else
602           try = convert (integer_type_node,
603                          ffecom_2 (RDIV_EXPR, TREE_TYPE (tvar),
604                                    try,
605                                    tincr));
606
607         /* Warn if loop never executed, since we've done the evaluation
608            of the unofficial iteration count already.  */
609
610         try = ffecom_truth_value (ffecom_2 (LE_EXPR, integer_type_node,
611                                             try,
612                                             convert (TREE_TYPE (tvar),
613                                                      integer_zero_node)));
614
615         if (integer_onep (try))
616           {
617             ffebad_start (FFEBAD_DO_NULL);
618             ffebad_here (0, ffelex_token_where_line (start_token),
619                          ffelex_token_where_column (start_token));
620             ffebad_string (msg);
621             ffebad_finish ();
622           }
623       }
624
625     /* Warn if end plus incr would overflow.  */
626
627     try = ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
628                     tend,
629                     tincr);
630
631     if ((TREE_CODE_CLASS (TREE_CODE (try)) == 'c')
632         && TREE_CONSTANT_OVERFLOW (try))
633       {
634         ffebad_start (FFEBAD_DO_END_OVERFLOW);
635         ffebad_here (0, ffelex_token_where_line (end_token),
636                      ffelex_token_where_column (end_token));
637         ffebad_string (msg);
638         ffebad_finish ();
639       }
640   }
641
642   /* Do the initial assignment into the DO var.  */
643
644   tstart = ffecom_save_tree (tstart);
645
646   expr = ffecom_2 (MINUS_EXPR, TREE_TYPE (tvar),
647                    tend,
648                    tstart);
649
650   if (! ffe_is_onetrip ())
651     {
652       expr = ffecom_2 (PLUS_EXPR, TREE_TYPE (expr),
653                        expr,
654                        convert (TREE_TYPE (expr), tincr_saved));
655     }
656
657   if (TREE_CODE (TREE_TYPE (tvar)) != REAL_TYPE)
658     expr = ffecom_2 (TRUNC_DIV_EXPR, TREE_TYPE (expr),
659                      expr,
660                      tincr_saved);
661   else
662     expr = ffecom_2 (RDIV_EXPR, TREE_TYPE (expr),
663                      expr,
664                      tincr_saved);
665
666 #if 1   /* New, F90-approved approach: convert to default INTEGER. */
667   if (TREE_TYPE (tvar) != error_mark_node)
668     expr = convert (ffecom_integer_type_node, expr);
669 #else   /* Old approach; convert to INTEGER unless that's a narrowing. */
670   if ((TREE_TYPE (tvar) != error_mark_node)
671       && ((TREE_CODE (TREE_TYPE (tvar)) != INTEGER_TYPE)
672           || ((TYPE_SIZE (TREE_TYPE (tvar)) != NULL_TREE)
673               && ((TREE_CODE (TYPE_SIZE (TREE_TYPE (tvar)))
674                    != INTEGER_CST)
675                   || (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tvar)))
676                       <= TREE_INT_CST_LOW (TYPE_SIZE (ffecom_integer_type_node)))))))
677     /* Convert unless promoting INTEGER type of any kind downward to
678        default INTEGER; else leave as, say, INTEGER*8 (long long int).  */
679     expr = convert (ffecom_integer_type_node, expr);
680 #endif
681
682   assert (TYPE_MAIN_VARIANT (TREE_TYPE (niters))
683           == TYPE_MAIN_VARIANT (TREE_TYPE (expr)));
684
685   expr = ffecom_modify (void_type_node, niters, expr);
686   expand_expr_stmt (expr);
687
688   expr = ffecom_modify (void_type_node, tvar, tstart);
689   expand_expr_stmt (expr);
690
691   ffeste_end_stmt_ ();
692
693   expanded_loop = expand_start_loop_continue_elsewhere (!! block);
694   if (block)
695     ffestw_set_do_hook (block, expanded_loop);
696
697   if (! ffe_is_onetrip ())
698     {
699       expr = ffecom_truth_value
700         (ffecom_2 (GE_EXPR, integer_type_node,
701                    ffecom_2 (PREDECREMENT_EXPR,
702                              TREE_TYPE (niters),
703                              niters,
704                              convert (TREE_TYPE (niters),
705                                       ffecom_integer_one_node)),
706                    convert (TREE_TYPE (niters),
707                             ffecom_integer_zero_node)));
708
709       expand_exit_loop_top_cond (0, expr);
710     }
711
712   if (block)
713     {
714       ffestw_set_do_tvar (block, tvar);
715       ffestw_set_do_incr_saved (block, tincr_saved);
716       ffestw_set_do_count_var (block, niters);
717     }
718   else
719     {
720       *xtvar = tvar;
721       *xtincr = tincr_saved;
722       *xitersvar = niters;
723     }
724 }
725
726 /* End an iterative DO loop.  Pass the same iteration variable and increment
727    value trees that were generated in the paired _begin_ call.  */
728
729 static void
730 ffeste_end_iterdo_ (ffestw block, tree tvar, tree tincr, tree itersvar)
731 {
732   tree expr;
733   tree niters = itersvar;
734
735   if (tvar == error_mark_node)
736     return;
737
738   expand_loop_continue_here ();
739
740   ffeste_start_stmt_ ();
741
742   if (ffe_is_onetrip ())
743     {
744       expr = ffecom_truth_value
745         (ffecom_2 (GE_EXPR, integer_type_node,
746                    ffecom_2 (PREDECREMENT_EXPR,
747                              TREE_TYPE (niters),
748                              niters,
749                              convert (TREE_TYPE (niters),
750                                       ffecom_integer_one_node)),
751                    convert (TREE_TYPE (niters),
752                             ffecom_integer_zero_node)));
753
754       expand_exit_loop_if_false (0, expr);
755     }
756
757   expr = ffecom_modify (void_type_node, tvar,
758                         ffecom_2 (PLUS_EXPR, TREE_TYPE (tvar),
759                                   tvar,
760                                   tincr));
761   expand_expr_stmt (expr);
762
763   /* Lose the stuff we just built. */
764   ffeste_end_stmt_ ();
765
766   expand_end_loop ();
767
768   /* Lose the tvar and incr_saved trees. */
769   if (block)
770     ffeste_end_block_ (block);
771   else
772     ffeste_end_stmt_ ();
773 }
774
775 /* Generate call to run-time I/O routine.  */
776
777 static void
778 ffeste_io_call_ (tree call, bool do_check)
779 {
780   /* Generate the call and optional assignment into iostat var. */
781
782   TREE_SIDE_EFFECTS (call) = 1;
783   if (ffeste_io_iostat_ != NULL_TREE)
784     call = ffecom_modify (do_check ? NULL_TREE : void_type_node,
785                           ffeste_io_iostat_, call);
786   expand_expr_stmt (call);
787
788   if (! do_check
789       || ffeste_io_abort_ == NULL_TREE
790       || TREE_CODE (ffeste_io_abort_) == ERROR_MARK)
791     return;
792
793   /* Generate optional test. */
794
795   expand_start_cond (ffecom_truth_value (ffeste_io_iostat_), 0);
796   expand_goto (ffeste_io_abort_);
797   expand_end_cond ();
798 }
799
800 /* Handle implied-DO in I/O list.
801
802    Expands code to start up the DO loop.  Then for each item in the
803    DO loop, handles appropriately (possibly including recursively calling
804    itself).  Then expands code to end the DO loop.  */
805
806 static void
807 ffeste_io_impdo_ (ffebld impdo, ffelexToken impdo_token)
808 {
809   ffebld var = ffebld_head (ffebld_right (impdo));
810   ffebld start = ffebld_head (ffebld_trail (ffebld_right (impdo)));
811   ffebld end = ffebld_head (ffebld_trail (ffebld_trail
812                                           (ffebld_right (impdo))));
813   ffebld incr = ffebld_head (ffebld_trail (ffebld_trail
814                                     (ffebld_trail (ffebld_right (impdo)))));
815   ffebld list;
816   ffebld item;
817   tree tvar;
818   tree tincr;
819   tree titervar;
820
821   if (incr == NULL)
822     {
823       incr = ffebld_new_conter (ffebld_constant_new_integerdefault_val (1));
824       ffebld_set_info (incr, ffeinfo_new
825                        (FFEINFO_basictypeINTEGER,
826                         FFEINFO_kindtypeINTEGERDEFAULT,
827                         0,
828                         FFEINFO_kindENTITY,
829                         FFEINFO_whereCONSTANT,
830                         FFETARGET_charactersizeNONE));
831     }
832
833   /* Start the DO loop.  */
834
835   start = ffeexpr_convert_expr (start, impdo_token, var, impdo_token,
836                                 FFEEXPR_contextLET);
837   end = ffeexpr_convert_expr (end, impdo_token, var, impdo_token,
838                               FFEEXPR_contextLET);
839   incr = ffeexpr_convert_expr (incr, impdo_token, var, impdo_token,
840                                FFEEXPR_contextLET);
841
842   ffeste_begin_iterdo_ (NULL, &tvar, &tincr, &titervar, var,
843                         start, impdo_token,
844                         end, impdo_token,
845                         incr, impdo_token,
846                         "Implied DO loop");
847
848   /* Handle the list of items.  */
849
850   for (list = ffebld_left (impdo); list != NULL; list = ffebld_trail (list))
851     {
852       item = ffebld_head (list);
853       if (item == NULL)
854         continue;
855
856       /* Strip parens off items such as in "READ *,(A)".  This is really a bug
857          in the user's code, but I've been told lots of code does this.  */
858       while (ffebld_op (item) == FFEBLD_opPAREN)
859         item = ffebld_left (item);
860
861       if (ffebld_op (item) == FFEBLD_opANY)
862         continue;
863
864       if (ffebld_op (item) == FFEBLD_opIMPDO)
865         ffeste_io_impdo_ (item, impdo_token);
866       else
867         {
868           ffeste_start_stmt_ ();
869
870           ffecom_prepare_arg_ptr_to_expr (item);
871
872           ffecom_prepare_end ();
873
874           ffeste_io_call_ ((*ffeste_io_driver_) (item), TRUE);
875
876           ffeste_end_stmt_ ();
877         }
878     }
879
880   /* Generate end of implied-do construct. */
881
882   ffeste_end_iterdo_ (NULL, tvar, tincr, titervar);
883 }
884
885 /* I/O driver for formatted I/O item (do_fio)
886
887    Returns a tree for a CALL_EXPR to the do_fio function, which handles
888    a formatted I/O list item, along with the appropriate arguments for
889    the function.  It is up to the caller to set the TREE_SIDE_EFFECTS flag
890    for the CALL_EXPR, expand (emit) the expression, emit any assignment
891    of the result to an IOSTAT= variable, and emit any checking of the
892    result for errors.  */
893
894 static tree
895 ffeste_io_dofio_ (ffebld expr)
896 {
897   tree num_elements;
898   tree variable;
899   tree size;
900   tree arglist;
901   ffeinfoBasictype bt;
902   ffeinfoKindtype kt;
903   bool is_complex;
904
905   bt = ffeinfo_basictype (ffebld_info (expr));
906   kt = ffeinfo_kindtype (ffebld_info (expr));
907
908   if ((bt == FFEINFO_basictypeANY)
909       || (kt == FFEINFO_kindtypeANY))
910     return error_mark_node;
911
912   if (bt == FFEINFO_basictypeCOMPLEX)
913     {
914       is_complex = TRUE;
915       bt = FFEINFO_basictypeREAL;
916     }
917   else
918     is_complex = FALSE;
919
920   variable = ffecom_arg_ptr_to_expr (expr, &size);
921
922   if ((variable == error_mark_node)
923       || (size == error_mark_node))
924     return error_mark_node;
925
926   if (size == NULL_TREE)        /* Already filled in for CHARACTER type. */
927     {                           /* "(ftnlen) sizeof(type)" */
928       size = size_binop (CEIL_DIV_EXPR,
929                          TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
930                          size_int (TYPE_PRECISION (char_type_node)
931                                    / BITS_PER_UNIT));
932 #if 0   /* Assume that while it is possible that char * is wider than
933            ftnlen, no object in Fortran space can get big enough for its
934            size to be wider than ftnlen.  I really hope nobody wastes
935            time debugging a case where it can!  */
936       assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
937               >= TYPE_PRECISION (TREE_TYPE (size)));
938 #endif
939       size = convert (ffecom_f2c_ftnlen_type_node, size);
940     }
941
942   if (ffeinfo_rank (ffebld_info (expr)) == 0
943       || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
944     num_elements
945       = is_complex ? ffecom_f2c_ftnlen_two_node : ffecom_f2c_ftnlen_one_node;
946   else
947     {
948       num_elements
949         = size_binop (CEIL_DIV_EXPR,
950                       TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
951                       convert (sizetype, size));
952       num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
953                                  size_int (TYPE_PRECISION (char_type_node)
954                                            / BITS_PER_UNIT));
955       num_elements = convert (ffecom_f2c_ftnlen_type_node,
956                               num_elements);
957     }
958
959   num_elements
960     = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
961                 num_elements);
962
963   variable = convert (string_type_node, variable);
964
965   arglist = build_tree_list (NULL_TREE, num_elements);
966   TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
967   TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
968
969   return ffecom_call_gfrt (FFECOM_gfrtDOFIO, arglist, NULL_TREE);
970 }
971
972 /* I/O driver for list-directed I/O item (do_lio)
973
974    Returns a tree for a CALL_EXPR to the do_lio function, which handles
975    a list-directed I/O list item, along with the appropriate arguments for
976    the function.  It is up to the caller to set the TREE_SIDE_EFFECTS flag
977    for the CALL_EXPR, expand (emit) the expression, emit any assignment
978    of the result to an IOSTAT= variable, and emit any checking of the
979    result for errors.  */
980
981 static tree
982 ffeste_io_dolio_ (ffebld expr)
983 {
984   tree type_id;
985   tree num_elements;
986   tree variable;
987   tree size;
988   tree arglist;
989   ffeinfoBasictype bt;
990   ffeinfoKindtype kt;
991   int tc;
992
993   bt = ffeinfo_basictype (ffebld_info (expr));
994   kt = ffeinfo_kindtype (ffebld_info (expr));
995
996   if ((bt == FFEINFO_basictypeANY)
997       || (kt == FFEINFO_kindtypeANY))
998     return error_mark_node;
999
1000   tc = ffecom_f2c_typecode (bt, kt);
1001   assert (tc != -1);
1002   type_id = build_int_2 (tc, 0);
1003
1004   type_id
1005     = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnint_type_node,
1006                 convert (ffecom_f2c_ftnint_type_node,
1007                          type_id));
1008
1009   variable = ffecom_arg_ptr_to_expr (expr, &size);
1010
1011   if ((type_id == error_mark_node)
1012       || (variable == error_mark_node)
1013       || (size == error_mark_node))
1014     return error_mark_node;
1015
1016   if (size == NULL_TREE)        /* Already filled in for CHARACTER type. */
1017     {                           /* "(ftnlen) sizeof(type)" */
1018       size = size_binop (CEIL_DIV_EXPR,
1019                          TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
1020                          size_int (TYPE_PRECISION (char_type_node)
1021                                    / BITS_PER_UNIT));
1022 #if 0   /* Assume that while it is possible that char * is wider than
1023            ftnlen, no object in Fortran space can get big enough for its
1024            size to be wider than ftnlen.  I really hope nobody wastes
1025            time debugging a case where it can!  */
1026       assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
1027               >= TYPE_PRECISION (TREE_TYPE (size)));
1028 #endif
1029       size = convert (ffecom_f2c_ftnlen_type_node, size);
1030     }
1031
1032   if (ffeinfo_rank (ffebld_info (expr)) == 0
1033       || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
1034     num_elements = ffecom_integer_one_node;
1035   else
1036     {
1037       num_elements
1038         = size_binop (CEIL_DIV_EXPR,
1039                       TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
1040                       convert (sizetype, size));
1041       num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
1042                                  size_int (TYPE_PRECISION (char_type_node)
1043                                            / BITS_PER_UNIT));
1044       num_elements = convert (ffecom_f2c_ftnlen_type_node,
1045                               num_elements);
1046     }
1047
1048   num_elements
1049     = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
1050                 num_elements);
1051
1052   variable = convert (string_type_node, variable);
1053
1054   arglist = build_tree_list (NULL_TREE, type_id);
1055   TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, num_elements);
1056   TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, variable);
1057   TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))
1058     = build_tree_list (NULL_TREE, size);
1059
1060   return ffecom_call_gfrt (FFECOM_gfrtDOLIO, arglist, NULL_TREE);
1061 }
1062
1063 /* I/O driver for unformatted I/O item (do_uio)
1064
1065    Returns a tree for a CALL_EXPR to the do_uio function, which handles
1066    an unformatted I/O list item, along with the appropriate arguments for
1067    the function.  It is up to the caller to set the TREE_SIDE_EFFECTS flag
1068    for the CALL_EXPR, expand (emit) the expression, emit any assignment
1069    of the result to an IOSTAT= variable, and emit any checking of the
1070    result for errors.  */
1071
1072 static tree
1073 ffeste_io_douio_ (ffebld expr)
1074 {
1075   tree num_elements;
1076   tree variable;
1077   tree size;
1078   tree arglist;
1079   ffeinfoBasictype bt;
1080   ffeinfoKindtype kt;
1081   bool is_complex;
1082
1083   bt = ffeinfo_basictype (ffebld_info (expr));
1084   kt = ffeinfo_kindtype (ffebld_info (expr));
1085
1086   if ((bt == FFEINFO_basictypeANY)
1087       || (kt == FFEINFO_kindtypeANY))
1088     return error_mark_node;
1089
1090   if (bt == FFEINFO_basictypeCOMPLEX)
1091     {
1092       is_complex = TRUE;
1093       bt = FFEINFO_basictypeREAL;
1094     }
1095   else
1096     is_complex = FALSE;
1097
1098   variable = ffecom_arg_ptr_to_expr (expr, &size);
1099
1100   if ((variable == error_mark_node)
1101       || (size == error_mark_node))
1102     return error_mark_node;
1103
1104   if (size == NULL_TREE)        /* Already filled in for CHARACTER type. */
1105     {                           /* "(ftnlen) sizeof(type)" */
1106       size = size_binop (CEIL_DIV_EXPR,
1107                          TYPE_SIZE_UNIT (ffecom_tree_type[bt][kt]),
1108                          size_int (TYPE_PRECISION (char_type_node)
1109                                    / BITS_PER_UNIT));
1110 #if 0   /* Assume that while it is possible that char * is wider than
1111            ftnlen, no object in Fortran space can get big enough for its
1112            size to be wider than ftnlen.  I really hope nobody wastes
1113            time debugging a case where it can!  */
1114       assert (TYPE_PRECISION (ffecom_f2c_ftnlen_type_node)
1115               >= TYPE_PRECISION (TREE_TYPE (size)));
1116 #endif
1117       size = convert (ffecom_f2c_ftnlen_type_node, size);
1118     }
1119
1120   if (ffeinfo_rank (ffebld_info (expr)) == 0
1121       || TREE_CODE (TREE_TYPE (TREE_TYPE (variable))) != ARRAY_TYPE)
1122     num_elements
1123       = is_complex ? ffecom_f2c_ftnlen_two_node : ffecom_f2c_ftnlen_one_node;
1124   else
1125     {
1126       num_elements
1127         = size_binop (CEIL_DIV_EXPR,
1128                       TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (variable))),
1129                       convert (sizetype, size));
1130       num_elements = size_binop (CEIL_DIV_EXPR, num_elements,
1131                                  size_int (TYPE_PRECISION (char_type_node)
1132                                            / BITS_PER_UNIT));
1133       num_elements = convert (ffecom_f2c_ftnlen_type_node,
1134                               num_elements);
1135     }
1136
1137   num_elements
1138     = ffecom_1 (ADDR_EXPR, ffecom_f2c_ptr_to_ftnlen_type_node,
1139                 num_elements);
1140
1141   variable = convert (string_type_node, variable);
1142
1143   arglist = build_tree_list (NULL_TREE, num_elements);
1144   TREE_CHAIN (arglist) = build_tree_list (NULL_TREE, variable);
1145   TREE_CHAIN (TREE_CHAIN (arglist)) = build_tree_list (NULL_TREE, size);
1146
1147   return ffecom_call_gfrt (FFECOM_gfrtDOUIO, arglist, NULL_TREE);
1148 }
1149
1150 /* Make arglist with ptr to BACKSPACE/ENDFILE/REWIND control list.
1151
1152    Returns a tree suitable as an argument list containing a pointer to
1153    a BACKSPACE/ENDFILE/REWIND control list.  First, generates that control
1154    list, if necessary, along with any static and run-time initializations
1155    that are needed as specified by the arguments to this function.
1156
1157    Must ensure that all expressions are prepared before being evaluated,
1158    for any whose evaluation might result in the generation of temporaries.
1159
1160    Note that this means this function causes a transition, within the
1161    current block being code-generated via the back end, from the
1162    declaration of variables (temporaries) to the expanding of expressions,
1163    statements, etc.  */
1164
1165 static tree
1166 ffeste_io_ialist_ (bool have_err,
1167                    ffestvUnit unit,
1168                    ffebld unit_expr,
1169                    int unit_dflt)
1170 {
1171   static tree f2c_alist_struct = NULL_TREE;
1172   tree t;
1173   tree ttype;
1174   tree field;
1175   tree inits, initn;
1176   bool constantp = TRUE;
1177   static tree errfield, unitfield;
1178   tree errinit, unitinit;
1179   tree unitexp;
1180   static int mynumber = 0;
1181
1182   if (f2c_alist_struct == NULL_TREE)
1183     {
1184       tree ref;
1185
1186       ref = make_node (RECORD_TYPE);
1187
1188       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1189                                     ffecom_f2c_flag_type_node);
1190       unitfield = ffecom_decl_field (ref, errfield, "unit",
1191                                      ffecom_f2c_ftnint_type_node);
1192
1193       TYPE_FIELDS (ref) = errfield;
1194       layout_type (ref);
1195
1196       ggc_add_tree_root (&f2c_alist_struct, 1);
1197
1198       f2c_alist_struct = ref;
1199     }
1200
1201   /* Try to do as much compile-time initialization of the structure
1202      as possible, to save run time.  */
1203
1204   ffeste_f2c_init_flag_ (have_err, errinit);
1205
1206   switch (unit)
1207     {
1208     case FFESTV_unitNONE:
1209     case FFESTV_unitASTERISK:
1210       unitinit = build_int_2 (unit_dflt, 0);
1211       unitexp = unitinit;
1212       break;
1213
1214     case FFESTV_unitINTEXPR:
1215       unitexp = ffecom_const_expr (unit_expr);
1216       if (unitexp)
1217         unitinit = unitexp;
1218       else
1219         {
1220           unitinit = ffecom_integer_zero_node;
1221           constantp = FALSE;
1222         }
1223       break;
1224
1225     default:
1226       assert ("bad unit spec" == NULL);
1227       unitinit = ffecom_integer_zero_node;
1228       unitexp = unitinit;
1229       break;
1230     }
1231
1232   inits = build_tree_list ((field = TYPE_FIELDS (f2c_alist_struct)), errinit);
1233   initn = inits;
1234   ffeste_f2c_init_next_ (unitinit);
1235
1236   inits = build (CONSTRUCTOR, f2c_alist_struct, NULL_TREE, inits);
1237   TREE_CONSTANT (inits) = constantp ? 1 : 0;
1238   TREE_STATIC (inits) = 1;
1239
1240   t = build_decl (VAR_DECL,
1241                   ffecom_get_invented_identifier ("__g77_alist_%d",
1242                                                   mynumber++),
1243                   f2c_alist_struct);
1244   TREE_STATIC (t) = 1;
1245   t = ffecom_start_decl (t, 1);
1246   ffecom_finish_decl (t, inits, 0);
1247
1248   /* Prepare run-time expressions.  */
1249
1250   if (! unitexp)
1251     ffecom_prepare_expr (unit_expr);
1252
1253   ffecom_prepare_end ();
1254
1255   /* Now evaluate run-time expressions as needed.  */
1256
1257   if (! unitexp)
1258     {
1259       unitexp = ffecom_expr (unit_expr);
1260       ffeste_f2c_compile_ (unitfield, unitexp);
1261     }
1262
1263   ttype = build_pointer_type (TREE_TYPE (t));
1264   t = ffecom_1 (ADDR_EXPR, ttype, t);
1265
1266   t = build_tree_list (NULL_TREE, t);
1267
1268   return t;
1269 }
1270
1271 /* Make arglist with ptr to external-I/O control list.
1272
1273    Returns a tree suitable as an argument list containing a pointer to
1274    an external-I/O control list.  First, generates that control
1275    list, if necessary, along with any static and run-time initializations
1276    that are needed as specified by the arguments to this function.
1277
1278    Must ensure that all expressions are prepared before being evaluated,
1279    for any whose evaluation might result in the generation of temporaries.
1280
1281    Note that this means this function causes a transition, within the
1282    current block being code-generated via the back end, from the
1283    declaration of variables (temporaries) to the expanding of expressions,
1284    statements, etc.  */
1285
1286 static tree
1287 ffeste_io_cilist_ (bool have_err,
1288                    ffestvUnit unit,
1289                    ffebld unit_expr,
1290                    int unit_dflt,
1291                    bool have_end,
1292                    ffestvFormat format,
1293                    ffestpFile *format_spec,
1294                    bool rec,
1295                    ffebld rec_expr)
1296 {
1297   static tree f2c_cilist_struct = NULL_TREE;
1298   tree t;
1299   tree ttype;
1300   tree field;
1301   tree inits, initn;
1302   bool constantp = TRUE;
1303   static tree errfield, unitfield, endfield, formatfield, recfield;
1304   tree errinit, unitinit, endinit, formatinit, recinit;
1305   tree unitexp, formatexp, recexp;
1306   static int mynumber = 0;
1307
1308   if (f2c_cilist_struct == NULL_TREE)
1309     {
1310       tree ref;
1311
1312       ref = make_node (RECORD_TYPE);
1313
1314       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1315                                     ffecom_f2c_flag_type_node);
1316       unitfield = ffecom_decl_field (ref, errfield, "unit",
1317                                      ffecom_f2c_ftnint_type_node);
1318       endfield = ffecom_decl_field (ref, unitfield, "end",
1319                                     ffecom_f2c_flag_type_node);
1320       formatfield = ffecom_decl_field (ref, endfield, "format",
1321                                        string_type_node);
1322       recfield = ffecom_decl_field (ref, formatfield, "rec",
1323                                     ffecom_f2c_ftnint_type_node);
1324
1325       TYPE_FIELDS (ref) = errfield;
1326       layout_type (ref);
1327
1328       ggc_add_tree_root (&f2c_cilist_struct, 1);
1329
1330       f2c_cilist_struct = ref;
1331     }
1332
1333   /* Try to do as much compile-time initialization of the structure
1334      as possible, to save run time.  */
1335
1336   ffeste_f2c_init_flag_ (have_err, errinit);
1337
1338   switch (unit)
1339     {
1340     case FFESTV_unitNONE:
1341     case FFESTV_unitASTERISK:
1342       unitinit = build_int_2 (unit_dflt, 0);
1343       unitexp = unitinit;
1344       break;
1345
1346     case FFESTV_unitINTEXPR:
1347       unitexp = ffecom_const_expr (unit_expr);
1348       if (unitexp)
1349         unitinit = unitexp;
1350       else
1351         {
1352           unitinit = ffecom_integer_zero_node;
1353           constantp = FALSE;
1354         }
1355       break;
1356
1357     default:
1358       assert ("bad unit spec" == NULL);
1359       unitinit = ffecom_integer_zero_node;
1360       unitexp = unitinit;
1361       break;
1362     }
1363
1364   switch (format)
1365     {
1366     case FFESTV_formatNONE:
1367       formatinit = null_pointer_node;
1368       formatexp = formatinit;
1369       break;
1370
1371     case FFESTV_formatLABEL:
1372       formatexp = error_mark_node;
1373       formatinit = ffecom_lookup_label (format_spec->u.label);
1374       if ((formatinit == NULL_TREE)
1375           || (TREE_CODE (formatinit) == ERROR_MARK))
1376         break;
1377       formatinit = ffecom_1 (ADDR_EXPR,
1378                              build_pointer_type (void_type_node),
1379                              formatinit);
1380       TREE_CONSTANT (formatinit) = 1;
1381       break;
1382
1383     case FFESTV_formatCHAREXPR:
1384       formatexp = ffecom_arg_ptr_to_const_expr (format_spec->u.expr, NULL);
1385       if (formatexp)
1386         formatinit = formatexp;
1387       else
1388         {
1389           formatinit = null_pointer_node;
1390           constantp = FALSE;
1391         }
1392       break;
1393
1394     case FFESTV_formatASTERISK:
1395       formatinit = null_pointer_node;
1396       formatexp = formatinit;
1397       break;
1398
1399     case FFESTV_formatINTEXPR:
1400       formatinit = null_pointer_node;
1401       formatexp = ffecom_expr_assign (format_spec->u.expr);
1402       if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (formatexp)))
1403           < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
1404         error ("ASSIGNed FORMAT specifier is too small");
1405       formatexp = convert (string_type_node, formatexp);
1406       break;
1407
1408     case FFESTV_formatNAMELIST:
1409       formatinit = ffecom_expr (format_spec->u.expr);
1410       formatexp = formatinit;
1411       break;
1412
1413     default:
1414       assert ("bad format spec" == NULL);
1415       formatinit = integer_zero_node;
1416       formatexp = formatinit;
1417       break;
1418     }
1419
1420   ffeste_f2c_init_flag_ (have_end, endinit);
1421
1422   if (rec)
1423     recexp = ffecom_const_expr (rec_expr);
1424   else
1425     recexp = ffecom_integer_zero_node;
1426   if (recexp)
1427     recinit = recexp;
1428   else
1429     {
1430       recinit = ffecom_integer_zero_node;
1431       constantp = FALSE;
1432     }
1433
1434   inits = build_tree_list ((field = TYPE_FIELDS (f2c_cilist_struct)), errinit);
1435   initn = inits;
1436   ffeste_f2c_init_next_ (unitinit);
1437   ffeste_f2c_init_next_ (endinit);
1438   ffeste_f2c_init_next_ (formatinit);
1439   ffeste_f2c_init_next_ (recinit);
1440
1441   inits = build (CONSTRUCTOR, f2c_cilist_struct, NULL_TREE, inits);
1442   TREE_CONSTANT (inits) = constantp ? 1 : 0;
1443   TREE_STATIC (inits) = 1;
1444
1445   t = build_decl (VAR_DECL,
1446                   ffecom_get_invented_identifier ("__g77_cilist_%d",
1447                                                   mynumber++),
1448                   f2c_cilist_struct);
1449   TREE_STATIC (t) = 1;
1450   t = ffecom_start_decl (t, 1);
1451   ffecom_finish_decl (t, inits, 0);
1452
1453   /* Prepare run-time expressions.  */
1454
1455   if (! unitexp)
1456     ffecom_prepare_expr (unit_expr);
1457
1458   if (! formatexp)
1459     ffecom_prepare_arg_ptr_to_expr (format_spec->u.expr);
1460
1461   if (! recexp)
1462     ffecom_prepare_expr (rec_expr);
1463
1464   ffecom_prepare_end ();
1465
1466   /* Now evaluate run-time expressions as needed.  */
1467
1468   if (! unitexp)
1469     {
1470       unitexp = ffecom_expr (unit_expr);
1471       ffeste_f2c_compile_ (unitfield, unitexp);
1472     }
1473
1474   if (! formatexp)
1475     {
1476       formatexp = ffecom_arg_ptr_to_expr (format_spec->u.expr, NULL);
1477       ffeste_f2c_compile_ (formatfield, formatexp);
1478     }
1479   else if (format == FFESTV_formatINTEXPR)
1480     ffeste_f2c_compile_ (formatfield, formatexp);
1481
1482   if (! recexp)
1483     {
1484       recexp = ffecom_expr (rec_expr);
1485       ffeste_f2c_compile_ (recfield, recexp);
1486     }
1487
1488   ttype = build_pointer_type (TREE_TYPE (t));
1489   t = ffecom_1 (ADDR_EXPR, ttype, t);
1490
1491   t = build_tree_list (NULL_TREE, t);
1492
1493   return t;
1494 }
1495
1496 /* Make arglist with ptr to CLOSE control list.
1497
1498    Returns a tree suitable as an argument list containing a pointer to
1499    a CLOSE-statement control list.  First, generates that control
1500    list, if necessary, along with any static and run-time initializations
1501    that are needed as specified by the arguments to this function.
1502
1503    Must ensure that all expressions are prepared before being evaluated,
1504    for any whose evaluation might result in the generation of temporaries.
1505
1506    Note that this means this function causes a transition, within the
1507    current block being code-generated via the back end, from the
1508    declaration of variables (temporaries) to the expanding of expressions,
1509    statements, etc.  */
1510
1511 static tree
1512 ffeste_io_cllist_ (bool have_err,
1513                    ffebld unit_expr,
1514                    ffestpFile *stat_spec)
1515 {
1516   static tree f2c_close_struct = NULL_TREE;
1517   tree t;
1518   tree ttype;
1519   tree field;
1520   tree inits, initn;
1521   tree ignore;                  /* Ignore length info for certain fields. */
1522   bool constantp = TRUE;
1523   static tree errfield, unitfield, statfield;
1524   tree errinit, unitinit, statinit;
1525   tree unitexp, statexp;
1526   static int mynumber = 0;
1527
1528   if (f2c_close_struct == NULL_TREE)
1529     {
1530       tree ref;
1531
1532       ref = make_node (RECORD_TYPE);
1533
1534       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1535                                     ffecom_f2c_flag_type_node);
1536       unitfield = ffecom_decl_field (ref, errfield, "unit",
1537                                      ffecom_f2c_ftnint_type_node);
1538       statfield = ffecom_decl_field (ref, unitfield, "stat",
1539                                      string_type_node);
1540
1541       TYPE_FIELDS (ref) = errfield;
1542       layout_type (ref);
1543
1544       ggc_add_tree_root (&f2c_close_struct, 1);
1545
1546       f2c_close_struct = ref;
1547     }
1548
1549   /* Try to do as much compile-time initialization of the structure
1550      as possible, to save run time.  */
1551
1552   ffeste_f2c_init_flag_ (have_err, errinit);
1553
1554   unitexp = ffecom_const_expr (unit_expr);
1555   if (unitexp)
1556     unitinit = unitexp;
1557   else
1558     {
1559       unitinit = ffecom_integer_zero_node;
1560       constantp = FALSE;
1561     }
1562
1563   ffeste_f2c_init_charnolen_ (statexp, statinit, stat_spec);
1564
1565   inits = build_tree_list ((field = TYPE_FIELDS (f2c_close_struct)), errinit);
1566   initn = inits;
1567   ffeste_f2c_init_next_ (unitinit);
1568   ffeste_f2c_init_next_ (statinit);
1569
1570   inits = build (CONSTRUCTOR, f2c_close_struct, NULL_TREE, inits);
1571   TREE_CONSTANT (inits) = constantp ? 1 : 0;
1572   TREE_STATIC (inits) = 1;
1573
1574   t = build_decl (VAR_DECL,
1575                   ffecom_get_invented_identifier ("__g77_cllist_%d",
1576                                                   mynumber++),
1577                   f2c_close_struct);
1578   TREE_STATIC (t) = 1;
1579   t = ffecom_start_decl (t, 1);
1580   ffecom_finish_decl (t, inits, 0);
1581
1582   /* Prepare run-time expressions.  */
1583
1584   if (! unitexp)
1585     ffecom_prepare_expr (unit_expr);
1586
1587   if (! statexp)
1588     ffecom_prepare_arg_ptr_to_expr (stat_spec->u.expr);
1589
1590   ffecom_prepare_end ();
1591
1592   /* Now evaluate run-time expressions as needed.  */
1593
1594   if (! unitexp)
1595     {
1596       unitexp = ffecom_expr (unit_expr);
1597       ffeste_f2c_compile_ (unitfield, unitexp);
1598     }
1599
1600   ffeste_f2c_compile_charnolen_ (statfield, stat_spec, statexp);
1601
1602   ttype = build_pointer_type (TREE_TYPE (t));
1603   t = ffecom_1 (ADDR_EXPR, ttype, t);
1604
1605   t = build_tree_list (NULL_TREE, t);
1606
1607   return t;
1608 }
1609
1610 /* Make arglist with ptr to internal-I/O control list.
1611
1612    Returns a tree suitable as an argument list containing a pointer to
1613    an internal-I/O control list.  First, generates that control
1614    list, if necessary, along with any static and run-time initializations
1615    that are needed as specified by the arguments to this function.
1616
1617    Must ensure that all expressions are prepared before being evaluated,
1618    for any whose evaluation might result in the generation of temporaries.
1619
1620    Note that this means this function causes a transition, within the
1621    current block being code-generated via the back end, from the
1622    declaration of variables (temporaries) to the expanding of expressions,
1623    statements, etc.  */
1624
1625 static tree
1626 ffeste_io_icilist_ (bool have_err,
1627                     ffebld unit_expr,
1628                     bool have_end,
1629                     ffestvFormat format,
1630                     ffestpFile *format_spec)
1631 {
1632   static tree f2c_icilist_struct = NULL_TREE;
1633   tree t;
1634   tree ttype;
1635   tree field;
1636   tree inits, initn;
1637   bool constantp = TRUE;
1638   static tree errfield, unitfield, endfield, formatfield, unitlenfield,
1639     unitnumfield;
1640   tree errinit, unitinit, endinit, formatinit, unitleninit, unitnuminit;
1641   tree unitexp, formatexp, unitlenexp, unitnumexp;
1642   static int mynumber = 0;
1643
1644   if (f2c_icilist_struct == NULL_TREE)
1645     {
1646       tree ref;
1647
1648       ref = make_node (RECORD_TYPE);
1649
1650       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1651                                     ffecom_f2c_flag_type_node);
1652       unitfield = ffecom_decl_field (ref, errfield, "unit",
1653                                      string_type_node);
1654       endfield = ffecom_decl_field (ref, unitfield, "end",
1655                                     ffecom_f2c_flag_type_node);
1656       formatfield = ffecom_decl_field (ref, endfield, "format",
1657                                        string_type_node);
1658       unitlenfield = ffecom_decl_field (ref, formatfield, "unitlen",
1659                                         ffecom_f2c_ftnint_type_node);
1660       unitnumfield = ffecom_decl_field (ref, unitlenfield, "unitnum",
1661                                         ffecom_f2c_ftnint_type_node);
1662
1663       TYPE_FIELDS (ref) = errfield;
1664       layout_type (ref);
1665
1666       ggc_add_tree_root (&f2c_icilist_struct, 1);
1667
1668       f2c_icilist_struct = ref;
1669     }
1670
1671   /* Try to do as much compile-time initialization of the structure
1672      as possible, to save run time.  */
1673
1674   ffeste_f2c_init_flag_ (have_err, errinit);
1675
1676   unitexp = ffecom_arg_ptr_to_const_expr (unit_expr, &unitlenexp);
1677   if (unitexp)
1678     unitinit = unitexp;
1679   else
1680     {
1681       unitinit = null_pointer_node;
1682       constantp = FALSE;
1683     }
1684   if (unitlenexp)
1685     unitleninit = unitlenexp;
1686   else
1687     {
1688       unitleninit = ffecom_integer_zero_node;
1689       constantp = FALSE;
1690     }
1691
1692   /* Now see if we can fully initialize the number of elements, or
1693      if we have to compute that at run time.  */
1694   if (ffeinfo_rank (ffebld_info (unit_expr)) == 0
1695       || (unitexp
1696           && TREE_CODE (TREE_TYPE (TREE_TYPE (unitexp))) != ARRAY_TYPE))
1697     {
1698       /* Not an array, so just one element.  */
1699       unitnuminit = ffecom_integer_one_node;
1700       unitnumexp = unitnuminit;
1701     }
1702   else if (unitexp && unitlenexp)
1703     {
1704       /* An array, but all the info is constant, so compute now.  */
1705       unitnuminit
1706         = size_binop (CEIL_DIV_EXPR,
1707                       TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (unitexp))),
1708                       convert (sizetype, unitlenexp));
1709       unitnuminit = size_binop (CEIL_DIV_EXPR, unitnuminit,
1710                                 size_int (TYPE_PRECISION (char_type_node)
1711                                           / BITS_PER_UNIT));
1712       unitnumexp = unitnuminit;
1713     }
1714   else
1715     {
1716       /* Put off computing until run time.  */
1717       unitnuminit = ffecom_integer_zero_node;
1718       unitnumexp = NULL_TREE;
1719       constantp = FALSE;
1720     }
1721
1722   switch (format)
1723     {
1724     case FFESTV_formatNONE:
1725       formatinit = null_pointer_node;
1726       formatexp = formatinit;
1727       break;
1728
1729     case FFESTV_formatLABEL:
1730       formatexp = error_mark_node;
1731       formatinit = ffecom_lookup_label (format_spec->u.label);
1732       if ((formatinit == NULL_TREE)
1733           || (TREE_CODE (formatinit) == ERROR_MARK))
1734         break;
1735       formatinit = ffecom_1 (ADDR_EXPR,
1736                              build_pointer_type (void_type_node),
1737                              formatinit);
1738       TREE_CONSTANT (formatinit) = 1;
1739       break;
1740
1741     case FFESTV_formatCHAREXPR:
1742       ffeste_f2c_init_format_ (formatexp, formatinit, format_spec);
1743       break;
1744
1745     case FFESTV_formatASTERISK:
1746       formatinit = null_pointer_node;
1747       formatexp = formatinit;
1748       break;
1749
1750     case FFESTV_formatINTEXPR:
1751       formatinit = null_pointer_node;
1752       formatexp = ffecom_expr_assign (format_spec->u.expr);
1753       if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (formatexp)))
1754           < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
1755         error ("ASSIGNed FORMAT specifier is too small");
1756       formatexp = convert (string_type_node, formatexp);
1757       break;
1758
1759     default:
1760       assert ("bad format spec" == NULL);
1761       formatinit = ffecom_integer_zero_node;
1762       formatexp = formatinit;
1763       break;
1764     }
1765
1766   ffeste_f2c_init_flag_ (have_end, endinit);
1767
1768   inits = build_tree_list ((field = TYPE_FIELDS (f2c_icilist_struct)),
1769                            errinit);
1770   initn = inits;
1771   ffeste_f2c_init_next_ (unitinit);
1772   ffeste_f2c_init_next_ (endinit);
1773   ffeste_f2c_init_next_ (formatinit);
1774   ffeste_f2c_init_next_ (unitleninit);
1775   ffeste_f2c_init_next_ (unitnuminit);
1776
1777   inits = build (CONSTRUCTOR, f2c_icilist_struct, NULL_TREE, inits);
1778   TREE_CONSTANT (inits) = constantp ? 1 : 0;
1779   TREE_STATIC (inits) = 1;
1780
1781   t = build_decl (VAR_DECL,
1782                   ffecom_get_invented_identifier ("__g77_icilist_%d",
1783                                                   mynumber++),
1784                   f2c_icilist_struct);
1785   TREE_STATIC (t) = 1;
1786   t = ffecom_start_decl (t, 1);
1787   ffecom_finish_decl (t, inits, 0);
1788
1789   /* Prepare run-time expressions.  */
1790
1791   if (! unitexp)
1792     ffecom_prepare_arg_ptr_to_expr (unit_expr);
1793
1794   ffeste_f2c_prepare_format_ (format_spec, formatexp);
1795
1796   ffecom_prepare_end ();
1797
1798   /* Now evaluate run-time expressions as needed.  */
1799
1800   if (! unitexp || ! unitlenexp)
1801     {
1802       int need_unitexp = (! unitexp);
1803       int need_unitlenexp = (! unitlenexp);
1804
1805       unitexp = ffecom_arg_ptr_to_expr (unit_expr, &unitlenexp);
1806       if (need_unitexp)
1807         ffeste_f2c_compile_ (unitfield, unitexp);
1808       if (need_unitlenexp)
1809         ffeste_f2c_compile_ (unitlenfield, unitlenexp);
1810     }
1811
1812   if (! unitnumexp
1813       && unitexp != error_mark_node
1814       && unitlenexp != error_mark_node)
1815     {
1816       unitnumexp
1817         = size_binop (CEIL_DIV_EXPR,
1818                       TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (unitexp))),
1819                       convert (sizetype, unitlenexp));
1820       unitnumexp = size_binop (CEIL_DIV_EXPR, unitnumexp,
1821                                size_int (TYPE_PRECISION (char_type_node)
1822                                          / BITS_PER_UNIT));
1823       ffeste_f2c_compile_ (unitnumfield, unitnumexp);
1824     }
1825
1826   if (format == FFESTV_formatINTEXPR)
1827     ffeste_f2c_compile_ (formatfield, formatexp);
1828   else
1829     ffeste_f2c_compile_format_ (formatfield, format_spec, formatexp);
1830
1831   ttype = build_pointer_type (TREE_TYPE (t));
1832   t = ffecom_1 (ADDR_EXPR, ttype, t);
1833
1834   t = build_tree_list (NULL_TREE, t);
1835
1836   return t;
1837 }
1838
1839 /* Make arglist with ptr to INQUIRE control list
1840
1841    Returns a tree suitable as an argument list containing a pointer to
1842    an INQUIRE-statement control list.  First, generates that control
1843    list, if necessary, along with any static and run-time initializations
1844    that are needed as specified by the arguments to this function.
1845
1846    Must ensure that all expressions are prepared before being evaluated,
1847    for any whose evaluation might result in the generation of temporaries.
1848
1849    Note that this means this function causes a transition, within the
1850    current block being code-generated via the back end, from the
1851    declaration of variables (temporaries) to the expanding of expressions,
1852    statements, etc.  */
1853
1854 static tree
1855 ffeste_io_inlist_ (bool have_err,
1856                    ffestpFile *unit_spec,
1857                    ffestpFile *file_spec,
1858                    ffestpFile *exist_spec,
1859                    ffestpFile *open_spec,
1860                    ffestpFile *number_spec,
1861                    ffestpFile *named_spec,
1862                    ffestpFile *name_spec,
1863                    ffestpFile *access_spec,
1864                    ffestpFile *sequential_spec,
1865                    ffestpFile *direct_spec,
1866                    ffestpFile *form_spec,
1867                    ffestpFile *formatted_spec,
1868                    ffestpFile *unformatted_spec,
1869                    ffestpFile *recl_spec,
1870                    ffestpFile *nextrec_spec,
1871                    ffestpFile *blank_spec)
1872 {
1873   static tree f2c_inquire_struct = NULL_TREE;
1874   tree t;
1875   tree ttype;
1876   tree field;
1877   tree inits, initn;
1878   bool constantp = TRUE;
1879   static tree errfield, unitfield, filefield, filelenfield, existfield,
1880     openfield, numberfield, namedfield, namefield, namelenfield, accessfield,
1881     accesslenfield, sequentialfield, sequentiallenfield, directfield, directlenfield,
1882     formfield, formlenfield, formattedfield, formattedlenfield, unformattedfield,
1883     unformattedlenfield, reclfield, nextrecfield, blankfield, blanklenfield;
1884   tree errinit, unitinit, fileinit, fileleninit, existinit, openinit, numberinit,
1885     namedinit, nameinit, nameleninit, accessinit, accessleninit, sequentialinit,
1886     sequentialleninit, directinit, directleninit, forminit, formleninit,
1887     formattedinit, formattedleninit, unformattedinit, unformattedleninit,
1888     reclinit, nextrecinit, blankinit, blankleninit;
1889   tree
1890     unitexp, fileexp, filelenexp, existexp, openexp, numberexp, namedexp,
1891     nameexp, namelenexp, accessexp, accesslenexp, sequentialexp, sequentiallenexp,
1892     directexp, directlenexp, formexp, formlenexp, formattedexp, formattedlenexp,
1893     unformattedexp, unformattedlenexp, reclexp, nextrecexp, blankexp, blanklenexp;
1894   static int mynumber = 0;
1895
1896   if (f2c_inquire_struct == NULL_TREE)
1897     {
1898       tree ref;
1899
1900       ref = make_node (RECORD_TYPE);
1901
1902       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
1903                                     ffecom_f2c_flag_type_node);
1904       unitfield = ffecom_decl_field (ref, errfield, "unit",
1905                                      ffecom_f2c_ftnint_type_node);
1906       filefield = ffecom_decl_field (ref, unitfield, "file",
1907                                      string_type_node);
1908       filelenfield = ffecom_decl_field (ref, filefield, "filelen",
1909                                         ffecom_f2c_ftnlen_type_node);
1910       existfield = ffecom_decl_field (ref, filelenfield, "exist",
1911                                       ffecom_f2c_ptr_to_ftnint_type_node);
1912       openfield = ffecom_decl_field (ref, existfield, "open",
1913                                      ffecom_f2c_ptr_to_ftnint_type_node);
1914       numberfield = ffecom_decl_field (ref, openfield, "number",
1915                                        ffecom_f2c_ptr_to_ftnint_type_node);
1916       namedfield = ffecom_decl_field (ref, numberfield, "named",
1917                                       ffecom_f2c_ptr_to_ftnint_type_node);
1918       namefield = ffecom_decl_field (ref, namedfield, "name",
1919                                      string_type_node);
1920       namelenfield = ffecom_decl_field (ref, namefield, "namelen",
1921                                         ffecom_f2c_ftnlen_type_node);
1922       accessfield = ffecom_decl_field (ref, namelenfield, "access",
1923                                        string_type_node);
1924       accesslenfield = ffecom_decl_field (ref, accessfield, "accesslen",
1925                                           ffecom_f2c_ftnlen_type_node);
1926       sequentialfield = ffecom_decl_field (ref, accesslenfield, "sequential",
1927                                            string_type_node);
1928       sequentiallenfield = ffecom_decl_field (ref, sequentialfield,
1929                                               "sequentiallen",
1930                                               ffecom_f2c_ftnlen_type_node);
1931       directfield = ffecom_decl_field (ref, sequentiallenfield, "direct",
1932                                        string_type_node);
1933       directlenfield = ffecom_decl_field (ref, directfield, "directlen",
1934                                           ffecom_f2c_ftnlen_type_node);
1935       formfield = ffecom_decl_field (ref, directlenfield, "form",
1936                                      string_type_node);
1937       formlenfield = ffecom_decl_field (ref, formfield, "formlen",
1938                                         ffecom_f2c_ftnlen_type_node);
1939       formattedfield = ffecom_decl_field (ref, formlenfield, "formatted",
1940                                           string_type_node);
1941       formattedlenfield = ffecom_decl_field (ref, formattedfield,
1942                                              "formattedlen",
1943                                              ffecom_f2c_ftnlen_type_node);
1944       unformattedfield = ffecom_decl_field (ref, formattedlenfield,
1945                                             "unformatted",
1946                                             string_type_node);
1947       unformattedlenfield = ffecom_decl_field (ref, unformattedfield,
1948                                                "unformattedlen",
1949                                                ffecom_f2c_ftnlen_type_node);
1950       reclfield = ffecom_decl_field (ref, unformattedlenfield, "recl",
1951                                      ffecom_f2c_ptr_to_ftnint_type_node);
1952       nextrecfield = ffecom_decl_field (ref, reclfield, "nextrec",
1953                                         ffecom_f2c_ptr_to_ftnint_type_node);
1954       blankfield = ffecom_decl_field (ref, nextrecfield, "blank",
1955                                       string_type_node);
1956       blanklenfield = ffecom_decl_field (ref, blankfield, "blanklen",
1957                                          ffecom_f2c_ftnlen_type_node);
1958
1959       TYPE_FIELDS (ref) = errfield;
1960       layout_type (ref);
1961
1962       ggc_add_tree_root (&f2c_inquire_struct, 1);
1963
1964       f2c_inquire_struct = ref;
1965     }
1966
1967   /* Try to do as much compile-time initialization of the structure
1968      as possible, to save run time.  */
1969
1970   ffeste_f2c_init_flag_ (have_err, errinit);
1971   ffeste_f2c_init_int_ (unitexp, unitinit, unit_spec);
1972   ffeste_f2c_init_char_ (fileexp, fileinit, filelenexp, fileleninit,
1973                          file_spec);
1974   ffeste_f2c_init_ptrtoint_ (existexp, existinit, exist_spec);
1975   ffeste_f2c_init_ptrtoint_ (openexp, openinit, open_spec);
1976   ffeste_f2c_init_ptrtoint_ (numberexp, numberinit, number_spec);
1977   ffeste_f2c_init_ptrtoint_ (namedexp, namedinit, named_spec);
1978   ffeste_f2c_init_char_ (nameexp, nameinit, namelenexp, nameleninit,
1979                          name_spec);
1980   ffeste_f2c_init_char_ (accessexp, accessinit, accesslenexp,
1981                          accessleninit, access_spec);
1982   ffeste_f2c_init_char_ (sequentialexp, sequentialinit, sequentiallenexp,
1983                          sequentialleninit, sequential_spec);
1984   ffeste_f2c_init_char_ (directexp, directinit, directlenexp,
1985                          directleninit, direct_spec);
1986   ffeste_f2c_init_char_ (formexp, forminit, formlenexp, formleninit,
1987                          form_spec);
1988   ffeste_f2c_init_char_ (formattedexp, formattedinit,
1989                          formattedlenexp, formattedleninit, formatted_spec);
1990   ffeste_f2c_init_char_ (unformattedexp, unformattedinit, unformattedlenexp,
1991                          unformattedleninit, unformatted_spec);
1992   ffeste_f2c_init_ptrtoint_ (reclexp, reclinit, recl_spec);
1993   ffeste_f2c_init_ptrtoint_ (nextrecexp, nextrecinit, nextrec_spec);
1994   ffeste_f2c_init_char_ (blankexp, blankinit, blanklenexp,
1995                          blankleninit, blank_spec);
1996
1997   inits = build_tree_list ((field = TYPE_FIELDS (f2c_inquire_struct)),
1998                            errinit);
1999   initn = inits;
2000   ffeste_f2c_init_next_ (unitinit);
2001   ffeste_f2c_init_next_ (fileinit);
2002   ffeste_f2c_init_next_ (fileleninit);
2003   ffeste_f2c_init_next_ (existinit);
2004   ffeste_f2c_init_next_ (openinit);
2005   ffeste_f2c_init_next_ (numberinit);
2006   ffeste_f2c_init_next_ (namedinit);
2007   ffeste_f2c_init_next_ (nameinit);
2008   ffeste_f2c_init_next_ (nameleninit);
2009   ffeste_f2c_init_next_ (accessinit);
2010   ffeste_f2c_init_next_ (accessleninit);
2011   ffeste_f2c_init_next_ (sequentialinit);
2012   ffeste_f2c_init_next_ (sequentialleninit);
2013   ffeste_f2c_init_next_ (directinit);
2014   ffeste_f2c_init_next_ (directleninit);
2015   ffeste_f2c_init_next_ (forminit);
2016   ffeste_f2c_init_next_ (formleninit);
2017   ffeste_f2c_init_next_ (formattedinit);
2018   ffeste_f2c_init_next_ (formattedleninit);
2019   ffeste_f2c_init_next_ (unformattedinit);
2020   ffeste_f2c_init_next_ (unformattedleninit);
2021   ffeste_f2c_init_next_ (reclinit);
2022   ffeste_f2c_init_next_ (nextrecinit);
2023   ffeste_f2c_init_next_ (blankinit);
2024   ffeste_f2c_init_next_ (blankleninit);
2025
2026   inits = build (CONSTRUCTOR, f2c_inquire_struct, NULL_TREE, inits);
2027   TREE_CONSTANT (inits) = constantp ? 1 : 0;
2028   TREE_STATIC (inits) = 1;
2029
2030   t = build_decl (VAR_DECL,
2031                   ffecom_get_invented_identifier ("__g77_inlist_%d",
2032                                                   mynumber++),
2033                   f2c_inquire_struct);
2034   TREE_STATIC (t) = 1;
2035   t = ffecom_start_decl (t, 1);
2036   ffecom_finish_decl (t, inits, 0);
2037
2038   /* Prepare run-time expressions.  */
2039
2040   ffeste_f2c_prepare_int_ (unit_spec, unitexp);
2041   ffeste_f2c_prepare_char_ (file_spec, fileexp);
2042   ffeste_f2c_prepare_ptrtoint_ (exist_spec, existexp);
2043   ffeste_f2c_prepare_ptrtoint_ (open_spec, openexp);
2044   ffeste_f2c_prepare_ptrtoint_ (number_spec, numberexp);
2045   ffeste_f2c_prepare_ptrtoint_ (named_spec, namedexp);
2046   ffeste_f2c_prepare_char_ (name_spec, nameexp);
2047   ffeste_f2c_prepare_char_ (access_spec, accessexp);
2048   ffeste_f2c_prepare_char_ (sequential_spec, sequentialexp);
2049   ffeste_f2c_prepare_char_ (direct_spec, directexp);
2050   ffeste_f2c_prepare_char_ (form_spec, formexp);
2051   ffeste_f2c_prepare_char_ (formatted_spec, formattedexp);
2052   ffeste_f2c_prepare_char_ (unformatted_spec, unformattedexp);
2053   ffeste_f2c_prepare_ptrtoint_ (recl_spec, reclexp);
2054   ffeste_f2c_prepare_ptrtoint_ (nextrec_spec, nextrecexp);
2055   ffeste_f2c_prepare_char_ (blank_spec, blankexp);
2056
2057   ffecom_prepare_end ();
2058
2059   /* Now evaluate run-time expressions as needed.  */
2060
2061   ffeste_f2c_compile_int_ (unitfield, unit_spec, unitexp);
2062   ffeste_f2c_compile_char_ (filefield, filelenfield, file_spec,
2063                             fileexp, filelenexp);
2064   ffeste_f2c_compile_ptrtoint_ (existfield, exist_spec, existexp);
2065   ffeste_f2c_compile_ptrtoint_ (openfield, open_spec, openexp);
2066   ffeste_f2c_compile_ptrtoint_ (numberfield, number_spec, numberexp);
2067   ffeste_f2c_compile_ptrtoint_ (namedfield, named_spec, namedexp);
2068   ffeste_f2c_compile_char_ (namefield, namelenfield, name_spec, nameexp,
2069                             namelenexp);
2070   ffeste_f2c_compile_char_ (accessfield, accesslenfield, access_spec,
2071                             accessexp, accesslenexp);
2072   ffeste_f2c_compile_char_ (sequentialfield, sequentiallenfield,
2073                             sequential_spec, sequentialexp,
2074                             sequentiallenexp);
2075   ffeste_f2c_compile_char_ (directfield, directlenfield, direct_spec,
2076                             directexp, directlenexp);
2077   ffeste_f2c_compile_char_ (formfield, formlenfield, form_spec, formexp,
2078                             formlenexp);
2079   ffeste_f2c_compile_char_ (formattedfield, formattedlenfield, formatted_spec,
2080                             formattedexp, formattedlenexp);
2081   ffeste_f2c_compile_char_ (unformattedfield, unformattedlenfield,
2082                             unformatted_spec, unformattedexp,
2083                             unformattedlenexp);
2084   ffeste_f2c_compile_ptrtoint_ (reclfield, recl_spec, reclexp);
2085   ffeste_f2c_compile_ptrtoint_ (nextrecfield, nextrec_spec, nextrecexp);
2086   ffeste_f2c_compile_char_ (blankfield, blanklenfield, blank_spec, blankexp,
2087                             blanklenexp);
2088
2089   ttype = build_pointer_type (TREE_TYPE (t));
2090   t = ffecom_1 (ADDR_EXPR, ttype, t);
2091
2092   t = build_tree_list (NULL_TREE, t);
2093
2094   return t;
2095 }
2096
2097 /* Make arglist with ptr to OPEN control list
2098
2099    Returns a tree suitable as an argument list containing a pointer to
2100    an OPEN-statement control list.  First, generates that control
2101    list, if necessary, along with any static and run-time initializations
2102    that are needed as specified by the arguments to this function.
2103
2104    Must ensure that all expressions are prepared before being evaluated,
2105    for any whose evaluation might result in the generation of temporaries.
2106
2107    Note that this means this function causes a transition, within the
2108    current block being code-generated via the back end, from the
2109    declaration of variables (temporaries) to the expanding of expressions,
2110    statements, etc.  */
2111
2112 static tree
2113 ffeste_io_olist_ (bool have_err,
2114                   ffebld unit_expr,
2115                   ffestpFile *file_spec,
2116                   ffestpFile *stat_spec,
2117                   ffestpFile *access_spec,
2118                   ffestpFile *form_spec,
2119                   ffestpFile *recl_spec,
2120                   ffestpFile *blank_spec)
2121 {
2122   static tree f2c_open_struct = NULL_TREE;
2123   tree t;
2124   tree ttype;
2125   tree field;
2126   tree inits, initn;
2127   tree ignore;                  /* Ignore length info for certain fields. */
2128   bool constantp = TRUE;
2129   static tree errfield, unitfield, filefield, filelenfield, statfield,
2130     accessfield, formfield, reclfield, blankfield;
2131   tree errinit, unitinit, fileinit, fileleninit, statinit, accessinit,
2132     forminit, reclinit, blankinit;
2133   tree
2134     unitexp, fileexp, filelenexp, statexp, accessexp, formexp, reclexp,
2135     blankexp;
2136   static int mynumber = 0;
2137
2138   if (f2c_open_struct == NULL_TREE)
2139     {
2140       tree ref;
2141
2142       ref = make_node (RECORD_TYPE);
2143
2144       errfield = ffecom_decl_field (ref, NULL_TREE, "err",
2145                                     ffecom_f2c_flag_type_node);
2146       unitfield = ffecom_decl_field (ref, errfield, "unit",
2147                                      ffecom_f2c_ftnint_type_node);
2148       filefield = ffecom_decl_field (ref, unitfield, "file",
2149                                      string_type_node);
2150       filelenfield = ffecom_decl_field (ref, filefield, "filelen",
2151                                         ffecom_f2c_ftnlen_type_node);
2152       statfield = ffecom_decl_field (ref, filelenfield, "stat",
2153                                      string_type_node);
2154       accessfield = ffecom_decl_field (ref, statfield, "access",
2155                                        string_type_node);
2156       formfield = ffecom_decl_field (ref, accessfield, "form",
2157                                      string_type_node);
2158       reclfield = ffecom_decl_field (ref, formfield, "recl",
2159                                      ffecom_f2c_ftnint_type_node);
2160       blankfield = ffecom_decl_field (ref, reclfield, "blank",
2161                                       string_type_node);
2162
2163       TYPE_FIELDS (ref) = errfield;
2164       layout_type (ref);
2165
2166       ggc_add_tree_root (&f2c_open_struct, 1);
2167
2168       f2c_open_struct = ref;
2169     }
2170
2171   /* Try to do as much compile-time initialization of the structure
2172      as possible, to save run time.  */
2173
2174   ffeste_f2c_init_flag_ (have_err, errinit);
2175
2176   unitexp = ffecom_const_expr (unit_expr);
2177   if (unitexp)
2178     unitinit = unitexp;
2179   else
2180     {
2181       unitinit = ffecom_integer_zero_node;
2182       constantp = FALSE;
2183     }
2184
2185   ffeste_f2c_init_char_ (fileexp, fileinit, filelenexp, fileleninit,
2186                          file_spec);
2187   ffeste_f2c_init_charnolen_ (statexp, statinit, stat_spec);
2188   ffeste_f2c_init_charnolen_ (accessexp, accessinit, access_spec);
2189   ffeste_f2c_init_charnolen_ (formexp, forminit, form_spec);
2190   ffeste_f2c_init_int_ (reclexp, reclinit, recl_spec);
2191   ffeste_f2c_init_charnolen_ (blankexp, blankinit, blank_spec);
2192
2193   inits = build_tree_list ((field = TYPE_FIELDS (f2c_open_struct)), errinit);
2194   initn = inits;
2195   ffeste_f2c_init_next_ (unitinit);
2196   ffeste_f2c_init_next_ (fileinit);
2197   ffeste_f2c_init_next_ (fileleninit);
2198   ffeste_f2c_init_next_ (statinit);
2199   ffeste_f2c_init_next_ (accessinit);
2200   ffeste_f2c_init_next_ (forminit);
2201   ffeste_f2c_init_next_ (reclinit);
2202   ffeste_f2c_init_next_ (blankinit);
2203
2204   inits = build (CONSTRUCTOR, f2c_open_struct, NULL_TREE, inits);
2205   TREE_CONSTANT (inits) = constantp ? 1 : 0;
2206   TREE_STATIC (inits) = 1;
2207
2208   t = build_decl (VAR_DECL,
2209                   ffecom_get_invented_identifier ("__g77_olist_%d",
2210                                                   mynumber++),
2211                   f2c_open_struct);
2212   TREE_STATIC (t) = 1;
2213   t = ffecom_start_decl (t, 1);
2214   ffecom_finish_decl (t, inits, 0);
2215
2216   /* Prepare run-time expressions.  */
2217
2218   if (! unitexp)
2219     ffecom_prepare_expr (unit_expr);
2220
2221   ffeste_f2c_prepare_char_ (file_spec, fileexp);
2222   ffeste_f2c_prepare_charnolen_ (stat_spec, statexp);
2223   ffeste_f2c_prepare_charnolen_ (access_spec, accessexp);
2224   ffeste_f2c_prepare_charnolen_ (form_spec, formexp);
2225   ffeste_f2c_prepare_int_ (recl_spec, reclexp);
2226   ffeste_f2c_prepare_charnolen_ (blank_spec, blankexp);
2227
2228   ffecom_prepare_end ();
2229
2230   /* Now evaluate run-time expressions as needed.  */
2231
2232   if (! unitexp)
2233     {
2234       unitexp = ffecom_expr (unit_expr);
2235       ffeste_f2c_compile_ (unitfield, unitexp);
2236     }
2237
2238   ffeste_f2c_compile_char_ (filefield, filelenfield, file_spec, fileexp,
2239                             filelenexp);
2240   ffeste_f2c_compile_charnolen_ (statfield, stat_spec, statexp);
2241   ffeste_f2c_compile_charnolen_ (accessfield, access_spec, accessexp);
2242   ffeste_f2c_compile_charnolen_ (formfield, form_spec, formexp);
2243   ffeste_f2c_compile_int_ (reclfield, recl_spec, reclexp);
2244   ffeste_f2c_compile_charnolen_ (blankfield, blank_spec, blankexp);
2245
2246   ttype = build_pointer_type (TREE_TYPE (t));
2247   t = ffecom_1 (ADDR_EXPR, ttype, t);
2248
2249   t = build_tree_list (NULL_TREE, t);
2250
2251   return t;
2252 }
2253
2254 /* Generate code for BACKSPACE/ENDFILE/REWIND.  */
2255
2256 static void
2257 ffeste_subr_beru_ (ffestpBeruStmt *info, ffecomGfrt rt)
2258 {
2259   tree alist;
2260   bool iostat;
2261   bool errl;
2262
2263   ffeste_emit_line_note_ ();
2264
2265 #define specified(something) (info->beru_spec[something].kw_or_val_present)
2266
2267   iostat = specified (FFESTP_beruixIOSTAT);
2268   errl = specified (FFESTP_beruixERR);
2269
2270 #undef specified
2271
2272   /* ~~For now, we assume the unit number is specified and is not ASTERISK,
2273      because the FFE doesn't support BACKSPACE(*) and rejects a BACKSPACE
2274      without any unit specifier.  f2c, however, supports the former
2275      construct.  When it is time to add this feature to the FFE, which
2276      probably is fairly easy, ffestc_R919 and company will want to pass an
2277      ffestvUnit indicator of FFESTV_unitINTEXPR or _unitASTERISK to
2278      ffeste_R919 and company, and they will want to pass that same value to
2279      this function, and that argument will replace the constant _unitINTEXPR_
2280      in the call below.  Right now, the default unit number, 6, is ignored.  */
2281
2282   ffeste_start_stmt_ ();
2283
2284   if (errl)
2285     {
2286       /* Have ERR= specification.   */
2287
2288       ffeste_io_err_
2289         = ffeste_io_abort_
2290         = ffecom_lookup_label
2291         (info->beru_spec[FFESTP_beruixERR].u.label);
2292       ffeste_io_abort_is_temp_ = FALSE;
2293     }
2294   else
2295     {
2296       /* No ERR= specification.  */
2297
2298       ffeste_io_err_ = NULL_TREE;
2299
2300       if ((ffeste_io_abort_is_temp_ = iostat))
2301         ffeste_io_abort_ = ffecom_temp_label ();
2302       else
2303         ffeste_io_abort_ = NULL_TREE;
2304     }
2305
2306   if (iostat)
2307     {
2308       /* Have IOSTAT= specification.  */
2309
2310       ffeste_io_iostat_is_temp_ = FALSE;
2311       ffeste_io_iostat_ = ffecom_expr
2312         (info->beru_spec[FFESTP_beruixIOSTAT].u.expr);
2313     }
2314   else if (ffeste_io_abort_ != NULL_TREE)
2315     {
2316       /* Have no IOSTAT= but have ERR=.  */
2317
2318       ffeste_io_iostat_is_temp_ = TRUE;
2319       ffeste_io_iostat_
2320         = ffecom_make_tempvar ("beru", ffecom_integer_type_node,
2321                                FFETARGET_charactersizeNONE, -1);
2322     }
2323   else
2324     {
2325       /* No IOSTAT= or ERR= specification.  */
2326
2327       ffeste_io_iostat_is_temp_ = FALSE;
2328       ffeste_io_iostat_ = NULL_TREE;
2329     }
2330
2331   /* Now prescan, then convert, all the arguments.  */
2332
2333   alist = ffeste_io_ialist_ (errl || iostat, FFESTV_unitINTEXPR,
2334                              info->beru_spec[FFESTP_beruixUNIT].u.expr, 6);
2335
2336   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
2337      label, since we're gonna fall through to there anyway. */
2338
2339   ffeste_io_call_ (ffecom_call_gfrt (rt, alist, NULL_TREE),
2340                    ! ffeste_io_abort_is_temp_);
2341
2342   /* If we've got a temp label, generate its code here. */
2343
2344   if (ffeste_io_abort_is_temp_)
2345     {
2346       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
2347       emit_nop ();
2348       expand_label (ffeste_io_abort_);
2349
2350       assert (ffeste_io_err_ == NULL_TREE);
2351     }
2352
2353   ffeste_end_stmt_ ();
2354 }
2355
2356 /* END DO statement
2357
2358    Also invoked by _labeldef_branch_finish_ (or, in cases
2359    of errors, other _labeldef_ functions) when the label definition is
2360    for a DO-target (LOOPEND) label, once per matching/outstanding DO
2361    block on the stack.  */
2362
2363 void
2364 ffeste_do (ffestw block)
2365 {
2366   ffeste_emit_line_note_ ();
2367
2368   if (ffestw_do_tvar (block) == 0)
2369     {
2370       expand_end_loop ();               /* DO WHILE and just DO. */
2371
2372       ffeste_end_block_ (block);
2373     }
2374   else
2375     ffeste_end_iterdo_ (block,
2376                         ffestw_do_tvar (block),
2377                         ffestw_do_incr_saved (block),
2378                         ffestw_do_count_var (block));
2379 }
2380
2381 /* End of statement following logical IF.
2382
2383    Applies to *only* logical IF, not to IF-THEN.  */
2384
2385 void
2386 ffeste_end_R807 ()
2387 {
2388   ffeste_emit_line_note_ ();
2389
2390   expand_end_cond ();
2391
2392   ffeste_end_block_ (NULL);
2393 }
2394
2395 /* Generate "code" for branch label definition.  */
2396
2397 void
2398 ffeste_labeldef_branch (ffelab label)
2399 {
2400   tree glabel;
2401
2402   glabel = ffecom_lookup_label (label);
2403   assert (glabel != NULL_TREE);
2404   if (TREE_CODE (glabel) == ERROR_MARK)
2405     return;
2406
2407   assert (DECL_INITIAL (glabel) == NULL_TREE);
2408
2409   DECL_INITIAL (glabel) = error_mark_node;
2410   DECL_SOURCE_FILE (glabel) = ffelab_definition_filename (label);
2411   DECL_SOURCE_LINE (glabel) = ffelab_definition_filelinenum (label);
2412
2413   emit_nop ();
2414
2415   expand_label (glabel);
2416 }
2417
2418 /* Generate "code" for FORMAT label definition.  */
2419
2420 void
2421 ffeste_labeldef_format (ffelab label)
2422 {
2423   ffeste_label_formatdef_ = label;
2424 }
2425
2426 /* Assignment statement (outside of WHERE).  */
2427
2428 void
2429 ffeste_R737A (ffebld dest, ffebld source)
2430 {
2431   ffeste_check_simple_ ();
2432
2433   ffeste_emit_line_note_ ();
2434
2435   ffeste_start_stmt_ ();
2436
2437   ffecom_expand_let_stmt (dest, source);
2438
2439   ffeste_end_stmt_ ();
2440 }
2441
2442 /* Block IF (IF-THEN) statement.  */
2443
2444 void
2445 ffeste_R803 (ffestw block, ffebld expr)
2446 {
2447   tree temp;
2448
2449   ffeste_check_simple_ ();
2450
2451   ffeste_emit_line_note_ ();
2452
2453   ffeste_start_block_ (block);
2454
2455   temp = ffecom_make_tempvar ("ifthen", integer_type_node,
2456                               FFETARGET_charactersizeNONE, -1);
2457
2458   ffeste_start_stmt_ ();
2459
2460   ffecom_prepare_expr (expr);
2461
2462   if (ffecom_prepare_end ())
2463     {
2464       tree result;
2465
2466       result = ffecom_modify (void_type_node,
2467                               temp,
2468                               ffecom_truth_value (ffecom_expr (expr)));
2469
2470       expand_expr_stmt (result);
2471
2472       ffeste_end_stmt_ ();
2473     }
2474   else
2475     {
2476       ffeste_end_stmt_ ();
2477
2478       temp = ffecom_truth_value (ffecom_expr (expr));
2479     }
2480
2481   expand_start_cond (temp, 0);
2482
2483   /* No fake `else' constructs introduced (yet).  */
2484   ffestw_set_ifthen_fake_else (block, 0);
2485 }
2486
2487 /* ELSE IF statement.  */
2488
2489 void
2490 ffeste_R804 (ffestw block, ffebld expr)
2491 {
2492   tree temp;
2493
2494   ffeste_check_simple_ ();
2495
2496   ffeste_emit_line_note_ ();
2497
2498   /* Since ELSEIF(expr) might require preparations for expr,
2499      implement as ELSE; prepare-expr; IF (expr) THEN ...; ENDIF.  */
2500
2501   expand_start_else ();
2502
2503   ffeste_start_block_ (block);
2504
2505   temp = ffecom_make_tempvar ("elseif", integer_type_node,
2506                               FFETARGET_charactersizeNONE, -1);
2507
2508   ffeste_start_stmt_ ();
2509
2510   ffecom_prepare_expr (expr);
2511
2512   if (ffecom_prepare_end ())
2513     {
2514       tree result;
2515
2516       result = ffecom_modify (void_type_node,
2517                               temp,
2518                               ffecom_truth_value (ffecom_expr (expr)));
2519
2520       expand_expr_stmt (result);
2521
2522       ffeste_end_stmt_ ();
2523     }
2524   else
2525     {
2526       /* In this case, we could probably have used expand_start_elseif
2527          instead, saving the need for a fake `else' construct.  But,
2528          until it's clear that'd improve performance, it's easier this
2529          way, since we have to expand_start_else before we get to this
2530          test, given the current design.  */
2531
2532       ffeste_end_stmt_ ();
2533
2534       temp = ffecom_truth_value (ffecom_expr (expr));
2535     }
2536
2537   expand_start_cond (temp, 0);
2538
2539   /* Increment number of fake `else' constructs introduced.  */
2540   ffestw_set_ifthen_fake_else (block,
2541                                ffestw_ifthen_fake_else (block) + 1);
2542 }
2543
2544 /* ELSE statement.  */
2545
2546 void
2547 ffeste_R805 (ffestw block UNUSED)
2548 {
2549   ffeste_check_simple_ ();
2550
2551   ffeste_emit_line_note_ ();
2552
2553   expand_start_else ();
2554 }
2555
2556 /* END IF statement.  */
2557
2558 void
2559 ffeste_R806 (ffestw block)
2560 {
2561   int i = ffestw_ifthen_fake_else (block) + 1;
2562
2563   ffeste_emit_line_note_ ();
2564
2565   for (; i; --i)
2566     {
2567       expand_end_cond ();
2568
2569       ffeste_end_block_ (block);
2570     }
2571 }
2572
2573 /* Logical IF statement.  */
2574
2575 void
2576 ffeste_R807 (ffebld expr)
2577 {
2578   tree temp;
2579
2580   ffeste_check_simple_ ();
2581
2582   ffeste_emit_line_note_ ();
2583
2584   ffeste_start_block_ (NULL);
2585
2586   temp = ffecom_make_tempvar ("if", integer_type_node,
2587                               FFETARGET_charactersizeNONE, -1);
2588
2589   ffeste_start_stmt_ ();
2590
2591   ffecom_prepare_expr (expr);
2592
2593   if (ffecom_prepare_end ())
2594     {
2595       tree result;
2596
2597       result = ffecom_modify (void_type_node,
2598                               temp,
2599                               ffecom_truth_value (ffecom_expr (expr)));
2600
2601       expand_expr_stmt (result);
2602
2603       ffeste_end_stmt_ ();
2604     }
2605   else
2606     {
2607       ffeste_end_stmt_ ();
2608
2609       temp = ffecom_truth_value (ffecom_expr (expr));
2610     }
2611
2612   expand_start_cond (temp, 0);
2613 }
2614
2615 /* SELECT CASE statement.  */
2616
2617 void
2618 ffeste_R809 (ffestw block, ffebld expr)
2619 {
2620   ffeste_check_simple_ ();
2621
2622   ffeste_emit_line_note_ ();
2623
2624   ffeste_start_block_ (block);
2625
2626   if ((expr == NULL)
2627       || (ffeinfo_basictype (ffebld_info (expr))
2628           == FFEINFO_basictypeANY))
2629     ffestw_set_select_texpr (block, error_mark_node);
2630   else if (ffeinfo_basictype (ffebld_info (expr))
2631            == FFEINFO_basictypeCHARACTER)
2632     {
2633       /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2634
2635       /* xgettext:no-c-format */
2636       ffebad_start_msg ("SELECT CASE on CHARACTER type (at %0) not supported -- sorry",
2637                         FFEBAD_severityFATAL);
2638       ffebad_here (0, ffestw_line (block), ffestw_col (block));
2639       ffebad_finish ();
2640       ffestw_set_select_texpr (block, error_mark_node);
2641     }
2642   else
2643     {
2644       tree result;
2645       tree texpr;
2646
2647       result = ffecom_make_tempvar ("select", ffecom_type_expr (expr),
2648                                     ffeinfo_size (ffebld_info (expr)),
2649                                     -1);
2650
2651       ffeste_start_stmt_ ();
2652
2653       ffecom_prepare_expr (expr);
2654
2655       ffecom_prepare_end ();
2656
2657       texpr = ffecom_expr (expr);
2658
2659       assert (TYPE_MAIN_VARIANT (TREE_TYPE (texpr))
2660               == TYPE_MAIN_VARIANT (TREE_TYPE (result)));
2661
2662       texpr = ffecom_modify (void_type_node,
2663                              result,
2664                              texpr);
2665       expand_expr_stmt (texpr);
2666
2667       ffeste_end_stmt_ ();
2668
2669       expand_start_case (1, result, TREE_TYPE (result),
2670                          "SELECT CASE statement");
2671       ffestw_set_select_texpr (block, texpr);
2672       ffestw_set_select_break (block, FALSE);
2673     }
2674 }
2675
2676 /* CASE statement.
2677
2678    If casenum is 0, it's CASE DEFAULT.  Else it's the case ranges at
2679    the start of the first_stmt list in the select object at the top of
2680    the stack that match casenum.  */
2681
2682 void
2683 ffeste_R810 (ffestw block, unsigned long casenum)
2684 {
2685   ffestwSelect s = ffestw_select (block);
2686   ffestwCase c;
2687   tree texprlow;
2688   tree texprhigh;
2689   tree tlabel;
2690   int pushok;
2691   tree duplicate;
2692
2693   ffeste_check_simple_ ();
2694
2695   if (s->first_stmt == (ffestwCase) &s->first_rel)
2696     c = NULL;
2697   else
2698     c = s->first_stmt;
2699
2700   ffeste_emit_line_note_ ();
2701
2702   if (ffestw_select_texpr (block) == error_mark_node)
2703     return;
2704
2705   /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2706
2707   tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
2708
2709   if (ffestw_select_break (block))
2710     expand_exit_something ();
2711   else
2712     ffestw_set_select_break (block, TRUE);
2713
2714   if ((c == NULL) || (casenum != c->casenum))
2715     {
2716       if (casenum == 0) /* Intentional CASE DEFAULT. */
2717         {
2718           pushok = pushcase (NULL_TREE, 0, tlabel, &duplicate);
2719           assert (pushok == 0);
2720         }
2721     }
2722   else
2723     do
2724       {
2725         texprlow = (c->low == NULL) ? NULL_TREE
2726           : ffecom_constantunion (&ffebld_constant_union (c->low), s->type,
2727                                   s->kindtype,
2728                                   ffecom_tree_type[s->type][s->kindtype]);
2729         if (c->low != c->high)
2730           {
2731             texprhigh = (c->high == NULL) ? NULL_TREE
2732               : ffecom_constantunion (&ffebld_constant_union (c->high),
2733                                       s->type, s->kindtype,
2734                                       ffecom_tree_type[s->type][s->kindtype]);
2735             pushok = pushcase_range (texprlow, texprhigh, convert,
2736                                      tlabel, &duplicate);
2737           }
2738         else
2739           pushok = pushcase (texprlow, convert, tlabel, &duplicate);
2740         assert (pushok == 0);
2741         c = c->next_stmt;
2742         /* Unlink prev.  */
2743         c->previous_stmt->previous_stmt->next_stmt = c;
2744         c->previous_stmt = c->previous_stmt->previous_stmt;
2745       }
2746     while ((c != (ffestwCase) &s->first_rel) && (casenum == c->casenum));
2747 }
2748
2749 /* END SELECT statement.  */
2750
2751 void
2752 ffeste_R811 (ffestw block)
2753 {
2754   ffeste_emit_line_note_ ();
2755
2756   /* ~~~Someday handle CHARACTER*1, CHARACTER*N */
2757
2758   if (TREE_CODE (ffestw_select_texpr (block)) != ERROR_MARK)
2759     expand_end_case (ffestw_select_texpr (block));
2760
2761   ffeste_end_block_ (block);
2762 }
2763
2764 /* Iterative DO statement.  */
2765
2766 void
2767 ffeste_R819A (ffestw block, ffelab label UNUSED, ffebld var,
2768               ffebld start, ffelexToken start_token,
2769               ffebld end, ffelexToken end_token,
2770               ffebld incr, ffelexToken incr_token)
2771 {
2772   ffeste_check_simple_ ();
2773
2774   ffeste_emit_line_note_ ();
2775
2776   ffeste_begin_iterdo_ (block, NULL, NULL, NULL,
2777                         var,
2778                         start, start_token,
2779                         end, end_token,
2780                         incr, incr_token,
2781                         "Iterative DO loop");
2782 }
2783
2784 /* DO WHILE statement.  */
2785
2786 void
2787 ffeste_R819B (ffestw block, ffelab label UNUSED, ffebld expr)
2788 {
2789   tree result;
2790
2791   ffeste_check_simple_ ();
2792
2793   ffeste_emit_line_note_ ();
2794
2795   ffeste_start_block_ (block);
2796
2797   if (expr)
2798     {
2799       struct nesting *loop;
2800       tree mod;
2801
2802       result = ffecom_make_tempvar ("dowhile", integer_type_node,
2803                                     FFETARGET_charactersizeNONE, -1);
2804       loop = expand_start_loop (1);
2805
2806       ffeste_start_stmt_ ();
2807
2808       ffecom_prepare_expr (expr);
2809
2810       ffecom_prepare_end ();
2811
2812       mod = ffecom_modify (void_type_node,
2813                            result,
2814                            ffecom_truth_value (ffecom_expr (expr)));
2815       expand_expr_stmt (mod);
2816
2817       ffeste_end_stmt_ ();
2818
2819       ffestw_set_do_hook (block, loop);
2820       expand_exit_loop_top_cond (0, result);
2821     }
2822   else
2823     ffestw_set_do_hook (block, expand_start_loop (1));
2824
2825   ffestw_set_do_tvar (block, NULL_TREE);
2826 }
2827
2828 /* END DO statement.
2829
2830    This is the MIL-STD 1753 END DO. It's syntactic sugar, similar to
2831    CONTINUE (except that it has to have a label that is the target of
2832    one or more iterative DO statement), not the Fortran-90 structured
2833    END DO, which is handled elsewhere, as is the actual mechanism of
2834    ending an iterative DO statement, even one that ends at a label.  */
2835
2836 void
2837 ffeste_R825 ()
2838 {
2839   ffeste_check_simple_ ();
2840
2841   ffeste_emit_line_note_ ();
2842
2843   emit_nop ();
2844 }
2845
2846 /* CYCLE statement.  */
2847
2848 void
2849 ffeste_R834 (ffestw block)
2850 {
2851   ffeste_check_simple_ ();
2852
2853   ffeste_emit_line_note_ ();
2854
2855   expand_continue_loop (ffestw_do_hook (block));
2856 }
2857
2858 /* EXIT statement.  */
2859
2860 void
2861 ffeste_R835 (ffestw block)
2862 {
2863   ffeste_check_simple_ ();
2864
2865   ffeste_emit_line_note_ ();
2866
2867   expand_exit_loop (ffestw_do_hook (block));
2868 }
2869
2870 /* GOTO statement.  */
2871
2872 void
2873 ffeste_R836 (ffelab label)
2874 {
2875   tree glabel;
2876
2877   ffeste_check_simple_ ();
2878
2879   ffeste_emit_line_note_ ();
2880
2881   glabel = ffecom_lookup_label (label);
2882   if ((glabel != NULL_TREE)
2883       && (TREE_CODE (glabel) != ERROR_MARK))
2884     {
2885       expand_goto (glabel);
2886       TREE_USED (glabel) = 1;
2887     }
2888 }
2889
2890 /* Computed GOTO statement.  */
2891
2892 void
2893 ffeste_R837 (ffelab *labels, int count, ffebld expr)
2894 {
2895   int i;
2896   tree texpr;
2897   tree value;
2898   tree tlabel;
2899   int pushok;
2900   tree duplicate;
2901
2902   ffeste_check_simple_ ();
2903
2904   ffeste_emit_line_note_ ();
2905
2906   ffeste_start_stmt_ ();
2907
2908   ffecom_prepare_expr (expr);
2909
2910   ffecom_prepare_end ();
2911
2912   texpr = ffecom_expr (expr);
2913
2914   expand_start_case (0, texpr, TREE_TYPE (texpr), "computed GOTO statement");
2915
2916   for (i = 0; i < count; ++i)
2917     {
2918       value = build_int_2 (i + 1, 0);
2919       tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
2920
2921       pushok = pushcase (value, convert, tlabel, &duplicate);
2922       assert (pushok == 0);
2923
2924       tlabel = ffecom_lookup_label (labels[i]);
2925       if ((tlabel == NULL_TREE)
2926           || (TREE_CODE (tlabel) == ERROR_MARK))
2927         continue;
2928
2929       expand_goto (tlabel);
2930       TREE_USED (tlabel) = 1;
2931     }
2932   expand_end_case (texpr);
2933
2934   ffeste_end_stmt_ ();
2935 }
2936
2937 /* ASSIGN statement.  */
2938
2939 void
2940 ffeste_R838 (ffelab label, ffebld target)
2941 {
2942   tree expr_tree;
2943   tree label_tree;
2944   tree target_tree;
2945
2946   ffeste_check_simple_ ();
2947
2948   ffeste_emit_line_note_ ();
2949
2950     /* No need to call ffeste_start_stmt_(), as the sorts of expressions
2951        seen here should never require use of temporaries.  */
2952
2953   label_tree = ffecom_lookup_label (label);
2954   if ((label_tree != NULL_TREE)
2955       && (TREE_CODE (label_tree) != ERROR_MARK))
2956     {
2957       label_tree = ffecom_1 (ADDR_EXPR,
2958                              build_pointer_type (void_type_node),
2959                              label_tree);
2960       TREE_CONSTANT (label_tree) = 1;
2961
2962       target_tree = ffecom_expr_assign_w (target);
2963       if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (target_tree)))
2964           < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (label_tree))))
2965         error ("ASSIGN to variable that is too small");
2966
2967       label_tree = convert (TREE_TYPE (target_tree), label_tree);
2968
2969       expr_tree = ffecom_modify (void_type_node,
2970                                  target_tree,
2971                                  label_tree);
2972       expand_expr_stmt (expr_tree);
2973     }
2974 }
2975
2976 /* Assigned GOTO statement.  */
2977
2978 void
2979 ffeste_R839 (ffebld target)
2980 {
2981   tree t;
2982
2983   ffeste_check_simple_ ();
2984
2985   ffeste_emit_line_note_ ();
2986
2987   /* No need to call ffeste_start_stmt_(), as the sorts of expressions
2988      seen here should never require use of temporaries.  */
2989
2990   t = ffecom_expr_assign (target);
2991   if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (t)))
2992       < GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (null_pointer_node))))
2993     error ("ASSIGNed GOTO target variable is too small");
2994
2995   expand_computed_goto (convert (TREE_TYPE (null_pointer_node), t));
2996 }
2997
2998 /* Arithmetic IF statement.  */
2999
3000 void
3001 ffeste_R840 (ffebld expr, ffelab neg, ffelab zero, ffelab pos)
3002 {
3003   tree gneg = ffecom_lookup_label (neg);
3004   tree gzero = ffecom_lookup_label (zero);
3005   tree gpos = ffecom_lookup_label (pos);
3006   tree texpr;
3007
3008   ffeste_check_simple_ ();
3009
3010   ffeste_emit_line_note_ ();
3011
3012   if ((gneg == NULL_TREE) || (gzero == NULL_TREE) || (gpos == NULL_TREE))
3013     return;
3014   if ((TREE_CODE (gneg) == ERROR_MARK)
3015       || (TREE_CODE (gzero) == ERROR_MARK)
3016       || (TREE_CODE (gpos) == ERROR_MARK))
3017     return;
3018
3019   ffeste_start_stmt_ ();
3020
3021   ffecom_prepare_expr (expr);
3022
3023   ffecom_prepare_end ();
3024
3025   if (neg == zero)
3026     {
3027       if (neg == pos)
3028         expand_goto (gzero);
3029       else
3030         {
3031           /* IF (expr.LE.0) THEN GOTO neg/zero ELSE GOTO pos.  */
3032           texpr = ffecom_expr (expr);
3033           texpr = ffecom_2 (LE_EXPR, integer_type_node,
3034                             texpr,
3035                             convert (TREE_TYPE (texpr),
3036                                      integer_zero_node));
3037           expand_start_cond (ffecom_truth_value (texpr), 0);
3038           expand_goto (gzero);
3039           expand_start_else ();
3040           expand_goto (gpos);
3041           expand_end_cond ();
3042         }
3043     }
3044   else if (neg == pos)
3045     {
3046       /* IF (expr.NE.0) THEN GOTO neg/pos ELSE GOTO zero.  */
3047       texpr = ffecom_expr (expr);
3048       texpr = ffecom_2 (NE_EXPR, integer_type_node,
3049                         texpr,
3050                         convert (TREE_TYPE (texpr),
3051                                  integer_zero_node));
3052       expand_start_cond (ffecom_truth_value (texpr), 0);
3053       expand_goto (gneg);
3054       expand_start_else ();
3055       expand_goto (gzero);
3056       expand_end_cond ();
3057     }
3058   else if (zero == pos)
3059     {
3060       /* IF (expr.GE.0) THEN GOTO zero/pos ELSE GOTO neg.  */
3061       texpr = ffecom_expr (expr);
3062       texpr = ffecom_2 (GE_EXPR, integer_type_node,
3063                         texpr,
3064                         convert (TREE_TYPE (texpr),
3065                                  integer_zero_node));
3066       expand_start_cond (ffecom_truth_value (texpr), 0);
3067       expand_goto (gzero);
3068       expand_start_else ();
3069       expand_goto (gneg);
3070       expand_end_cond ();
3071     }
3072   else
3073     {
3074       /* Use a SAVE_EXPR in combo with:
3075          IF (expr.LT.0) THEN GOTO neg
3076          ELSEIF (expr.GT.0) THEN GOTO pos
3077          ELSE GOTO zero.  */
3078       tree expr_saved = ffecom_save_tree (ffecom_expr (expr));
3079
3080       texpr = ffecom_2 (LT_EXPR, integer_type_node,
3081                         expr_saved,
3082                         convert (TREE_TYPE (expr_saved),
3083                                  integer_zero_node));
3084       expand_start_cond (ffecom_truth_value (texpr), 0);
3085       expand_goto (gneg);
3086       texpr = ffecom_2 (GT_EXPR, integer_type_node,
3087                         expr_saved,
3088                         convert (TREE_TYPE (expr_saved),
3089                                  integer_zero_node));
3090       expand_start_elseif (ffecom_truth_value (texpr));
3091       expand_goto (gpos);
3092       expand_start_else ();
3093       expand_goto (gzero);
3094       expand_end_cond ();
3095     }
3096
3097   ffeste_end_stmt_ ();
3098 }
3099
3100 /* CONTINUE statement.  */
3101
3102 void
3103 ffeste_R841 ()
3104 {
3105   ffeste_check_simple_ ();
3106
3107   ffeste_emit_line_note_ ();
3108
3109   emit_nop ();
3110 }
3111
3112 /* STOP statement.  */
3113
3114 void
3115 ffeste_R842 (ffebld expr)
3116 {
3117   tree callit;
3118   ffelexToken msg;
3119
3120   ffeste_check_simple_ ();
3121
3122   ffeste_emit_line_note_ ();
3123
3124   if ((expr == NULL)
3125       || (ffeinfo_basictype (ffebld_info (expr))
3126           == FFEINFO_basictypeANY))
3127     {
3128       msg = ffelex_token_new_character ("",
3129                                         ffelex_token_where_line (ffesta_tokens[0]),
3130                                         ffelex_token_where_column (ffesta_tokens[0]));
3131       expr = ffebld_new_conter (ffebld_constant_new_characterdefault
3132                                 (msg));
3133       ffelex_token_kill (msg);
3134       ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3135                                           FFEINFO_kindtypeCHARACTERDEFAULT,
3136                                           0, FFEINFO_kindENTITY,
3137                                           FFEINFO_whereCONSTANT, 0));
3138     }
3139   else if (ffeinfo_basictype (ffebld_info (expr))
3140            == FFEINFO_basictypeINTEGER)
3141     {
3142       char num[50];
3143
3144       assert (ffebld_op (expr) == FFEBLD_opCONTER);
3145       assert (ffeinfo_kindtype (ffebld_info (expr))
3146               == FFEINFO_kindtypeINTEGERDEFAULT);
3147       sprintf (num, "%" ffetargetIntegerDefault_f "d",
3148                ffebld_constant_integer1 (ffebld_conter (expr)));
3149       msg = ffelex_token_new_character (num,
3150                                         ffelex_token_where_line (ffesta_tokens[0]),
3151                                         ffelex_token_where_column (ffesta_tokens[0]));
3152       expr = ffebld_new_conter (ffebld_constant_new_characterdefault (msg));
3153       ffelex_token_kill (msg);
3154       ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3155                                           FFEINFO_kindtypeCHARACTERDEFAULT,
3156                                           0, FFEINFO_kindENTITY,
3157                                           FFEINFO_whereCONSTANT, 0));
3158     }
3159   else
3160     {
3161       assert (ffeinfo_basictype (ffebld_info (expr))
3162               == FFEINFO_basictypeCHARACTER);
3163       assert (ffebld_op (expr) == FFEBLD_opCONTER);
3164       assert (ffeinfo_kindtype (ffebld_info (expr))
3165               == FFEINFO_kindtypeCHARACTERDEFAULT);
3166     }
3167
3168   /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3169      seen here should never require use of temporaries.  */
3170
3171   callit = ffecom_call_gfrt (FFECOM_gfrtSTOP,
3172                              ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3173                              NULL_TREE);
3174   TREE_SIDE_EFFECTS (callit) = 1;
3175
3176   expand_expr_stmt (callit);
3177 }
3178
3179 /* PAUSE statement.  */
3180
3181 void
3182 ffeste_R843 (ffebld expr)
3183 {
3184   tree callit;
3185   ffelexToken msg;
3186
3187   ffeste_check_simple_ ();
3188
3189   ffeste_emit_line_note_ ();
3190
3191   if ((expr == NULL)
3192       || (ffeinfo_basictype (ffebld_info (expr))
3193           == FFEINFO_basictypeANY))
3194     {
3195       msg = ffelex_token_new_character ("",
3196                                         ffelex_token_where_line (ffesta_tokens[0]),
3197                                         ffelex_token_where_column (ffesta_tokens[0]));
3198       expr = ffebld_new_conter (ffebld_constant_new_characterdefault (msg));
3199       ffelex_token_kill (msg);
3200       ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3201                                           FFEINFO_kindtypeCHARACTERDEFAULT,
3202                                           0, FFEINFO_kindENTITY,
3203                                           FFEINFO_whereCONSTANT, 0));
3204     }
3205   else if (ffeinfo_basictype (ffebld_info (expr)) == FFEINFO_basictypeINTEGER)
3206     {
3207       char num[50];
3208
3209       assert (ffebld_op (expr) == FFEBLD_opCONTER);
3210       assert (ffeinfo_kindtype (ffebld_info (expr))
3211               == FFEINFO_kindtypeINTEGERDEFAULT);
3212       sprintf (num, "%" ffetargetIntegerDefault_f "d",
3213                ffebld_constant_integer1 (ffebld_conter (expr)));
3214       msg = ffelex_token_new_character (num, ffelex_token_where_line (ffesta_tokens[0]),
3215                                         ffelex_token_where_column (ffesta_tokens[0]));
3216       expr = ffebld_new_conter (ffebld_constant_new_characterdefault (msg));
3217       ffelex_token_kill (msg);
3218       ffebld_set_info (expr, ffeinfo_new (FFEINFO_basictypeCHARACTER,
3219                                           FFEINFO_kindtypeCHARACTERDEFAULT,
3220                                           0, FFEINFO_kindENTITY,
3221                                           FFEINFO_whereCONSTANT, 0));
3222     }
3223   else
3224     {
3225       assert (ffeinfo_basictype (ffebld_info (expr))
3226               == FFEINFO_basictypeCHARACTER);
3227       assert (ffebld_op (expr) == FFEBLD_opCONTER);
3228       assert (ffeinfo_kindtype (ffebld_info (expr))
3229               == FFEINFO_kindtypeCHARACTERDEFAULT);
3230     }
3231
3232   /* No need to call ffeste_start_stmt_(), as the sorts of expressions
3233      seen here should never require use of temporaries.  */
3234
3235   callit = ffecom_call_gfrt (FFECOM_gfrtPAUSE,
3236                              ffecom_list_ptr_to_expr (ffebld_new_item (expr, NULL)),
3237                              NULL_TREE);
3238   TREE_SIDE_EFFECTS (callit) = 1;
3239
3240   expand_expr_stmt (callit);
3241 }
3242
3243 /* OPEN statement.  */
3244
3245 void
3246 ffeste_R904 (ffestpOpenStmt *info)
3247 {
3248   tree args;
3249   bool iostat;
3250   bool errl;
3251
3252   ffeste_check_simple_ ();
3253
3254   ffeste_emit_line_note_ ();
3255
3256 #define specified(something) (info->open_spec[something].kw_or_val_present)
3257
3258   iostat = specified (FFESTP_openixIOSTAT);
3259   errl = specified (FFESTP_openixERR);
3260
3261 #undef specified
3262
3263   ffeste_start_stmt_ ();
3264
3265   if (errl)
3266     {
3267       ffeste_io_err_
3268         = ffeste_io_abort_
3269         = ffecom_lookup_label
3270         (info->open_spec[FFESTP_openixERR].u.label);
3271       ffeste_io_abort_is_temp_ = FALSE;
3272     }
3273   else
3274     {
3275       ffeste_io_err_ = NULL_TREE;
3276
3277       if ((ffeste_io_abort_is_temp_ = iostat))
3278         ffeste_io_abort_ = ffecom_temp_label ();
3279       else
3280         ffeste_io_abort_ = NULL_TREE;
3281     }
3282
3283   if (iostat)
3284     {
3285       /* Have IOSTAT= specification.  */
3286
3287       ffeste_io_iostat_is_temp_ = FALSE;
3288       ffeste_io_iostat_ = ffecom_expr
3289         (info->open_spec[FFESTP_openixIOSTAT].u.expr);
3290     }
3291   else if (ffeste_io_abort_ != NULL_TREE)
3292     {
3293       /* Have no IOSTAT= but have ERR=.  */
3294
3295       ffeste_io_iostat_is_temp_ = TRUE;
3296       ffeste_io_iostat_
3297         = ffecom_make_tempvar ("open", ffecom_integer_type_node,
3298                                FFETARGET_charactersizeNONE, -1);
3299     }
3300   else
3301     {
3302       /* No IOSTAT= or ERR= specification.  */
3303
3304       ffeste_io_iostat_is_temp_ = FALSE;
3305       ffeste_io_iostat_ = NULL_TREE;
3306     }
3307
3308   /* Now prescan, then convert, all the arguments.  */
3309
3310   args = ffeste_io_olist_ (errl || iostat,
3311                            info->open_spec[FFESTP_openixUNIT].u.expr,
3312                            &info->open_spec[FFESTP_openixFILE],
3313                            &info->open_spec[FFESTP_openixSTATUS],
3314                            &info->open_spec[FFESTP_openixACCESS],
3315                            &info->open_spec[FFESTP_openixFORM],
3316                            &info->open_spec[FFESTP_openixRECL],
3317                            &info->open_spec[FFESTP_openixBLANK]);
3318
3319   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3320        label, since we're gonna fall through to there anyway. */
3321
3322   ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFOPEN, args, NULL_TREE),
3323                    ! ffeste_io_abort_is_temp_);
3324
3325   /* If we've got a temp label, generate its code here.  */
3326
3327   if (ffeste_io_abort_is_temp_)
3328     {
3329       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3330       emit_nop ();
3331       expand_label (ffeste_io_abort_);
3332
3333       assert (ffeste_io_err_ == NULL_TREE);
3334     }
3335
3336   ffeste_end_stmt_ ();
3337 }
3338
3339 /* CLOSE statement.  */
3340
3341 void
3342 ffeste_R907 (ffestpCloseStmt *info)
3343 {
3344   tree args;
3345   bool iostat;
3346   bool errl;
3347
3348   ffeste_check_simple_ ();
3349
3350   ffeste_emit_line_note_ ();
3351
3352 #define specified(something) (info->close_spec[something].kw_or_val_present)
3353
3354   iostat = specified (FFESTP_closeixIOSTAT);
3355   errl = specified (FFESTP_closeixERR);
3356
3357 #undef specified
3358
3359   ffeste_start_stmt_ ();
3360
3361   if (errl)
3362     {
3363       ffeste_io_err_
3364         = ffeste_io_abort_
3365         = ffecom_lookup_label
3366         (info->close_spec[FFESTP_closeixERR].u.label);
3367       ffeste_io_abort_is_temp_ = FALSE;
3368     }
3369   else
3370     {
3371       ffeste_io_err_ = NULL_TREE;
3372
3373       if ((ffeste_io_abort_is_temp_ = iostat))
3374         ffeste_io_abort_ = ffecom_temp_label ();
3375       else
3376         ffeste_io_abort_ = NULL_TREE;
3377     }
3378
3379   if (iostat)
3380     {
3381       /* Have IOSTAT= specification.  */
3382
3383       ffeste_io_iostat_is_temp_ = FALSE;
3384       ffeste_io_iostat_ = ffecom_expr
3385         (info->close_spec[FFESTP_closeixIOSTAT].u.expr);
3386     }
3387   else if (ffeste_io_abort_ != NULL_TREE)
3388     {
3389       /* Have no IOSTAT= but have ERR=.  */
3390
3391       ffeste_io_iostat_is_temp_ = TRUE;
3392       ffeste_io_iostat_
3393         = ffecom_make_tempvar ("close", ffecom_integer_type_node,
3394                                FFETARGET_charactersizeNONE, -1);
3395     }
3396   else
3397     {
3398       /* No IOSTAT= or ERR= specification.  */
3399
3400       ffeste_io_iostat_is_temp_ = FALSE;
3401       ffeste_io_iostat_ = NULL_TREE;
3402     }
3403
3404   /* Now prescan, then convert, all the arguments.  */
3405
3406   args = ffeste_io_cllist_ (errl || iostat,
3407                             info->close_spec[FFESTP_closeixUNIT].u.expr,
3408                             &info->close_spec[FFESTP_closeixSTATUS]);
3409
3410   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3411        label, since we're gonna fall through to there anyway. */
3412
3413   ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFCLOS, args, NULL_TREE),
3414                    ! ffeste_io_abort_is_temp_);
3415
3416   /* If we've got a temp label, generate its code here. */
3417
3418   if (ffeste_io_abort_is_temp_)
3419     {
3420       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3421       emit_nop ();
3422       expand_label (ffeste_io_abort_);
3423
3424       assert (ffeste_io_err_ == NULL_TREE);
3425     }
3426
3427   ffeste_end_stmt_ ();
3428 }
3429
3430 /* READ(...) statement -- start.  */
3431
3432 void
3433 ffeste_R909_start (ffestpReadStmt *info, bool only_format UNUSED,
3434                    ffestvUnit unit, ffestvFormat format, bool rec,
3435                    bool key UNUSED)
3436 {
3437   ffecomGfrt start;
3438   ffecomGfrt end;
3439   tree cilist;
3440   bool iostat;
3441   bool errl;
3442   bool endl;
3443
3444   ffeste_check_start_ ();
3445
3446   ffeste_emit_line_note_ ();
3447
3448   /* First determine the start, per-item, and end run-time functions to
3449      call.  The per-item function is picked by choosing an ffeste function
3450      to call to handle a given item; it knows how to generate a call to the
3451      appropriate run-time function, and is called an "I/O driver".  */
3452
3453   switch (format)
3454     {
3455     case FFESTV_formatNONE:     /* no FMT= */
3456       ffeste_io_driver_ = ffeste_io_douio_;
3457       if (rec)
3458         start = FFECOM_gfrtSRDUE, end = FFECOM_gfrtERDUE;
3459       else
3460         start = FFECOM_gfrtSRSUE, end = FFECOM_gfrtERSUE;
3461       break;
3462
3463     case FFESTV_formatLABEL:    /* FMT=10 */
3464     case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
3465     case FFESTV_formatINTEXPR:  /* FMT=I [after ASSIGN 10 TO I] */
3466       ffeste_io_driver_ = ffeste_io_dofio_;
3467       if (rec)
3468         start = FFECOM_gfrtSRDFE, end = FFECOM_gfrtERDFE;
3469       else if (unit == FFESTV_unitCHAREXPR)
3470         start = FFECOM_gfrtSRSFI, end = FFECOM_gfrtERSFI;
3471       else
3472         start = FFECOM_gfrtSRSFE, end = FFECOM_gfrtERSFE;
3473       break;
3474
3475     case FFESTV_formatASTERISK: /* FMT=* */
3476       ffeste_io_driver_ = ffeste_io_dolio_;
3477       if (unit == FFESTV_unitCHAREXPR)
3478         start = FFECOM_gfrtSRSLI, end = FFECOM_gfrtERSLI;
3479       else
3480         start = FFECOM_gfrtSRSLE, end = FFECOM_gfrtERSLE;
3481       break;
3482
3483     case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
3484                                    /FOO/] */
3485       ffeste_io_driver_ = NULL; /* No start or driver function. */
3486       start = FFECOM_gfrtSRSNE, end = FFECOM_gfrt;
3487       break;
3488
3489     default:
3490       assert ("Weird stuff" == NULL);
3491       start = FFECOM_gfrt, end = FFECOM_gfrt;
3492       break;
3493     }
3494   ffeste_io_endgfrt_ = end;
3495
3496 #define specified(something) (info->read_spec[something].kw_or_val_present)
3497
3498   iostat = specified (FFESTP_readixIOSTAT);
3499   errl = specified (FFESTP_readixERR);
3500   endl = specified (FFESTP_readixEND);
3501
3502 #undef specified
3503
3504   ffeste_start_stmt_ ();
3505
3506   if (errl)
3507     {
3508       /* Have ERR= specification.   */
3509
3510       ffeste_io_err_
3511         = ffecom_lookup_label (info->read_spec[FFESTP_readixERR].u.label);
3512
3513       if (endl)
3514         {
3515           /* Have both ERR= and END=.  Need a temp label to handle both.  */
3516           ffeste_io_end_
3517             = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
3518           ffeste_io_abort_is_temp_ = TRUE;
3519           ffeste_io_abort_ = ffecom_temp_label ();
3520         }
3521       else
3522         {
3523           /* Have ERR= but no END=.  */
3524           ffeste_io_end_ = NULL_TREE;
3525           if ((ffeste_io_abort_is_temp_ = iostat))
3526             ffeste_io_abort_ = ffecom_temp_label ();
3527           else
3528             ffeste_io_abort_ = ffeste_io_err_;
3529         }
3530     }
3531   else
3532     {
3533       /* No ERR= specification.  */
3534
3535       ffeste_io_err_ = NULL_TREE;
3536       if (endl)
3537         {
3538           /* Have END= but no ERR=.  */
3539           ffeste_io_end_
3540             = ffecom_lookup_label (info->read_spec[FFESTP_readixEND].u.label);
3541           if ((ffeste_io_abort_is_temp_ = iostat))
3542             ffeste_io_abort_ = ffecom_temp_label ();
3543           else
3544             ffeste_io_abort_ = ffeste_io_end_;
3545         }
3546       else
3547         {
3548           /* Have no ERR= or END=.  */
3549
3550           ffeste_io_end_ = NULL_TREE;
3551           if ((ffeste_io_abort_is_temp_ = iostat))
3552             ffeste_io_abort_ = ffecom_temp_label ();
3553           else
3554             ffeste_io_abort_ = NULL_TREE;
3555         }
3556     }
3557
3558   if (iostat)
3559     {
3560       /* Have IOSTAT= specification.  */
3561
3562       ffeste_io_iostat_is_temp_ = FALSE;
3563       ffeste_io_iostat_
3564         = ffecom_expr (info->read_spec[FFESTP_readixIOSTAT].u.expr);
3565     }
3566   else if (ffeste_io_abort_ != NULL_TREE)
3567     {
3568       /* Have no IOSTAT= but have ERR= and/or END=.  */
3569
3570       ffeste_io_iostat_is_temp_ = TRUE;
3571       ffeste_io_iostat_
3572         = ffecom_make_tempvar ("read", ffecom_integer_type_node,
3573                                FFETARGET_charactersizeNONE, -1);
3574     }
3575   else
3576     {
3577       /* No IOSTAT=, ERR=, or END= specification.  */
3578
3579       ffeste_io_iostat_is_temp_ = FALSE;
3580       ffeste_io_iostat_ = NULL_TREE;
3581     }
3582
3583   /* Now prescan, then convert, all the arguments.  */
3584
3585   if (unit == FFESTV_unitCHAREXPR)
3586     cilist = ffeste_io_icilist_ (errl || iostat,
3587                                  info->read_spec[FFESTP_readixUNIT].u.expr,
3588                                  endl || iostat, format,
3589                                  &info->read_spec[FFESTP_readixFORMAT]);
3590   else
3591     cilist = ffeste_io_cilist_ (errl || iostat, unit,
3592                                 info->read_spec[FFESTP_readixUNIT].u.expr,
3593                                 5, endl || iostat, format,
3594                                 &info->read_spec[FFESTP_readixFORMAT],
3595                                 rec,
3596                                 info->read_spec[FFESTP_readixREC].u.expr);
3597
3598   /* If there is no end function, then there are no item functions (i.e.
3599      it's a NAMELIST), and vice versa by the way.  In this situation, don't
3600      generate the "if (iostat != 0) goto label;" if the label is temp abort
3601      label, since we're gonna fall through to there anyway.  */
3602
3603   ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
3604                    (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
3605 }
3606
3607 /* READ statement -- I/O item.  */
3608
3609 void
3610 ffeste_R909_item (ffebld expr, ffelexToken expr_token)
3611 {
3612   ffeste_check_item_ ();
3613
3614   if (expr == NULL)
3615     return;
3616
3617   /* Strip parens off items such as in "READ *,(A)".  This is really a bug
3618      in the user's code, but I've been told lots of code does this.  */
3619   while (ffebld_op (expr) == FFEBLD_opPAREN)
3620     expr = ffebld_left (expr);
3621
3622   if (ffebld_op (expr) == FFEBLD_opANY)
3623     return;
3624
3625   if (ffebld_op (expr) == FFEBLD_opIMPDO)
3626     ffeste_io_impdo_ (expr, expr_token);
3627   else
3628     {
3629       ffeste_start_stmt_ ();
3630
3631       ffecom_prepare_arg_ptr_to_expr (expr);
3632
3633       ffecom_prepare_end ();
3634
3635       ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
3636
3637       ffeste_end_stmt_ ();
3638     }
3639 }
3640
3641 /* READ statement -- end.  */
3642
3643 void
3644 ffeste_R909_finish ()
3645 {
3646   ffeste_check_finish_ ();
3647
3648   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3649      label, since we're gonna fall through to there anyway. */
3650
3651   if (ffeste_io_endgfrt_ != FFECOM_gfrt)
3652     ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
3653                                        NULL_TREE),
3654                      ! ffeste_io_abort_is_temp_);
3655
3656   /* If we've got a temp label, generate its code here and have it fan out
3657      to the END= or ERR= label as appropriate. */
3658
3659   if (ffeste_io_abort_is_temp_)
3660     {
3661       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3662       emit_nop ();
3663       expand_label (ffeste_io_abort_);
3664
3665       /* "if (iostat<0) goto end_label;".  */
3666
3667       if ((ffeste_io_end_ != NULL_TREE)
3668           && (TREE_CODE (ffeste_io_end_) != ERROR_MARK))
3669         {
3670           expand_start_cond (ffecom_truth_value
3671                              (ffecom_2 (LT_EXPR, integer_type_node,
3672                                         ffeste_io_iostat_,
3673                                         ffecom_integer_zero_node)),
3674                              0);
3675           expand_goto (ffeste_io_end_);
3676           expand_end_cond ();
3677         }
3678
3679       /* "if (iostat>0) goto err_label;".  */
3680
3681       if ((ffeste_io_err_ != NULL_TREE)
3682           && (TREE_CODE (ffeste_io_err_) != ERROR_MARK))
3683         {
3684           expand_start_cond (ffecom_truth_value
3685                              (ffecom_2 (GT_EXPR, integer_type_node,
3686                                         ffeste_io_iostat_,
3687                                         ffecom_integer_zero_node)),
3688                              0);
3689           expand_goto (ffeste_io_err_);
3690           expand_end_cond ();
3691         }
3692     }
3693
3694   ffeste_end_stmt_ ();
3695 }
3696
3697 /* WRITE statement -- start.  */
3698
3699 void
3700 ffeste_R910_start (ffestpWriteStmt *info, ffestvUnit unit,
3701                    ffestvFormat format, bool rec)
3702 {
3703   ffecomGfrt start;
3704   ffecomGfrt end;
3705   tree cilist;
3706   bool iostat;
3707   bool errl;
3708
3709   ffeste_check_start_ ();
3710
3711   ffeste_emit_line_note_ ();
3712
3713   /* First determine the start, per-item, and end run-time functions to
3714      call.  The per-item function is picked by choosing an ffeste function
3715      to call to handle a given item; it knows how to generate a call to the
3716      appropriate run-time function, and is called an "I/O driver".  */
3717
3718   switch (format)
3719     {
3720     case FFESTV_formatNONE:     /* no FMT= */
3721       ffeste_io_driver_ = ffeste_io_douio_;
3722       if (rec)
3723         start = FFECOM_gfrtSWDUE, end = FFECOM_gfrtEWDUE;
3724       else
3725         start = FFECOM_gfrtSWSUE, end = FFECOM_gfrtEWSUE;
3726       break;
3727
3728     case FFESTV_formatLABEL:    /* FMT=10 */
3729     case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
3730     case FFESTV_formatINTEXPR:  /* FMT=I [after ASSIGN 10 TO I] */
3731       ffeste_io_driver_ = ffeste_io_dofio_;
3732       if (rec)
3733         start = FFECOM_gfrtSWDFE, end = FFECOM_gfrtEWDFE;
3734       else if (unit == FFESTV_unitCHAREXPR)
3735         start = FFECOM_gfrtSWSFI, end = FFECOM_gfrtEWSFI;
3736       else
3737         start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
3738       break;
3739
3740     case FFESTV_formatASTERISK: /* FMT=* */
3741       ffeste_io_driver_ = ffeste_io_dolio_;
3742       if (unit == FFESTV_unitCHAREXPR)
3743         start = FFECOM_gfrtSWSLI, end = FFECOM_gfrtEWSLI;
3744       else
3745         start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
3746       break;
3747
3748     case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
3749                                    /FOO/] */
3750       ffeste_io_driver_ = NULL; /* No start or driver function. */
3751       start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
3752       break;
3753
3754     default:
3755       assert ("Weird stuff" == NULL);
3756       start = FFECOM_gfrt, end = FFECOM_gfrt;
3757       break;
3758     }
3759   ffeste_io_endgfrt_ = end;
3760
3761 #define specified(something) (info->write_spec[something].kw_or_val_present)
3762
3763   iostat = specified (FFESTP_writeixIOSTAT);
3764   errl = specified (FFESTP_writeixERR);
3765
3766 #undef specified
3767
3768   ffeste_start_stmt_ ();
3769
3770   ffeste_io_end_ = NULL_TREE;
3771
3772   if (errl)
3773     {
3774       /* Have ERR= specification.   */
3775
3776       ffeste_io_err_
3777         = ffeste_io_abort_
3778         = ffecom_lookup_label
3779         (info->write_spec[FFESTP_writeixERR].u.label);
3780       ffeste_io_abort_is_temp_ = FALSE;
3781     }
3782   else
3783     {
3784       /* No ERR= specification.  */
3785
3786       ffeste_io_err_ = NULL_TREE;
3787
3788       if ((ffeste_io_abort_is_temp_ = iostat))
3789         ffeste_io_abort_ = ffecom_temp_label ();
3790       else
3791         ffeste_io_abort_ = NULL_TREE;
3792     }
3793
3794   if (iostat)
3795     {
3796       /* Have IOSTAT= specification.  */
3797
3798       ffeste_io_iostat_is_temp_ = FALSE;
3799       ffeste_io_iostat_ = ffecom_expr
3800         (info->write_spec[FFESTP_writeixIOSTAT].u.expr);
3801     }
3802   else if (ffeste_io_abort_ != NULL_TREE)
3803     {
3804       /* Have no IOSTAT= but have ERR=.  */
3805
3806       ffeste_io_iostat_is_temp_ = TRUE;
3807       ffeste_io_iostat_
3808         = ffecom_make_tempvar ("write", ffecom_integer_type_node,
3809                                FFETARGET_charactersizeNONE, -1);
3810     }
3811   else
3812     {
3813       /* No IOSTAT= or ERR= specification.  */
3814
3815       ffeste_io_iostat_is_temp_ = FALSE;
3816       ffeste_io_iostat_ = NULL_TREE;
3817     }
3818
3819   /* Now prescan, then convert, all the arguments.  */
3820
3821   if (unit == FFESTV_unitCHAREXPR)
3822     cilist = ffeste_io_icilist_ (errl || iostat,
3823                                  info->write_spec[FFESTP_writeixUNIT].u.expr,
3824                                  FALSE, format,
3825                                  &info->write_spec[FFESTP_writeixFORMAT]);
3826   else
3827     cilist = ffeste_io_cilist_ (errl || iostat, unit,
3828                                 info->write_spec[FFESTP_writeixUNIT].u.expr,
3829                                 6, FALSE, format,
3830                                 &info->write_spec[FFESTP_writeixFORMAT],
3831                                 rec,
3832                                 info->write_spec[FFESTP_writeixREC].u.expr);
3833
3834   /* If there is no end function, then there are no item functions (i.e.
3835      it's a NAMELIST), and vice versa by the way.  In this situation, don't
3836      generate the "if (iostat != 0) goto label;" if the label is temp abort
3837      label, since we're gonna fall through to there anyway.  */
3838
3839   ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
3840                    (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
3841 }
3842
3843 /* WRITE statement -- I/O item.  */
3844
3845 void
3846 ffeste_R910_item (ffebld expr, ffelexToken expr_token)
3847 {
3848   ffeste_check_item_ ();
3849
3850   if (expr == NULL)
3851     return;
3852
3853   if (ffebld_op (expr) == FFEBLD_opANY)
3854     return;
3855
3856   if (ffebld_op (expr) == FFEBLD_opIMPDO)
3857     ffeste_io_impdo_ (expr, expr_token);
3858   else
3859     {
3860       ffeste_start_stmt_ ();
3861
3862       ffecom_prepare_arg_ptr_to_expr (expr);
3863
3864       ffecom_prepare_end ();
3865
3866       ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
3867
3868       ffeste_end_stmt_ ();
3869     }
3870 }
3871
3872 /* WRITE statement -- end.  */
3873
3874 void
3875 ffeste_R910_finish ()
3876 {
3877   ffeste_check_finish_ ();
3878
3879   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
3880      label, since we're gonna fall through to there anyway. */
3881
3882   if (ffeste_io_endgfrt_ != FFECOM_gfrt)
3883     ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
3884                                        NULL_TREE),
3885                      ! ffeste_io_abort_is_temp_);
3886
3887   /* If we've got a temp label, generate its code here. */
3888
3889   if (ffeste_io_abort_is_temp_)
3890     {
3891       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
3892       emit_nop ();
3893       expand_label (ffeste_io_abort_);
3894
3895       assert (ffeste_io_err_ == NULL_TREE);
3896     }
3897
3898   ffeste_end_stmt_ ();
3899 }
3900
3901 /* PRINT statement -- start.  */
3902
3903 void
3904 ffeste_R911_start (ffestpPrintStmt *info, ffestvFormat format)
3905 {
3906   ffecomGfrt start;
3907   ffecomGfrt end;
3908   tree cilist;
3909
3910   ffeste_check_start_ ();
3911
3912   ffeste_emit_line_note_ ();
3913
3914   /* First determine the start, per-item, and end run-time functions to
3915      call.  The per-item function is picked by choosing an ffeste function
3916      to call to handle a given item; it knows how to generate a call to the
3917      appropriate run-time function, and is called an "I/O driver".  */
3918
3919   switch (format)
3920     {
3921     case FFESTV_formatLABEL:    /* FMT=10 */
3922     case FFESTV_formatCHAREXPR: /* FMT='(I10)' */
3923     case FFESTV_formatINTEXPR:  /* FMT=I [after ASSIGN 10 TO I] */
3924       ffeste_io_driver_ = ffeste_io_dofio_;
3925       start = FFECOM_gfrtSWSFE, end = FFECOM_gfrtEWSFE;
3926       break;
3927
3928     case FFESTV_formatASTERISK: /* FMT=* */
3929       ffeste_io_driver_ = ffeste_io_dolio_;
3930       start = FFECOM_gfrtSWSLE, end = FFECOM_gfrtEWSLE;
3931       break;
3932
3933     case FFESTV_formatNAMELIST: /* FMT=FOO or NML=FOO [NAMELIST
3934                                    /FOO/] */
3935       ffeste_io_driver_ = NULL; /* No start or driver function. */
3936       start = FFECOM_gfrtSWSNE, end = FFECOM_gfrt;
3937       break;
3938
3939     default:
3940       assert ("Weird stuff" == NULL);
3941       start = FFECOM_gfrt, end = FFECOM_gfrt;
3942       break;
3943     }
3944   ffeste_io_endgfrt_ = end;
3945
3946   ffeste_start_stmt_ ();
3947
3948   ffeste_io_end_ = NULL_TREE;
3949   ffeste_io_err_ = NULL_TREE;
3950   ffeste_io_abort_ = NULL_TREE;
3951   ffeste_io_abort_is_temp_ = FALSE;
3952   ffeste_io_iostat_is_temp_ = FALSE;
3953   ffeste_io_iostat_ = NULL_TREE;
3954
3955   /* Now prescan, then convert, all the arguments.  */
3956
3957   cilist = ffeste_io_cilist_ (FALSE, FFESTV_unitNONE, NULL, 6, FALSE, format,
3958                               &info->print_spec[FFESTP_printixFORMAT],
3959                               FALSE, NULL);
3960
3961   /* If there is no end function, then there are no item functions (i.e.
3962      it's a NAMELIST), and vice versa by the way.  In this situation, don't
3963      generate the "if (iostat != 0) goto label;" if the label is temp abort
3964      label, since we're gonna fall through to there anyway.  */
3965
3966   ffeste_io_call_ (ffecom_call_gfrt (start, cilist, NULL_TREE),
3967                    (! ffeste_io_abort_is_temp_) || (end != FFECOM_gfrt));
3968 }
3969
3970 /* PRINT statement -- I/O item.  */
3971
3972 void
3973 ffeste_R911_item (ffebld expr, ffelexToken expr_token)
3974 {
3975   ffeste_check_item_ ();
3976
3977   if (expr == NULL)
3978     return;
3979
3980   if (ffebld_op (expr) == FFEBLD_opANY)
3981     return;
3982
3983   if (ffebld_op (expr) == FFEBLD_opIMPDO)
3984     ffeste_io_impdo_ (expr, expr_token);
3985   else
3986     {
3987       ffeste_start_stmt_ ();
3988
3989       ffecom_prepare_arg_ptr_to_expr (expr);
3990
3991       ffecom_prepare_end ();
3992
3993       ffeste_io_call_ ((*ffeste_io_driver_) (expr), TRUE);
3994
3995       ffeste_end_stmt_ ();
3996     }
3997 }
3998
3999 /* PRINT statement -- end.  */
4000
4001 void
4002 ffeste_R911_finish ()
4003 {
4004   ffeste_check_finish_ ();
4005
4006   if (ffeste_io_endgfrt_ != FFECOM_gfrt)
4007     ffeste_io_call_ (ffecom_call_gfrt (ffeste_io_endgfrt_, NULL_TREE,
4008                                        NULL_TREE),
4009                      FALSE);
4010
4011   ffeste_end_stmt_ ();
4012 }
4013
4014 /* BACKSPACE statement.  */
4015
4016 void
4017 ffeste_R919 (ffestpBeruStmt *info)
4018 {
4019   ffeste_check_simple_ ();
4020
4021   ffeste_subr_beru_ (info, FFECOM_gfrtFBACK);
4022 }
4023
4024 /* ENDFILE statement.  */
4025
4026 void
4027 ffeste_R920 (ffestpBeruStmt *info)
4028 {
4029   ffeste_check_simple_ ();
4030
4031   ffeste_subr_beru_ (info, FFECOM_gfrtFEND);
4032 }
4033
4034 /* REWIND statement.  */
4035
4036 void
4037 ffeste_R921 (ffestpBeruStmt *info)
4038 {
4039   ffeste_check_simple_ ();
4040
4041   ffeste_subr_beru_ (info, FFECOM_gfrtFREW);
4042 }
4043
4044 /* INQUIRE statement (non-IOLENGTH version).  */
4045
4046 void
4047 ffeste_R923A (ffestpInquireStmt *info, bool by_file UNUSED)
4048 {
4049   tree args;
4050   bool iostat;
4051   bool errl;
4052
4053   ffeste_check_simple_ ();
4054
4055   ffeste_emit_line_note_ ();
4056
4057 #define specified(something) (info->inquire_spec[something].kw_or_val_present)
4058
4059   iostat = specified (FFESTP_inquireixIOSTAT);
4060   errl = specified (FFESTP_inquireixERR);
4061
4062 #undef specified
4063
4064   ffeste_start_stmt_ ();
4065
4066   if (errl)
4067     {
4068       ffeste_io_err_
4069         = ffeste_io_abort_
4070         = ffecom_lookup_label
4071         (info->inquire_spec[FFESTP_inquireixERR].u.label);
4072       ffeste_io_abort_is_temp_ = FALSE;
4073     }
4074   else
4075     {
4076       ffeste_io_err_ = NULL_TREE;
4077
4078       if ((ffeste_io_abort_is_temp_ = iostat))
4079         ffeste_io_abort_ = ffecom_temp_label ();
4080       else
4081         ffeste_io_abort_ = NULL_TREE;
4082     }
4083
4084   if (iostat)
4085     {
4086       /* Have IOSTAT= specification.  */
4087
4088       ffeste_io_iostat_is_temp_ = FALSE;
4089       ffeste_io_iostat_ = ffecom_expr
4090         (info->inquire_spec[FFESTP_inquireixIOSTAT].u.expr);
4091     }
4092   else if (ffeste_io_abort_ != NULL_TREE)
4093     {
4094       /* Have no IOSTAT= but have ERR=.  */
4095
4096       ffeste_io_iostat_is_temp_ = TRUE;
4097       ffeste_io_iostat_
4098         = ffecom_make_tempvar ("inquire", ffecom_integer_type_node,
4099                                FFETARGET_charactersizeNONE, -1);
4100     }
4101   else
4102     {
4103       /* No IOSTAT= or ERR= specification.  */
4104
4105       ffeste_io_iostat_is_temp_ = FALSE;
4106       ffeste_io_iostat_ = NULL_TREE;
4107     }
4108
4109   /* Now prescan, then convert, all the arguments.  */
4110
4111   args
4112     = ffeste_io_inlist_ (errl || iostat,
4113                          &info->inquire_spec[FFESTP_inquireixUNIT],
4114                          &info->inquire_spec[FFESTP_inquireixFILE],
4115                          &info->inquire_spec[FFESTP_inquireixEXIST],
4116                          &info->inquire_spec[FFESTP_inquireixOPENED],
4117                          &info->inquire_spec[FFESTP_inquireixNUMBER],
4118                          &info->inquire_spec[FFESTP_inquireixNAMED],
4119                          &info->inquire_spec[FFESTP_inquireixNAME],
4120                          &info->inquire_spec[FFESTP_inquireixACCESS],
4121                          &info->inquire_spec[FFESTP_inquireixSEQUENTIAL],
4122                          &info->inquire_spec[FFESTP_inquireixDIRECT],
4123                          &info->inquire_spec[FFESTP_inquireixFORM],
4124                          &info->inquire_spec[FFESTP_inquireixFORMATTED],
4125                          &info->inquire_spec[FFESTP_inquireixUNFORMATTED],
4126                          &info->inquire_spec[FFESTP_inquireixRECL],
4127                          &info->inquire_spec[FFESTP_inquireixNEXTREC],
4128                          &info->inquire_spec[FFESTP_inquireixBLANK]);
4129
4130   /* Don't generate "if (iostat != 0) goto label;" if label is temp abort
4131      label, since we're gonna fall through to there anyway. */
4132
4133   ffeste_io_call_ (ffecom_call_gfrt (FFECOM_gfrtFINQU, args, NULL_TREE),
4134                    ! ffeste_io_abort_is_temp_);
4135
4136   /* If we've got a temp label, generate its code here.  */
4137
4138   if (ffeste_io_abort_is_temp_)
4139     {
4140       DECL_INITIAL (ffeste_io_abort_) = error_mark_node;
4141       emit_nop ();
4142       expand_label (ffeste_io_abort_);
4143
4144       assert (ffeste_io_err_ == NULL_TREE);
4145     }
4146
4147   ffeste_end_stmt_ ();
4148 }
4149
4150 /* INQUIRE(IOLENGTH=expr) statement -- start.  */
4151
4152 void
4153 ffeste_R923B_start (ffestpInquireStmt *info UNUSED)
4154 {
4155   ffeste_check_start_ ();
4156
4157   assert ("INQUIRE(IOLENGTH=<var>) not implemented yet! ~~~" == NULL);
4158
4159   ffeste_emit_line_note_ ();
4160 }
4161
4162 /* INQUIRE(IOLENGTH=expr) statement -- I/O item.  */
4163
4164 void
4165 ffeste_R923B_item (ffebld expr UNUSED)
4166 {
4167   ffeste_check_item_ ();
4168 }
4169
4170 /* INQUIRE(IOLENGTH=expr) statement -- end.  */
4171
4172 void
4173 ffeste_R923B_finish ()
4174 {
4175   ffeste_check_finish_ ();
4176 }
4177
4178 /* ffeste_R1001 -- FORMAT statement
4179
4180    ffeste_R1001(format_list);  */
4181
4182 void
4183 ffeste_R1001 (ffests s)
4184 {
4185   tree t;
4186   tree ttype;
4187   tree maxindex;
4188   tree var;
4189
4190   ffeste_check_simple_ ();
4191
4192   assert (ffeste_label_formatdef_ != NULL);
4193
4194   ffeste_emit_line_note_ ();
4195
4196   t = build_string (ffests_length (s), ffests_text (s));
4197
4198   TREE_TYPE (t)
4199     = build_type_variant (build_array_type
4200                           (char_type_node,
4201                            build_range_type (integer_type_node,
4202                                              integer_one_node,
4203                                              build_int_2 (ffests_length (s),
4204                                                           0))),
4205                           1, 0);
4206   TREE_CONSTANT (t) = 1;
4207   TREE_STATIC (t) = 1;
4208
4209   var = ffecom_lookup_label (ffeste_label_formatdef_);
4210   if ((var != NULL_TREE)
4211       && (TREE_CODE (var) == VAR_DECL))
4212     {
4213       DECL_INITIAL (var) = t;
4214       maxindex = build_int_2 (ffests_length (s) - 1, 0);
4215       ttype = TREE_TYPE (var);
4216       TYPE_DOMAIN (ttype) = build_range_type (integer_type_node,
4217                                               integer_zero_node,
4218                                               maxindex);
4219       if (!TREE_TYPE (maxindex))
4220         TREE_TYPE (maxindex) = TYPE_DOMAIN (ttype);
4221       layout_type (ttype);
4222       rest_of_decl_compilation (var, NULL, 1, 0);
4223       expand_decl (var);
4224       expand_decl_init (var);
4225     }
4226
4227   ffeste_label_formatdef_ = NULL;
4228 }
4229
4230 /* END PROGRAM.  */
4231
4232 void
4233 ffeste_R1103 ()
4234 {
4235 }
4236
4237 /* END BLOCK DATA.  */
4238
4239 void
4240 ffeste_R1112 ()
4241 {
4242 }
4243
4244 /* CALL statement.  */
4245
4246 void
4247 ffeste_R1212 (ffebld expr)
4248 {
4249   ffebld args;
4250   ffebld arg;
4251   ffebld labels = NULL; /* First in list of LABTERs. */
4252   ffebld prevlabels = NULL;
4253   ffebld prevargs = NULL;
4254
4255   ffeste_check_simple_ ();
4256
4257   args = ffebld_right (expr);
4258
4259   ffeste_emit_line_note_ ();
4260
4261   /* Here we split the list at ffebld_right(expr) into two lists: one at
4262      ffebld_right(expr) consisting of all items that are not LABTERs, the
4263      other at labels consisting of all items that are LABTERs.  Then, if
4264      the latter list is NULL, we have an ordinary call, else we have a call
4265      with alternate returns. */
4266
4267   for (args = ffebld_right (expr); args != NULL; args = ffebld_trail (args))
4268     {
4269       if (((arg = ffebld_head (args)) == NULL)
4270           || (ffebld_op (arg) != FFEBLD_opLABTER))
4271         {
4272           if (prevargs == NULL)
4273             {
4274               prevargs = args;
4275               ffebld_set_right (expr, args);
4276             }
4277           else
4278             {
4279               ffebld_set_trail (prevargs, args);
4280               prevargs = args;
4281             }
4282         }
4283       else
4284         {
4285           if (prevlabels == NULL)
4286             {
4287               prevlabels = labels = args;
4288             }
4289           else
4290             {
4291               ffebld_set_trail (prevlabels, args);
4292               prevlabels = args;
4293             }
4294         }
4295     }
4296   if (prevlabels == NULL)
4297     labels = NULL;
4298   else
4299     ffebld_set_trail (prevlabels, NULL);
4300   if (prevargs == NULL)
4301     ffebld_set_right (expr, NULL);
4302   else
4303     ffebld_set_trail (prevargs, NULL);
4304
4305   ffeste_start_stmt_ ();
4306
4307   /* No temporaries are actually needed at this level, but we go
4308      through the motions anyway, just to be sure in case they do
4309      get made.  Temporaries needed for arguments should be in the
4310      scopes of inner blocks, and if clean-up actions are supported,
4311      such as CALL-ing an intrinsic that writes to an argument of one
4312      type when a variable of a different type is provided (requiring
4313      assignment to the variable from a temporary after the library
4314      routine returns), the clean-up must be done by the expression
4315      evaluator, generally, to handle alternate returns (which we hope
4316      won't ever be supported by intrinsics, but might be a similar
4317      issue, such as CALL-ing an F90-style subroutine with an INTERFACE
4318      block).  That implies the expression evaluator will have to
4319      recognize the need for its own temporary anyway, meaning it'll
4320      construct a block within the one constructed here.  */
4321
4322   ffecom_prepare_expr (expr);
4323
4324   ffecom_prepare_end ();
4325
4326   if (labels == NULL)
4327     expand_expr_stmt (ffecom_expr (expr));
4328   else
4329     {
4330       tree texpr;
4331       tree value;
4332       tree tlabel;
4333       int caseno;
4334       int pushok;
4335       tree duplicate;
4336       ffebld label;
4337
4338       texpr = ffecom_expr (expr);
4339       expand_start_case (0, texpr, TREE_TYPE (texpr), "CALL statement");
4340
4341       for (caseno = 1, label = labels;
4342            label != NULL;
4343            ++caseno, label = ffebld_trail (label))
4344         {
4345           value = build_int_2 (caseno, 0);
4346           tlabel = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
4347
4348           pushok = pushcase (value, convert, tlabel, &duplicate);
4349           assert (pushok == 0);
4350
4351           tlabel
4352             = ffecom_lookup_label (ffebld_labter (ffebld_head (label)));
4353           if ((tlabel == NULL_TREE)
4354               || (TREE_CODE (tlabel) == ERROR_MARK))
4355             continue;
4356           TREE_USED (tlabel) = 1;
4357           expand_goto (tlabel);
4358         }
4359
4360       expand_end_case (texpr);
4361     }
4362
4363   ffeste_end_stmt_ ();
4364 }
4365
4366 /* END FUNCTION.  */
4367
4368 void
4369 ffeste_R1221 ()
4370 {
4371 }
4372
4373 /* END SUBROUTINE.  */
4374
4375 void
4376 ffeste_R1225 ()
4377 {
4378 }
4379
4380 /* ENTRY statement.  */
4381
4382 void
4383 ffeste_R1226 (ffesymbol entry)
4384 {
4385   tree label;
4386
4387   ffeste_check_simple_ ();
4388
4389   label = ffesymbol_hook (entry).length_tree;
4390
4391   ffeste_emit_line_note_ ();
4392
4393   if (label == error_mark_node)
4394     return;
4395
4396   DECL_INITIAL (label) = error_mark_node;
4397   emit_nop ();
4398   expand_label (label);
4399 }
4400
4401 /* RETURN statement.  */
4402
4403 void
4404 ffeste_R1227 (ffestw block UNUSED, ffebld expr)
4405 {
4406   tree rtn;
4407
4408   ffeste_check_simple_ ();
4409
4410   ffeste_emit_line_note_ ();
4411
4412   ffeste_start_stmt_ ();
4413
4414   ffecom_prepare_return_expr (expr);
4415
4416   ffecom_prepare_end ();
4417
4418   rtn = ffecom_return_expr (expr);
4419
4420   if ((rtn == NULL_TREE)
4421       || (rtn == error_mark_node))
4422     expand_null_return ();
4423   else
4424     {
4425       tree result = DECL_RESULT (current_function_decl);
4426
4427       if ((result != error_mark_node)
4428           && (TREE_TYPE (result) != error_mark_node))
4429         expand_return (ffecom_modify (NULL_TREE,
4430                                       result,
4431                                       convert (TREE_TYPE (result),
4432                                                rtn)));
4433       else
4434         expand_null_return ();
4435     }
4436
4437   ffeste_end_stmt_ ();
4438 }
4439
4440 /* REWRITE statement -- start.  */
4441
4442 #if FFESTR_VXT
4443 void
4444 ffeste_V018_start (ffestpRewriteStmt *info, ffestvFormat format)
4445 {
4446   ffeste_check_start_ ();
4447 }
4448
4449 /* REWRITE statement -- I/O item.  */
4450
4451 void
4452 ffeste_V018_item (ffebld expr)
4453 {
4454   ffeste_check_item_ ();
4455 }
4456
4457 /* REWRITE statement -- end.  */
4458
4459 void
4460 ffeste_V018_finish ()
4461 {
4462   ffeste_check_finish_ ();
4463 }
4464
4465 /* ACCEPT statement -- start.  */
4466
4467 void
4468 ffeste_V019_start (ffestpAcceptStmt *info, ffestvFormat format)
4469 {
4470   ffeste_check_start_ ();
4471 }
4472
4473 /* ACCEPT statement -- I/O item.  */
4474
4475 void
4476 ffeste_V019_item (ffebld expr)
4477 {
4478   ffeste_check_item_ ();
4479 }
4480
4481 /* ACCEPT statement -- end.  */
4482
4483 void
4484 ffeste_V019_finish ()
4485 {
4486   ffeste_check_finish_ ();
4487 }
4488
4489 #endif
4490 /* TYPE statement -- start.  */
4491
4492 void
4493 ffeste_V020_start (ffestpTypeStmt *info UNUSED,
4494                    ffestvFormat format UNUSED)
4495 {
4496   ffeste_check_start_ ();
4497 }
4498
4499 /* TYPE statement -- I/O item.  */
4500
4501 void
4502 ffeste_V020_item (ffebld expr UNUSED)
4503 {
4504   ffeste_check_item_ ();
4505 }
4506
4507 /* TYPE statement -- end.  */
4508
4509 void
4510 ffeste_V020_finish ()
4511 {
4512   ffeste_check_finish_ ();
4513 }
4514
4515 /* DELETE statement.  */
4516
4517 #if FFESTR_VXT
4518 void
4519 ffeste_V021 (ffestpDeleteStmt *info)
4520 {
4521   ffeste_check_simple_ ();
4522 }
4523
4524 /* UNLOCK statement.  */
4525
4526 void
4527 ffeste_V022 (ffestpBeruStmt *info)
4528 {
4529   ffeste_check_simple_ ();
4530 }
4531
4532 /* ENCODE statement -- start.  */
4533
4534 void
4535 ffeste_V023_start (ffestpVxtcodeStmt *info)
4536 {
4537   ffeste_check_start_ ();
4538 }
4539
4540 /* ENCODE statement -- I/O item.  */
4541
4542 void
4543 ffeste_V023_item (ffebld expr)
4544 {
4545   ffeste_check_item_ ();
4546 }
4547
4548 /* ENCODE statement -- end.  */
4549
4550 void
4551 ffeste_V023_finish ()
4552 {
4553   ffeste_check_finish_ ();
4554 }
4555
4556 /* DECODE statement -- start.  */
4557
4558 void
4559 ffeste_V024_start (ffestpVxtcodeStmt *info)
4560 {
4561   ffeste_check_start_ ();
4562 }
4563
4564 /* DECODE statement -- I/O item.  */
4565
4566 void
4567 ffeste_V024_item (ffebld expr)
4568 {
4569   ffeste_check_item_ ();
4570 }
4571
4572 /* DECODE statement -- end.  */
4573
4574 void
4575 ffeste_V024_finish ()
4576 {
4577   ffeste_check_finish_ ();
4578 }
4579
4580 /* DEFINEFILE statement -- start.  */
4581
4582 void
4583 ffeste_V025_start ()
4584 {
4585   ffeste_check_start_ ();
4586 }
4587
4588 /* DEFINE FILE statement -- item.  */
4589
4590 void
4591 ffeste_V025_item (ffebld u, ffebld m, ffebld n, ffebld asv)
4592 {
4593   ffeste_check_item_ ();
4594 }
4595
4596 /* DEFINE FILE statement -- end.  */
4597
4598 void
4599 ffeste_V025_finish ()
4600 {
4601   ffeste_check_finish_ ();
4602 }
4603
4604 /* FIND statement.  */
4605
4606 void
4607 ffeste_V026 (ffestpFindStmt *info)
4608 {
4609   ffeste_check_simple_ ();
4610 }
4611
4612 #endif
4613
4614 #ifdef ENABLE_CHECKING
4615 void
4616 ffeste_terminate_2 (void)
4617 {
4618   assert (! ffeste_top_block_);
4619 }
4620 #endif