Home | History | Annotate | Line # | Download | only in io
      1  1.1.1.4  mrg /* Copyright (C) 2002-2024 Free Software Foundation, Inc.
      2      1.1  mrg    Contributed by Andy Vaught
      3      1.1  mrg    F2003 I/O support contributed by Jerry DeLisle
      4      1.1  mrg 
      5      1.1  mrg This file is part of the GNU Fortran runtime library (libgfortran).
      6      1.1  mrg 
      7      1.1  mrg Libgfortran is free software; you can redistribute it and/or modify
      8      1.1  mrg it under the terms of the GNU General Public License as published by
      9      1.1  mrg the Free Software Foundation; either version 3, or (at your option)
     10      1.1  mrg any later version.
     11      1.1  mrg 
     12      1.1  mrg Libgfortran is distributed in the hope that it will be useful,
     13      1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15      1.1  mrg GNU General Public License for more details.
     16      1.1  mrg 
     17      1.1  mrg Under Section 7 of GPL version 3, you are granted additional
     18      1.1  mrg permissions described in the GCC Runtime Library Exception, version
     19      1.1  mrg 3.1, as published by the Free Software Foundation.
     20      1.1  mrg 
     21      1.1  mrg You should have received a copy of the GNU General Public License and
     22      1.1  mrg a copy of the GCC Runtime Library Exception along with this program;
     23      1.1  mrg see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24      1.1  mrg <http://www.gnu.org/licenses/>.  */
     25      1.1  mrg 
     26      1.1  mrg #include "io.h"
     27      1.1  mrg #include "fbuf.h"
     28      1.1  mrg #include "unix.h"
     29      1.1  mrg #include "async.h"
     30      1.1  mrg 
     31      1.1  mrg #ifdef HAVE_UNISTD_H
     32      1.1  mrg #include <unistd.h>
     33      1.1  mrg #endif
     34      1.1  mrg 
     35      1.1  mrg #include <string.h>
     36      1.1  mrg #include <errno.h>
     37      1.1  mrg 
     38      1.1  mrg 
     39      1.1  mrg static const st_option access_opt[] = {
     40      1.1  mrg   {"sequential", ACCESS_SEQUENTIAL},
     41      1.1  mrg   {"direct", ACCESS_DIRECT},
     42      1.1  mrg   {"append", ACCESS_APPEND},
     43      1.1  mrg   {"stream", ACCESS_STREAM},
     44      1.1  mrg   {NULL, 0}
     45      1.1  mrg };
     46      1.1  mrg 
     47      1.1  mrg static const st_option action_opt[] =
     48      1.1  mrg {
     49      1.1  mrg   { "read", ACTION_READ},
     50      1.1  mrg   { "write", ACTION_WRITE},
     51      1.1  mrg   { "readwrite", ACTION_READWRITE},
     52      1.1  mrg   { NULL, 0}
     53      1.1  mrg };
     54      1.1  mrg 
     55      1.1  mrg static const st_option share_opt[] =
     56      1.1  mrg {
     57      1.1  mrg   { "denyrw", SHARE_DENYRW },
     58      1.1  mrg   { "denynone", SHARE_DENYNONE },
     59      1.1  mrg   { NULL, 0}
     60      1.1  mrg };
     61      1.1  mrg 
     62      1.1  mrg static const st_option cc_opt[] =
     63      1.1  mrg {
     64      1.1  mrg   { "list", CC_LIST },
     65      1.1  mrg   { "fortran", CC_FORTRAN },
     66      1.1  mrg   { "none", CC_NONE },
     67      1.1  mrg   { NULL, 0}
     68      1.1  mrg };
     69      1.1  mrg 
     70      1.1  mrg static const st_option blank_opt[] =
     71      1.1  mrg {
     72      1.1  mrg   { "null", BLANK_NULL},
     73      1.1  mrg   { "zero", BLANK_ZERO},
     74      1.1  mrg   { NULL, 0}
     75      1.1  mrg };
     76      1.1  mrg 
     77      1.1  mrg static const st_option delim_opt[] =
     78      1.1  mrg {
     79      1.1  mrg   { "none", DELIM_NONE},
     80      1.1  mrg   { "apostrophe", DELIM_APOSTROPHE},
     81      1.1  mrg   { "quote", DELIM_QUOTE},
     82      1.1  mrg   { NULL, 0}
     83      1.1  mrg };
     84      1.1  mrg 
     85      1.1  mrg static const st_option form_opt[] =
     86      1.1  mrg {
     87      1.1  mrg   { "formatted", FORM_FORMATTED},
     88      1.1  mrg   { "unformatted", FORM_UNFORMATTED},
     89      1.1  mrg   { NULL, 0}
     90      1.1  mrg };
     91      1.1  mrg 
     92      1.1  mrg static const st_option position_opt[] =
     93      1.1  mrg {
     94      1.1  mrg   { "asis", POSITION_ASIS},
     95      1.1  mrg   { "rewind", POSITION_REWIND},
     96      1.1  mrg   { "append", POSITION_APPEND},
     97      1.1  mrg   { NULL, 0}
     98      1.1  mrg };
     99      1.1  mrg 
    100      1.1  mrg static const st_option status_opt[] =
    101      1.1  mrg {
    102      1.1  mrg   { "unknown", STATUS_UNKNOWN},
    103      1.1  mrg   { "old", STATUS_OLD},
    104      1.1  mrg   { "new", STATUS_NEW},
    105      1.1  mrg   { "replace", STATUS_REPLACE},
    106      1.1  mrg   { "scratch", STATUS_SCRATCH},
    107      1.1  mrg   { NULL, 0}
    108      1.1  mrg };
    109      1.1  mrg 
    110      1.1  mrg static const st_option pad_opt[] =
    111      1.1  mrg {
    112      1.1  mrg   { "yes", PAD_YES},
    113      1.1  mrg   { "no", PAD_NO},
    114      1.1  mrg   { NULL, 0}
    115      1.1  mrg };
    116      1.1  mrg 
    117      1.1  mrg static const st_option decimal_opt[] =
    118      1.1  mrg {
    119      1.1  mrg   { "point", DECIMAL_POINT},
    120      1.1  mrg   { "comma", DECIMAL_COMMA},
    121      1.1  mrg   { NULL, 0}
    122      1.1  mrg };
    123      1.1  mrg 
    124      1.1  mrg static const st_option encoding_opt[] =
    125      1.1  mrg {
    126      1.1  mrg   { "utf-8", ENCODING_UTF8},
    127      1.1  mrg   { "default", ENCODING_DEFAULT},
    128      1.1  mrg   { NULL, 0}
    129      1.1  mrg };
    130      1.1  mrg 
    131      1.1  mrg static const st_option round_opt[] =
    132      1.1  mrg {
    133      1.1  mrg   { "up", ROUND_UP},
    134      1.1  mrg   { "down", ROUND_DOWN},
    135      1.1  mrg   { "zero", ROUND_ZERO},
    136      1.1  mrg   { "nearest", ROUND_NEAREST},
    137      1.1  mrg   { "compatible", ROUND_COMPATIBLE},
    138      1.1  mrg   { "processor_defined", ROUND_PROCDEFINED},
    139      1.1  mrg   { NULL, 0}
    140      1.1  mrg };
    141      1.1  mrg 
    142      1.1  mrg static const st_option sign_opt[] =
    143      1.1  mrg {
    144      1.1  mrg   { "plus", SIGN_PLUS},
    145      1.1  mrg   { "suppress", SIGN_SUPPRESS},
    146      1.1  mrg   { "processor_defined", SIGN_PROCDEFINED},
    147      1.1  mrg   { NULL, 0}
    148      1.1  mrg };
    149      1.1  mrg 
    150      1.1  mrg static const st_option convert_opt[] =
    151      1.1  mrg {
    152      1.1  mrg   { "native", GFC_CONVERT_NATIVE},
    153      1.1  mrg   { "swap", GFC_CONVERT_SWAP},
    154      1.1  mrg   { "big_endian", GFC_CONVERT_BIG},
    155      1.1  mrg   { "little_endian", GFC_CONVERT_LITTLE},
    156  1.1.1.3  mrg #ifdef HAVE_GFC_REAL_17
    157  1.1.1.3  mrg   /* Rather than write a special parsing routine, enumerate all the
    158  1.1.1.3  mrg      possibilities here.  */
    159  1.1.1.3  mrg   { "r16_ieee", GFC_CONVERT_R16_IEEE},
    160  1.1.1.3  mrg   { "r16_ibm", GFC_CONVERT_R16_IBM},
    161  1.1.1.3  mrg   { "native,r16_ieee", GFC_CONVERT_R16_IEEE},
    162  1.1.1.3  mrg   { "native,r16_ibm", GFC_CONVERT_R16_IBM},
    163  1.1.1.3  mrg   { "r16_ieee,native", GFC_CONVERT_R16_IEEE},
    164  1.1.1.3  mrg   { "r16_ibm,native", GFC_CONVERT_R16_IBM},
    165  1.1.1.3  mrg   { "swap,r16_ieee", GFC_CONVERT_R16_IEEE_SWAP},
    166  1.1.1.3  mrg   { "swap,r16_ibm", GFC_CONVERT_R16_IBM_SWAP},
    167  1.1.1.3  mrg   { "r16_ieee,swap", GFC_CONVERT_R16_IEEE_SWAP},
    168  1.1.1.3  mrg   { "r16_ibm,swap", GFC_CONVERT_R16_IBM_SWAP},
    169  1.1.1.3  mrg   { "big_endian,r16_ieee", GFC_CONVERT_R16_IEEE_BIG},
    170  1.1.1.3  mrg   { "big_endian,r16_ibm", GFC_CONVERT_R16_IBM_BIG},
    171  1.1.1.3  mrg   { "r16_ieee,big_endian", GFC_CONVERT_R16_IEEE_BIG},
    172  1.1.1.3  mrg   { "r16_ibm,big_endian", GFC_CONVERT_R16_IBM_BIG},
    173  1.1.1.3  mrg   { "little_endian,r16_ieee", GFC_CONVERT_R16_IEEE_LITTLE},
    174  1.1.1.3  mrg   { "little_endian,r16_ibm", GFC_CONVERT_R16_IBM_LITTLE},
    175  1.1.1.3  mrg   { "r16_ieee,little_endian", GFC_CONVERT_R16_IEEE_LITTLE},
    176  1.1.1.3  mrg   { "r16_ibm,little_endian",  GFC_CONVERT_R16_IBM_LITTLE},
    177  1.1.1.3  mrg #endif
    178      1.1  mrg   { NULL, 0}
    179      1.1  mrg };
    180      1.1  mrg 
    181      1.1  mrg static const st_option async_opt[] =
    182      1.1  mrg {
    183      1.1  mrg   { "yes", ASYNC_YES},
    184      1.1  mrg   { "no", ASYNC_NO},
    185      1.1  mrg   { NULL, 0}
    186      1.1  mrg };
    187      1.1  mrg 
    188      1.1  mrg /* Given a unit, test to see if the file is positioned at the terminal
    189      1.1  mrg    point, and if so, change state from NO_ENDFILE flag to AT_ENDFILE.
    190      1.1  mrg    This prevents us from changing the state from AFTER_ENDFILE to
    191      1.1  mrg    AT_ENDFILE.  */
    192      1.1  mrg 
    193      1.1  mrg static void
    194      1.1  mrg test_endfile (gfc_unit *u)
    195      1.1  mrg {
    196      1.1  mrg   if (u->endfile == NO_ENDFILE)
    197      1.1  mrg     {
    198      1.1  mrg       gfc_offset sz = ssize (u->s);
    199      1.1  mrg       if (sz == 0 || sz == stell (u->s))
    200      1.1  mrg 	u->endfile = AT_ENDFILE;
    201      1.1  mrg     }
    202      1.1  mrg }
    203      1.1  mrg 
    204      1.1  mrg 
    205      1.1  mrg /* Change the modes of a file, those that are allowed * to be
    206      1.1  mrg    changed.  */
    207      1.1  mrg 
    208      1.1  mrg static void
    209      1.1  mrg edit_modes (st_parameter_open *opp, gfc_unit *u, unit_flags *flags)
    210      1.1  mrg {
    211      1.1  mrg   /* Complain about attempts to change the unchangeable.  */
    212      1.1  mrg 
    213      1.1  mrg   if (flags->status != STATUS_UNSPECIFIED && flags->status != STATUS_OLD &&
    214      1.1  mrg       u->flags.status != flags->status)
    215      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    216      1.1  mrg 		    "Cannot change STATUS parameter in OPEN statement");
    217      1.1  mrg 
    218      1.1  mrg   if (flags->access != ACCESS_UNSPECIFIED && u->flags.access != flags->access)
    219      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    220      1.1  mrg 		    "Cannot change ACCESS parameter in OPEN statement");
    221      1.1  mrg 
    222      1.1  mrg   if (flags->form != FORM_UNSPECIFIED && u->flags.form != flags->form)
    223      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    224      1.1  mrg 		    "Cannot change FORM parameter in OPEN statement");
    225      1.1  mrg 
    226      1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN)
    227      1.1  mrg       && opp->recl_in != u->recl)
    228      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    229      1.1  mrg 		    "Cannot change RECL parameter in OPEN statement");
    230      1.1  mrg 
    231      1.1  mrg   if (flags->action != ACTION_UNSPECIFIED && u->flags.action != flags->action)
    232      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    233      1.1  mrg 		    "Cannot change ACTION parameter in OPEN statement");
    234      1.1  mrg 
    235      1.1  mrg   if (flags->share != SHARE_UNSPECIFIED && u->flags.share != flags->share)
    236      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    237      1.1  mrg 		    "Cannot change SHARE parameter in OPEN statement");
    238      1.1  mrg 
    239      1.1  mrg   if (flags->cc != CC_UNSPECIFIED && u->flags.cc != flags->cc)
    240      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    241      1.1  mrg 		  "Cannot change CARRIAGECONTROL parameter in OPEN statement");
    242      1.1  mrg 
    243      1.1  mrg   /* Status must be OLD if present.  */
    244      1.1  mrg 
    245      1.1  mrg   if (flags->status != STATUS_UNSPECIFIED && flags->status != STATUS_OLD &&
    246      1.1  mrg       flags->status != STATUS_UNKNOWN)
    247      1.1  mrg     {
    248      1.1  mrg       if (flags->status == STATUS_SCRATCH)
    249      1.1  mrg 	notify_std (&opp->common, GFC_STD_GNU,
    250      1.1  mrg 		    "OPEN statement must have a STATUS of OLD or UNKNOWN");
    251      1.1  mrg       else
    252      1.1  mrg 	generate_error (&opp->common, LIBERROR_BAD_OPTION,
    253      1.1  mrg 		    "OPEN statement must have a STATUS of OLD or UNKNOWN");
    254      1.1  mrg     }
    255      1.1  mrg 
    256      1.1  mrg   if (u->flags.form == FORM_UNFORMATTED)
    257      1.1  mrg     {
    258      1.1  mrg       if (flags->delim != DELIM_UNSPECIFIED)
    259      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    260      1.1  mrg 			"DELIM parameter conflicts with UNFORMATTED form in "
    261      1.1  mrg 			"OPEN statement");
    262      1.1  mrg 
    263      1.1  mrg       if (flags->blank != BLANK_UNSPECIFIED)
    264      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    265      1.1  mrg 			"BLANK parameter conflicts with UNFORMATTED form in "
    266      1.1  mrg 			"OPEN statement");
    267      1.1  mrg 
    268      1.1  mrg       if (flags->pad != PAD_UNSPECIFIED)
    269      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    270      1.1  mrg 			"PAD parameter conflicts with UNFORMATTED form in "
    271      1.1  mrg 			"OPEN statement");
    272      1.1  mrg 
    273      1.1  mrg       if (flags->decimal != DECIMAL_UNSPECIFIED)
    274      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    275      1.1  mrg 			"DECIMAL parameter conflicts with UNFORMATTED form in "
    276      1.1  mrg 			"OPEN statement");
    277      1.1  mrg 
    278      1.1  mrg       if (flags->encoding != ENCODING_UNSPECIFIED)
    279      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    280      1.1  mrg 			"ENCODING parameter conflicts with UNFORMATTED form in "
    281      1.1  mrg 			"OPEN statement");
    282      1.1  mrg 
    283      1.1  mrg       if (flags->round != ROUND_UNSPECIFIED)
    284      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    285      1.1  mrg 			"ROUND parameter conflicts with UNFORMATTED form in "
    286      1.1  mrg 			"OPEN statement");
    287      1.1  mrg 
    288      1.1  mrg       if (flags->sign != SIGN_UNSPECIFIED)
    289      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    290      1.1  mrg 			"SIGN parameter conflicts with UNFORMATTED form in "
    291      1.1  mrg 			"OPEN statement");
    292      1.1  mrg     }
    293      1.1  mrg 
    294      1.1  mrg   if ((opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
    295      1.1  mrg     {
    296      1.1  mrg       /* Change the changeable:  */
    297      1.1  mrg       if (flags->blank != BLANK_UNSPECIFIED)
    298      1.1  mrg 	u->flags.blank = flags->blank;
    299      1.1  mrg       if (flags->delim != DELIM_UNSPECIFIED)
    300      1.1  mrg 	u->flags.delim = flags->delim;
    301      1.1  mrg       if (flags->pad != PAD_UNSPECIFIED)
    302      1.1  mrg 	u->flags.pad = flags->pad;
    303      1.1  mrg       if (flags->decimal != DECIMAL_UNSPECIFIED)
    304      1.1  mrg 	u->flags.decimal = flags->decimal;
    305      1.1  mrg       if (flags->encoding != ENCODING_UNSPECIFIED)
    306      1.1  mrg 	u->flags.encoding = flags->encoding;
    307      1.1  mrg       if (flags->async != ASYNC_UNSPECIFIED)
    308      1.1  mrg 	u->flags.async = flags->async;
    309      1.1  mrg       if (flags->round != ROUND_UNSPECIFIED)
    310      1.1  mrg 	u->flags.round = flags->round;
    311      1.1  mrg       if (flags->sign != SIGN_UNSPECIFIED)
    312      1.1  mrg 	u->flags.sign = flags->sign;
    313      1.1  mrg 
    314      1.1  mrg       /* Reposition the file if necessary.  */
    315      1.1  mrg 
    316      1.1  mrg       switch (flags->position)
    317      1.1  mrg 	{
    318      1.1  mrg 	case POSITION_UNSPECIFIED:
    319      1.1  mrg 	case POSITION_ASIS:
    320      1.1  mrg 	  break;
    321      1.1  mrg 
    322      1.1  mrg 	case POSITION_REWIND:
    323      1.1  mrg 	  if (sseek (u->s, 0, SEEK_SET) != 0)
    324      1.1  mrg 	    goto seek_error;
    325      1.1  mrg 
    326      1.1  mrg 	  u->current_record = 0;
    327      1.1  mrg 	  u->last_record = 0;
    328      1.1  mrg 
    329      1.1  mrg 	  test_endfile (u);
    330      1.1  mrg 	  break;
    331      1.1  mrg 
    332      1.1  mrg 	case POSITION_APPEND:
    333      1.1  mrg 	  if (sseek (u->s, 0, SEEK_END) < 0)
    334      1.1  mrg 	    goto seek_error;
    335      1.1  mrg 
    336      1.1  mrg 	  if (flags->access != ACCESS_STREAM)
    337      1.1  mrg 	    u->current_record = 0;
    338      1.1  mrg 
    339      1.1  mrg 	  u->endfile = AT_ENDFILE;	/* We are at the end.  */
    340      1.1  mrg 	  break;
    341      1.1  mrg 
    342      1.1  mrg 	seek_error:
    343      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OS, NULL);
    344      1.1  mrg 	  break;
    345      1.1  mrg 	}
    346      1.1  mrg     }
    347      1.1  mrg 
    348      1.1  mrg   unlock_unit (u);
    349      1.1  mrg }
    350      1.1  mrg 
    351      1.1  mrg 
    352      1.1  mrg /* Open an unused unit.  */
    353      1.1  mrg 
    354      1.1  mrg gfc_unit *
    355      1.1  mrg new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags *flags)
    356      1.1  mrg {
    357      1.1  mrg   gfc_unit *u2;
    358      1.1  mrg   stream *s;
    359      1.1  mrg   char tmpname[5 /* fort. */ + 10 /* digits of unit number */ + 1 /* 0 */];
    360      1.1  mrg 
    361      1.1  mrg   /* Change unspecifieds to defaults.  Leave (flags->action ==
    362      1.1  mrg      ACTION_UNSPECIFIED) alone so open_external() can set it based on
    363      1.1  mrg      what type of open actually works.  */
    364      1.1  mrg 
    365      1.1  mrg   if (flags->access == ACCESS_UNSPECIFIED)
    366      1.1  mrg     flags->access = ACCESS_SEQUENTIAL;
    367      1.1  mrg 
    368      1.1  mrg   if (flags->form == FORM_UNSPECIFIED)
    369      1.1  mrg     flags->form = (flags->access == ACCESS_SEQUENTIAL)
    370      1.1  mrg       ? FORM_FORMATTED : FORM_UNFORMATTED;
    371      1.1  mrg 
    372      1.1  mrg   if (flags->async == ASYNC_UNSPECIFIED)
    373      1.1  mrg     flags->async = ASYNC_NO;
    374      1.1  mrg 
    375      1.1  mrg   if (flags->status == STATUS_UNSPECIFIED)
    376      1.1  mrg     flags->status = STATUS_UNKNOWN;
    377      1.1  mrg 
    378      1.1  mrg   if (flags->cc == CC_UNSPECIFIED)
    379      1.1  mrg     flags->cc = flags->form == FORM_UNFORMATTED ? CC_NONE : CC_LIST;
    380      1.1  mrg   else if (flags->form == FORM_UNFORMATTED && flags->cc != CC_NONE)
    381      1.1  mrg     {
    382      1.1  mrg       generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    383      1.1  mrg 	  "CARRIAGECONTROL parameter conflicts with UNFORMATTED form in "
    384      1.1  mrg 	  "OPEN statement");
    385      1.1  mrg       goto fail;
    386      1.1  mrg     }
    387      1.1  mrg 
    388      1.1  mrg   /* Checks.  */
    389      1.1  mrg 
    390      1.1  mrg   if (flags->delim != DELIM_UNSPECIFIED
    391      1.1  mrg       && flags->form == FORM_UNFORMATTED)
    392      1.1  mrg     {
    393      1.1  mrg       generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    394      1.1  mrg 		      "DELIM parameter conflicts with UNFORMATTED form in "
    395      1.1  mrg 		      "OPEN statement");
    396      1.1  mrg       goto fail;
    397      1.1  mrg     }
    398      1.1  mrg 
    399      1.1  mrg   if (flags->blank == BLANK_UNSPECIFIED)
    400      1.1  mrg     flags->blank = BLANK_NULL;
    401      1.1  mrg   else
    402      1.1  mrg     {
    403      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    404      1.1  mrg 	{
    405      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    406      1.1  mrg 			  "BLANK parameter conflicts with UNFORMATTED form in "
    407      1.1  mrg 			  "OPEN statement");
    408      1.1  mrg 	  goto fail;
    409      1.1  mrg 	}
    410      1.1  mrg     }
    411      1.1  mrg 
    412      1.1  mrg   if (flags->pad == PAD_UNSPECIFIED)
    413      1.1  mrg     flags->pad = PAD_YES;
    414      1.1  mrg   else
    415      1.1  mrg     {
    416      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    417      1.1  mrg 	{
    418      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    419      1.1  mrg 			  "PAD parameter conflicts with UNFORMATTED form in "
    420      1.1  mrg 			  "OPEN statement");
    421      1.1  mrg 	  goto fail;
    422      1.1  mrg 	}
    423      1.1  mrg     }
    424      1.1  mrg 
    425      1.1  mrg   if (flags->decimal == DECIMAL_UNSPECIFIED)
    426      1.1  mrg     flags->decimal = DECIMAL_POINT;
    427      1.1  mrg   else
    428      1.1  mrg     {
    429      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    430      1.1  mrg 	{
    431      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    432      1.1  mrg 			  "DECIMAL parameter conflicts with UNFORMATTED form "
    433      1.1  mrg 			  "in OPEN statement");
    434      1.1  mrg 	  goto fail;
    435      1.1  mrg 	}
    436      1.1  mrg     }
    437      1.1  mrg 
    438      1.1  mrg   if (flags->encoding == ENCODING_UNSPECIFIED)
    439      1.1  mrg     flags->encoding = ENCODING_DEFAULT;
    440      1.1  mrg   else
    441      1.1  mrg     {
    442      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    443      1.1  mrg 	{
    444      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    445      1.1  mrg 			  "ENCODING parameter conflicts with UNFORMATTED form in "
    446      1.1  mrg 			  "OPEN statement");
    447      1.1  mrg 	  goto fail;
    448      1.1  mrg 	}
    449      1.1  mrg     }
    450      1.1  mrg 
    451      1.1  mrg   /* NB: the value for ROUND when it's not specified by the user does not
    452      1.1  mrg          have to be PROCESSOR_DEFINED; the standard says that it is
    453      1.1  mrg 	 processor dependent, and requires that it is one of the
    454      1.1  mrg 	 possible value (see F2003, 9.4.5.13).  */
    455      1.1  mrg   if (flags->round == ROUND_UNSPECIFIED)
    456      1.1  mrg     flags->round = ROUND_PROCDEFINED;
    457      1.1  mrg   else
    458      1.1  mrg     {
    459      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    460      1.1  mrg 	{
    461      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    462      1.1  mrg 			  "ROUND parameter conflicts with UNFORMATTED form in "
    463      1.1  mrg 			  "OPEN statement");
    464      1.1  mrg 	  goto fail;
    465      1.1  mrg 	}
    466      1.1  mrg     }
    467      1.1  mrg 
    468      1.1  mrg   if (flags->sign == SIGN_UNSPECIFIED)
    469      1.1  mrg     flags->sign = SIGN_PROCDEFINED;
    470      1.1  mrg   else
    471      1.1  mrg     {
    472      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    473      1.1  mrg 	{
    474      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    475      1.1  mrg 			  "SIGN parameter conflicts with UNFORMATTED form in "
    476      1.1  mrg 			  "OPEN statement");
    477      1.1  mrg 	  goto fail;
    478      1.1  mrg 	}
    479      1.1  mrg     }
    480      1.1  mrg 
    481      1.1  mrg   if (flags->position != POSITION_ASIS && flags->access == ACCESS_DIRECT)
    482      1.1  mrg    {
    483      1.1  mrg      generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    484      1.1  mrg                      "ACCESS parameter conflicts with SEQUENTIAL access in "
    485      1.1  mrg                      "OPEN statement");
    486      1.1  mrg      goto fail;
    487      1.1  mrg    }
    488      1.1  mrg   else
    489      1.1  mrg    if (flags->position == POSITION_UNSPECIFIED)
    490      1.1  mrg      flags->position = POSITION_ASIS;
    491      1.1  mrg 
    492      1.1  mrg   if (flags->access == ACCESS_DIRECT
    493      1.1  mrg       && (opp->common.flags & IOPARM_OPEN_HAS_RECL_IN) == 0)
    494      1.1  mrg     {
    495      1.1  mrg       generate_error (&opp->common, LIBERROR_MISSING_OPTION,
    496      1.1  mrg 		      "Missing RECL parameter in OPEN statement");
    497      1.1  mrg       goto fail;
    498      1.1  mrg     }
    499      1.1  mrg 
    500      1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN) && opp->recl_in <= 0)
    501      1.1  mrg     {
    502      1.1  mrg       generate_error (&opp->common, LIBERROR_BAD_OPTION,
    503      1.1  mrg 		      "RECL parameter is non-positive in OPEN statement");
    504      1.1  mrg       goto fail;
    505      1.1  mrg     }
    506      1.1  mrg 
    507      1.1  mrg   switch (flags->status)
    508      1.1  mrg     {
    509      1.1  mrg     case STATUS_SCRATCH:
    510      1.1  mrg       if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) == 0)
    511      1.1  mrg 	{
    512      1.1  mrg 	  opp->file = NULL;
    513      1.1  mrg 	  break;
    514      1.1  mrg 	}
    515      1.1  mrg 
    516      1.1  mrg       generate_error (&opp->common, LIBERROR_BAD_OPTION,
    517      1.1  mrg 		      "FILE parameter must not be present in OPEN statement");
    518      1.1  mrg       goto fail;
    519      1.1  mrg 
    520      1.1  mrg     case STATUS_OLD:
    521      1.1  mrg     case STATUS_NEW:
    522      1.1  mrg     case STATUS_REPLACE:
    523      1.1  mrg     case STATUS_UNKNOWN:
    524      1.1  mrg       if ((opp->common.flags & IOPARM_OPEN_HAS_FILE))
    525      1.1  mrg 	break;
    526      1.1  mrg 
    527      1.1  mrg       opp->file = tmpname;
    528      1.1  mrg       opp->file_len = snprintf(opp->file, sizeof (tmpname), "fort.%d",
    529      1.1  mrg 			       (int) opp->common.unit);
    530      1.1  mrg       break;
    531      1.1  mrg 
    532      1.1  mrg     default:
    533      1.1  mrg       internal_error (&opp->common, "new_unit(): Bad status");
    534      1.1  mrg     }
    535      1.1  mrg 
    536      1.1  mrg   /* Make sure the file isn't already open someplace else.
    537      1.1  mrg      Do not error if opening file preconnected to stdin, stdout, stderr.  */
    538      1.1  mrg 
    539      1.1  mrg   u2 = NULL;
    540  1.1.1.2  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) != 0
    541  1.1.1.2  mrg       && !(compile_options.allow_std & GFC_STD_F2018))
    542      1.1  mrg     u2 = find_file (opp->file, opp->file_len);
    543      1.1  mrg   if (u2 != NULL
    544      1.1  mrg       && (options.stdin_unit < 0 || u2->unit_number != options.stdin_unit)
    545      1.1  mrg       && (options.stdout_unit < 0 || u2->unit_number != options.stdout_unit)
    546      1.1  mrg       && (options.stderr_unit < 0 || u2->unit_number != options.stderr_unit))
    547      1.1  mrg     {
    548      1.1  mrg       unlock_unit (u2);
    549      1.1  mrg       generate_error (&opp->common, LIBERROR_ALREADY_OPEN, NULL);
    550      1.1  mrg       goto cleanup;
    551      1.1  mrg     }
    552      1.1  mrg 
    553      1.1  mrg   if (u2 != NULL)
    554      1.1  mrg     unlock_unit (u2);
    555      1.1  mrg 
    556      1.1  mrg   /* If the unit specified is preconnected with a file specified to be open,
    557      1.1  mrg      then clear the format buffer.  */
    558      1.1  mrg   if ((opp->common.unit == options.stdin_unit ||
    559      1.1  mrg        opp->common.unit == options.stdout_unit ||
    560      1.1  mrg        opp->common.unit == options.stderr_unit)
    561      1.1  mrg       && (opp->common.flags & IOPARM_OPEN_HAS_FILE) != 0)
    562      1.1  mrg     fbuf_destroy (u);
    563      1.1  mrg 
    564      1.1  mrg   /* Open file.  */
    565      1.1  mrg 
    566      1.1  mrg   s = open_external (opp, flags);
    567      1.1  mrg   if (s == NULL)
    568      1.1  mrg     {
    569      1.1  mrg       char errbuf[256];
    570      1.1  mrg       char *path = fc_strdup (opp->file, opp->file_len);
    571      1.1  mrg       size_t msglen = opp->file_len + 22 + sizeof (errbuf);
    572      1.1  mrg       char *msg = xmalloc (msglen);
    573      1.1  mrg       snprintf (msg, msglen, "Cannot open file '%s': %s", path,
    574      1.1  mrg 		gf_strerror (errno, errbuf, sizeof (errbuf)));
    575      1.1  mrg       generate_error (&opp->common, LIBERROR_OS, msg);
    576      1.1  mrg       free (msg);
    577      1.1  mrg       free (path);
    578      1.1  mrg       goto cleanup;
    579      1.1  mrg     }
    580      1.1  mrg 
    581      1.1  mrg   if (flags->status == STATUS_NEW || flags->status == STATUS_REPLACE)
    582      1.1  mrg     flags->status = STATUS_OLD;
    583      1.1  mrg 
    584      1.1  mrg   /* Create the unit structure.  */
    585      1.1  mrg 
    586      1.1  mrg   if (u->unit_number != opp->common.unit)
    587      1.1  mrg     internal_error (&opp->common, "Unit number changed");
    588      1.1  mrg   u->s = s;
    589      1.1  mrg   u->flags = *flags;
    590      1.1  mrg   u->read_bad = 0;
    591      1.1  mrg   u->endfile = NO_ENDFILE;
    592      1.1  mrg   u->last_record = 0;
    593      1.1  mrg   u->current_record = 0;
    594      1.1  mrg   u->mode = READING;
    595      1.1  mrg   u->maxrec = 0;
    596      1.1  mrg   u->bytes_left = 0;
    597      1.1  mrg   u->saved_pos = 0;
    598      1.1  mrg 
    599      1.1  mrg   if (flags->position == POSITION_APPEND)
    600      1.1  mrg     {
    601      1.1  mrg       if (sseek (u->s, 0, SEEK_END) < 0)
    602      1.1  mrg 	{
    603      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OS, NULL);
    604      1.1  mrg 	  goto cleanup;
    605      1.1  mrg 	}
    606      1.1  mrg       u->endfile = AT_ENDFILE;
    607      1.1  mrg     }
    608      1.1  mrg 
    609      1.1  mrg   /* Unspecified recl ends up with a processor dependent value.  */
    610      1.1  mrg 
    611      1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN))
    612      1.1  mrg     {
    613      1.1  mrg       u->flags.has_recl = 1;
    614      1.1  mrg       u->recl = opp->recl_in;
    615      1.1  mrg       u->recl_subrecord = u->recl;
    616      1.1  mrg       u->bytes_left = u->recl;
    617      1.1  mrg     }
    618      1.1  mrg   else
    619      1.1  mrg     {
    620      1.1  mrg       u->flags.has_recl = 0;
    621      1.1  mrg       u->recl = default_recl;
    622      1.1  mrg       if (compile_options.max_subrecord_length)
    623      1.1  mrg 	{
    624      1.1  mrg 	  u->recl_subrecord = compile_options.max_subrecord_length;
    625      1.1  mrg 	}
    626      1.1  mrg       else
    627      1.1  mrg 	{
    628      1.1  mrg 	  switch (compile_options.record_marker)
    629      1.1  mrg 	    {
    630      1.1  mrg 	    case 0:
    631      1.1  mrg 	      /* Fall through */
    632      1.1  mrg 	    case sizeof (GFC_INTEGER_4):
    633      1.1  mrg 	      u->recl_subrecord = GFC_MAX_SUBRECORD_LENGTH;
    634      1.1  mrg 	      break;
    635      1.1  mrg 
    636      1.1  mrg 	    case sizeof (GFC_INTEGER_8):
    637      1.1  mrg 	      u->recl_subrecord = max_offset - 16;
    638      1.1  mrg 	      break;
    639      1.1  mrg 
    640      1.1  mrg 	    default:
    641      1.1  mrg 	      runtime_error ("Illegal value for record marker");
    642      1.1  mrg 	      break;
    643      1.1  mrg 	    }
    644      1.1  mrg 	}
    645      1.1  mrg     }
    646      1.1  mrg 
    647      1.1  mrg   /* If the file is direct access, calculate the maximum record number
    648      1.1  mrg      via a division now instead of letting the multiplication overflow
    649      1.1  mrg      later.  */
    650      1.1  mrg 
    651      1.1  mrg   if (flags->access == ACCESS_DIRECT)
    652      1.1  mrg     u->maxrec = max_offset / u->recl;
    653      1.1  mrg 
    654      1.1  mrg   if (flags->access == ACCESS_STREAM)
    655      1.1  mrg     {
    656      1.1  mrg       u->maxrec = max_offset;
    657      1.1  mrg       /* F2018 (N2137) 12.10.2.26: If the connection is for stream
    658      1.1  mrg 	 access recl is assigned the value -2.  */
    659      1.1  mrg       u->recl = -2;
    660      1.1  mrg       u->bytes_left = 1;
    661      1.1  mrg       u->strm_pos = stell (u->s) + 1;
    662      1.1  mrg     }
    663      1.1  mrg 
    664      1.1  mrg   u->filename = fc_strdup (opp->file, opp->file_len);
    665      1.1  mrg 
    666      1.1  mrg   /* Curiously, the standard requires that the
    667      1.1  mrg      position specifier be ignored for new files so a newly connected
    668      1.1  mrg      file starts out at the initial point.  We still need to figure
    669      1.1  mrg      out if the file is at the end or not.  */
    670      1.1  mrg 
    671      1.1  mrg   test_endfile (u);
    672      1.1  mrg 
    673      1.1  mrg   if (flags->status == STATUS_SCRATCH && opp->file != NULL)
    674      1.1  mrg     free (opp->file);
    675      1.1  mrg 
    676      1.1  mrg   if (flags->form == FORM_FORMATTED)
    677      1.1  mrg     {
    678      1.1  mrg       if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN))
    679      1.1  mrg         fbuf_init (u, u->recl);
    680      1.1  mrg       else
    681      1.1  mrg         fbuf_init (u, 0);
    682      1.1  mrg     }
    683      1.1  mrg   else
    684      1.1  mrg     u->fbuf = NULL;
    685      1.1  mrg 
    686      1.1  mrg   /* Check if asynchrounous.  */
    687      1.1  mrg   if (flags->async == ASYNC_YES)
    688      1.1  mrg     init_async_unit (u);
    689      1.1  mrg   else
    690      1.1  mrg     u->au = NULL;
    691      1.1  mrg 
    692      1.1  mrg   return u;
    693      1.1  mrg 
    694      1.1  mrg  cleanup:
    695      1.1  mrg 
    696      1.1  mrg   /* Free memory associated with a temporary filename.  */
    697      1.1  mrg 
    698      1.1  mrg   if (flags->status == STATUS_SCRATCH && opp->file != NULL)
    699      1.1  mrg     free (opp->file);
    700      1.1  mrg 
    701      1.1  mrg  fail:
    702      1.1  mrg 
    703      1.1  mrg   close_unit (u);
    704      1.1  mrg   return NULL;
    705      1.1  mrg }
    706      1.1  mrg 
    707      1.1  mrg 
    708      1.1  mrg /* Open a unit which is already open.  This involves changing the
    709      1.1  mrg    modes or closing what is there now and opening the new file.  */
    710      1.1  mrg 
    711      1.1  mrg static void
    712      1.1  mrg already_open (st_parameter_open *opp, gfc_unit *u, unit_flags *flags)
    713      1.1  mrg {
    714      1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) == 0)
    715      1.1  mrg     {
    716      1.1  mrg       edit_modes (opp, u, flags);
    717      1.1  mrg       return;
    718      1.1  mrg     }
    719      1.1  mrg 
    720      1.1  mrg   /* If the file is connected to something else, close it and open a
    721      1.1  mrg      new unit.  */
    722      1.1  mrg 
    723      1.1  mrg   if (!compare_file_filename (u, opp->file, opp->file_len))
    724      1.1  mrg     {
    725      1.1  mrg       if (sclose (u->s) == -1)
    726      1.1  mrg 	{
    727      1.1  mrg 	  unlock_unit (u);
    728      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OS,
    729      1.1  mrg 			  "Error closing file in OPEN statement");
    730      1.1  mrg 	  return;
    731      1.1  mrg 	}
    732      1.1  mrg 
    733      1.1  mrg       u->s = NULL;
    734      1.1  mrg 
    735      1.1  mrg #if !HAVE_UNLINK_OPEN_FILE
    736      1.1  mrg       if (u->filename && u->flags.status == STATUS_SCRATCH)
    737      1.1  mrg 	remove (u->filename);
    738      1.1  mrg #endif
    739      1.1  mrg       free (u->filename);
    740      1.1  mrg       u->filename = NULL;
    741      1.1  mrg 
    742      1.1  mrg       u = new_unit (opp, u, flags);
    743      1.1  mrg       if (u != NULL)
    744      1.1  mrg       unlock_unit (u);
    745      1.1  mrg       return;
    746      1.1  mrg     }
    747      1.1  mrg 
    748      1.1  mrg   edit_modes (opp, u, flags);
    749      1.1  mrg }
    750      1.1  mrg 
    751      1.1  mrg 
    752      1.1  mrg /* Open file.  */
    753      1.1  mrg 
    754      1.1  mrg extern void st_open (st_parameter_open *opp);
    755      1.1  mrg export_proto(st_open);
    756      1.1  mrg 
    757      1.1  mrg void
    758      1.1  mrg st_open (st_parameter_open *opp)
    759      1.1  mrg {
    760      1.1  mrg   unit_flags flags;
    761      1.1  mrg   gfc_unit *u = NULL;
    762      1.1  mrg   GFC_INTEGER_4 cf = opp->common.flags;
    763      1.1  mrg   unit_convert conv;
    764      1.1  mrg 
    765      1.1  mrg   library_start (&opp->common);
    766      1.1  mrg 
    767      1.1  mrg   /* Decode options.  */
    768      1.1  mrg   flags.readonly = !(cf & IOPARM_OPEN_HAS_READONLY) ? 0 : opp->readonly;
    769      1.1  mrg 
    770      1.1  mrg   flags.access = !(cf & IOPARM_OPEN_HAS_ACCESS) ? ACCESS_UNSPECIFIED :
    771      1.1  mrg     find_option (&opp->common, opp->access, opp->access_len,
    772      1.1  mrg 		 access_opt, "Bad ACCESS parameter in OPEN statement");
    773      1.1  mrg 
    774      1.1  mrg   flags.action = !(cf & IOPARM_OPEN_HAS_ACTION) ? ACTION_UNSPECIFIED :
    775      1.1  mrg     find_option (&opp->common, opp->action, opp->action_len,
    776      1.1  mrg 		 action_opt, "Bad ACTION parameter in OPEN statement");
    777      1.1  mrg 
    778      1.1  mrg   flags.cc = !(cf & IOPARM_OPEN_HAS_CC) ? CC_UNSPECIFIED :
    779      1.1  mrg     find_option (&opp->common, opp->cc, opp->cc_len,
    780      1.1  mrg 		 cc_opt, "Bad CARRIAGECONTROL parameter in OPEN statement");
    781      1.1  mrg 
    782      1.1  mrg   flags.share = !(cf & IOPARM_OPEN_HAS_SHARE) ? SHARE_UNSPECIFIED :
    783      1.1  mrg     find_option (&opp->common, opp->share, opp->share_len,
    784      1.1  mrg 		 share_opt, "Bad SHARE parameter in OPEN statement");
    785      1.1  mrg 
    786      1.1  mrg   flags.blank = !(cf & IOPARM_OPEN_HAS_BLANK) ? BLANK_UNSPECIFIED :
    787      1.1  mrg     find_option (&opp->common, opp->blank, opp->blank_len,
    788      1.1  mrg 		 blank_opt, "Bad BLANK parameter in OPEN statement");
    789      1.1  mrg 
    790      1.1  mrg   flags.delim = !(cf & IOPARM_OPEN_HAS_DELIM) ? DELIM_UNSPECIFIED :
    791      1.1  mrg     find_option (&opp->common, opp->delim, opp->delim_len,
    792      1.1  mrg 		 delim_opt, "Bad DELIM parameter in OPEN statement");
    793      1.1  mrg 
    794      1.1  mrg   flags.pad = !(cf & IOPARM_OPEN_HAS_PAD) ? PAD_UNSPECIFIED :
    795      1.1  mrg     find_option (&opp->common, opp->pad, opp->pad_len,
    796      1.1  mrg 		 pad_opt, "Bad PAD parameter in OPEN statement");
    797      1.1  mrg 
    798      1.1  mrg   flags.decimal = !(cf & IOPARM_OPEN_HAS_DECIMAL) ? DECIMAL_UNSPECIFIED :
    799      1.1  mrg     find_option (&opp->common, opp->decimal, opp->decimal_len,
    800      1.1  mrg 		 decimal_opt, "Bad DECIMAL parameter in OPEN statement");
    801      1.1  mrg 
    802      1.1  mrg   flags.encoding = !(cf & IOPARM_OPEN_HAS_ENCODING) ? ENCODING_UNSPECIFIED :
    803      1.1  mrg     find_option (&opp->common, opp->encoding, opp->encoding_len,
    804      1.1  mrg 		 encoding_opt, "Bad ENCODING parameter in OPEN statement");
    805      1.1  mrg 
    806      1.1  mrg   flags.async = !(cf & IOPARM_OPEN_HAS_ASYNCHRONOUS) ? ASYNC_UNSPECIFIED :
    807      1.1  mrg     find_option (&opp->common, opp->asynchronous, opp->asynchronous_len,
    808      1.1  mrg 		 async_opt, "Bad ASYNCHRONOUS parameter in OPEN statement");
    809      1.1  mrg 
    810      1.1  mrg   flags.round = !(cf & IOPARM_OPEN_HAS_ROUND) ? ROUND_UNSPECIFIED :
    811      1.1  mrg     find_option (&opp->common, opp->round, opp->round_len,
    812      1.1  mrg 		 round_opt, "Bad ROUND parameter in OPEN statement");
    813      1.1  mrg 
    814      1.1  mrg   flags.sign = !(cf & IOPARM_OPEN_HAS_SIGN) ? SIGN_UNSPECIFIED :
    815      1.1  mrg     find_option (&opp->common, opp->sign, opp->sign_len,
    816      1.1  mrg 		 sign_opt, "Bad SIGN parameter in OPEN statement");
    817      1.1  mrg 
    818      1.1  mrg   flags.form = !(cf & IOPARM_OPEN_HAS_FORM) ? FORM_UNSPECIFIED :
    819      1.1  mrg     find_option (&opp->common, opp->form, opp->form_len,
    820      1.1  mrg 		 form_opt, "Bad FORM parameter in OPEN statement");
    821      1.1  mrg 
    822      1.1  mrg   flags.position = !(cf & IOPARM_OPEN_HAS_POSITION) ? POSITION_UNSPECIFIED :
    823      1.1  mrg     find_option (&opp->common, opp->position, opp->position_len,
    824      1.1  mrg 		 position_opt, "Bad POSITION parameter in OPEN statement");
    825      1.1  mrg 
    826      1.1  mrg   flags.status = !(cf & IOPARM_OPEN_HAS_STATUS) ? STATUS_UNSPECIFIED :
    827      1.1  mrg     find_option (&opp->common, opp->status, opp->status_len,
    828      1.1  mrg 		 status_opt, "Bad STATUS parameter in OPEN statement");
    829      1.1  mrg 
    830      1.1  mrg   /* First, we check wether the convert flag has been set via environment
    831      1.1  mrg      variable.  This overrides the convert tag in the open statement.  */
    832      1.1  mrg 
    833      1.1  mrg   conv = get_unformatted_convert (opp->common.unit);
    834      1.1  mrg 
    835      1.1  mrg   if (conv == GFC_CONVERT_NONE)
    836      1.1  mrg     {
    837      1.1  mrg       /* Nothing has been set by environment variable, check the convert tag.  */
    838      1.1  mrg       if (cf & IOPARM_OPEN_HAS_CONVERT)
    839      1.1  mrg 	conv = find_option (&opp->common, opp->convert, opp->convert_len,
    840      1.1  mrg 			    convert_opt,
    841      1.1  mrg 			    "Bad CONVERT parameter in OPEN statement");
    842      1.1  mrg       else
    843      1.1  mrg 	conv = compile_options.convert;
    844      1.1  mrg     }
    845  1.1.1.3  mrg 
    846  1.1.1.3  mrg   flags.convert = 0;
    847  1.1.1.3  mrg 
    848  1.1.1.3  mrg #ifdef HAVE_GFC_REAL_17
    849  1.1.1.3  mrg   flags.convert = conv & (GFC_CONVERT_R16_IEEE | GFC_CONVERT_R16_IBM);
    850  1.1.1.3  mrg   conv &= ~(GFC_CONVERT_R16_IEEE | GFC_CONVERT_R16_IBM);
    851  1.1.1.3  mrg #endif
    852  1.1.1.3  mrg 
    853      1.1  mrg   switch (conv)
    854      1.1  mrg     {
    855      1.1  mrg     case GFC_CONVERT_NATIVE:
    856      1.1  mrg     case GFC_CONVERT_SWAP:
    857      1.1  mrg       break;
    858      1.1  mrg 
    859      1.1  mrg     case GFC_CONVERT_BIG:
    860      1.1  mrg       conv = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? GFC_CONVERT_NATIVE : GFC_CONVERT_SWAP;
    861      1.1  mrg       break;
    862      1.1  mrg 
    863      1.1  mrg     case GFC_CONVERT_LITTLE:
    864      1.1  mrg       conv = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? GFC_CONVERT_SWAP : GFC_CONVERT_NATIVE;
    865      1.1  mrg       break;
    866      1.1  mrg 
    867      1.1  mrg     default:
    868      1.1  mrg       internal_error (&opp->common, "Illegal value for CONVERT");
    869      1.1  mrg       break;
    870      1.1  mrg     }
    871      1.1  mrg 
    872  1.1.1.3  mrg   flags.convert |= conv;
    873      1.1  mrg 
    874      1.1  mrg   if (flags.position != POSITION_UNSPECIFIED
    875      1.1  mrg       && flags.access == ACCESS_DIRECT)
    876      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    877      1.1  mrg 		    "Cannot use POSITION with direct access files");
    878      1.1  mrg 
    879      1.1  mrg   if (flags.readonly
    880      1.1  mrg       && flags.action != ACTION_UNSPECIFIED && flags.action != ACTION_READ)
    881      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    882      1.1  mrg 		    "ACTION conflicts with READONLY in OPEN statement");
    883      1.1  mrg 
    884      1.1  mrg   if (flags.access == ACCESS_APPEND)
    885      1.1  mrg     {
    886      1.1  mrg       if (flags.position != POSITION_UNSPECIFIED
    887      1.1  mrg 	  && flags.position != POSITION_APPEND)
    888      1.1  mrg 	generate_error (&opp->common, LIBERROR_BAD_OPTION,
    889      1.1  mrg 			"Conflicting ACCESS and POSITION flags in"
    890      1.1  mrg 			" OPEN statement");
    891      1.1  mrg 
    892      1.1  mrg       notify_std (&opp->common, GFC_STD_GNU,
    893      1.1  mrg 		  "Extension: APPEND as a value for ACCESS in OPEN statement");
    894      1.1  mrg       flags.access = ACCESS_SEQUENTIAL;
    895      1.1  mrg       flags.position = POSITION_APPEND;
    896      1.1  mrg     }
    897      1.1  mrg 
    898      1.1  mrg   if (flags.position == POSITION_UNSPECIFIED)
    899      1.1  mrg     flags.position = POSITION_ASIS;
    900      1.1  mrg 
    901      1.1  mrg   if ((opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
    902      1.1  mrg     {
    903      1.1  mrg       if ((opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT))
    904      1.1  mrg 	opp->common.unit = newunit_alloc ();
    905      1.1  mrg       else if (opp->common.unit < 0)
    906      1.1  mrg 	{
    907      1.1  mrg 	  u = find_unit (opp->common.unit);
    908      1.1  mrg 	  if (u == NULL) /* Negative unit and no NEWUNIT-created unit found.  */
    909      1.1  mrg 	    {
    910      1.1  mrg 	      generate_error (&opp->common, LIBERROR_BAD_OPTION,
    911      1.1  mrg 			      "Bad unit number in OPEN statement");
    912      1.1  mrg 	      library_end ();
    913      1.1  mrg 	      return;
    914      1.1  mrg 	    }
    915      1.1  mrg 	}
    916      1.1  mrg 
    917      1.1  mrg       if (u == NULL)
    918      1.1  mrg 	u = find_or_create_unit (opp->common.unit);
    919      1.1  mrg       if (u->s == NULL)
    920      1.1  mrg 	{
    921      1.1  mrg 	  u = new_unit (opp, u, &flags);
    922      1.1  mrg 	  if (u != NULL)
    923      1.1  mrg 	    unlock_unit (u);
    924      1.1  mrg 	}
    925      1.1  mrg       else
    926      1.1  mrg 	already_open (opp, u, &flags);
    927      1.1  mrg     }
    928      1.1  mrg 
    929      1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT)
    930      1.1  mrg       && (opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
    931      1.1  mrg     *opp->newunit = opp->common.unit;
    932      1.1  mrg 
    933      1.1  mrg   library_end ();
    934      1.1  mrg }
    935