Home | History | Annotate | Line # | Download | only in io
open.c revision 1.1.1.2
      1  1.1.1.2  mrg /* Copyright (C) 2002-2020 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  mrg   { NULL, 0}
    157      1.1  mrg };
    158      1.1  mrg 
    159      1.1  mrg static const st_option async_opt[] =
    160      1.1  mrg {
    161      1.1  mrg   { "yes", ASYNC_YES},
    162      1.1  mrg   { "no", ASYNC_NO},
    163      1.1  mrg   { NULL, 0}
    164      1.1  mrg };
    165      1.1  mrg 
    166      1.1  mrg /* Given a unit, test to see if the file is positioned at the terminal
    167      1.1  mrg    point, and if so, change state from NO_ENDFILE flag to AT_ENDFILE.
    168      1.1  mrg    This prevents us from changing the state from AFTER_ENDFILE to
    169      1.1  mrg    AT_ENDFILE.  */
    170      1.1  mrg 
    171      1.1  mrg static void
    172      1.1  mrg test_endfile (gfc_unit *u)
    173      1.1  mrg {
    174      1.1  mrg   if (u->endfile == NO_ENDFILE)
    175      1.1  mrg     {
    176      1.1  mrg       gfc_offset sz = ssize (u->s);
    177      1.1  mrg       if (sz == 0 || sz == stell (u->s))
    178      1.1  mrg 	u->endfile = AT_ENDFILE;
    179      1.1  mrg     }
    180      1.1  mrg }
    181      1.1  mrg 
    182      1.1  mrg 
    183      1.1  mrg /* Change the modes of a file, those that are allowed * to be
    184      1.1  mrg    changed.  */
    185      1.1  mrg 
    186      1.1  mrg static void
    187      1.1  mrg edit_modes (st_parameter_open *opp, gfc_unit *u, unit_flags *flags)
    188      1.1  mrg {
    189      1.1  mrg   /* Complain about attempts to change the unchangeable.  */
    190      1.1  mrg 
    191      1.1  mrg   if (flags->status != STATUS_UNSPECIFIED && flags->status != STATUS_OLD &&
    192      1.1  mrg       u->flags.status != flags->status)
    193      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    194      1.1  mrg 		    "Cannot change STATUS parameter in OPEN statement");
    195      1.1  mrg 
    196      1.1  mrg   if (flags->access != ACCESS_UNSPECIFIED && u->flags.access != flags->access)
    197      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    198      1.1  mrg 		    "Cannot change ACCESS parameter in OPEN statement");
    199      1.1  mrg 
    200      1.1  mrg   if (flags->form != FORM_UNSPECIFIED && u->flags.form != flags->form)
    201      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    202      1.1  mrg 		    "Cannot change FORM parameter in OPEN statement");
    203      1.1  mrg 
    204      1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN)
    205      1.1  mrg       && opp->recl_in != u->recl)
    206      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    207      1.1  mrg 		    "Cannot change RECL parameter in OPEN statement");
    208      1.1  mrg 
    209      1.1  mrg   if (flags->action != ACTION_UNSPECIFIED && u->flags.action != flags->action)
    210      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    211      1.1  mrg 		    "Cannot change ACTION parameter in OPEN statement");
    212      1.1  mrg 
    213      1.1  mrg   if (flags->share != SHARE_UNSPECIFIED && u->flags.share != flags->share)
    214      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    215      1.1  mrg 		    "Cannot change SHARE parameter in OPEN statement");
    216      1.1  mrg 
    217      1.1  mrg   if (flags->cc != CC_UNSPECIFIED && u->flags.cc != flags->cc)
    218      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    219      1.1  mrg 		  "Cannot change CARRIAGECONTROL parameter in OPEN statement");
    220      1.1  mrg 
    221      1.1  mrg   /* Status must be OLD if present.  */
    222      1.1  mrg 
    223      1.1  mrg   if (flags->status != STATUS_UNSPECIFIED && flags->status != STATUS_OLD &&
    224      1.1  mrg       flags->status != STATUS_UNKNOWN)
    225      1.1  mrg     {
    226      1.1  mrg       if (flags->status == STATUS_SCRATCH)
    227      1.1  mrg 	notify_std (&opp->common, GFC_STD_GNU,
    228      1.1  mrg 		    "OPEN statement must have a STATUS of OLD or UNKNOWN");
    229      1.1  mrg       else
    230      1.1  mrg 	generate_error (&opp->common, LIBERROR_BAD_OPTION,
    231      1.1  mrg 		    "OPEN statement must have a STATUS of OLD or UNKNOWN");
    232      1.1  mrg     }
    233      1.1  mrg 
    234      1.1  mrg   if (u->flags.form == FORM_UNFORMATTED)
    235      1.1  mrg     {
    236      1.1  mrg       if (flags->delim != DELIM_UNSPECIFIED)
    237      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    238      1.1  mrg 			"DELIM parameter conflicts with UNFORMATTED form in "
    239      1.1  mrg 			"OPEN statement");
    240      1.1  mrg 
    241      1.1  mrg       if (flags->blank != BLANK_UNSPECIFIED)
    242      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    243      1.1  mrg 			"BLANK parameter conflicts with UNFORMATTED form in "
    244      1.1  mrg 			"OPEN statement");
    245      1.1  mrg 
    246      1.1  mrg       if (flags->pad != PAD_UNSPECIFIED)
    247      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    248      1.1  mrg 			"PAD parameter conflicts with UNFORMATTED form in "
    249      1.1  mrg 			"OPEN statement");
    250      1.1  mrg 
    251      1.1  mrg       if (flags->decimal != DECIMAL_UNSPECIFIED)
    252      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    253      1.1  mrg 			"DECIMAL parameter conflicts with UNFORMATTED form in "
    254      1.1  mrg 			"OPEN statement");
    255      1.1  mrg 
    256      1.1  mrg       if (flags->encoding != ENCODING_UNSPECIFIED)
    257      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    258      1.1  mrg 			"ENCODING parameter conflicts with UNFORMATTED form in "
    259      1.1  mrg 			"OPEN statement");
    260      1.1  mrg 
    261      1.1  mrg       if (flags->round != ROUND_UNSPECIFIED)
    262      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    263      1.1  mrg 			"ROUND parameter conflicts with UNFORMATTED form in "
    264      1.1  mrg 			"OPEN statement");
    265      1.1  mrg 
    266      1.1  mrg       if (flags->sign != SIGN_UNSPECIFIED)
    267      1.1  mrg 	generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    268      1.1  mrg 			"SIGN parameter conflicts with UNFORMATTED form in "
    269      1.1  mrg 			"OPEN statement");
    270      1.1  mrg     }
    271      1.1  mrg 
    272      1.1  mrg   if ((opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
    273      1.1  mrg     {
    274      1.1  mrg       /* Change the changeable:  */
    275      1.1  mrg       if (flags->blank != BLANK_UNSPECIFIED)
    276      1.1  mrg 	u->flags.blank = flags->blank;
    277      1.1  mrg       if (flags->delim != DELIM_UNSPECIFIED)
    278      1.1  mrg 	u->flags.delim = flags->delim;
    279      1.1  mrg       if (flags->pad != PAD_UNSPECIFIED)
    280      1.1  mrg 	u->flags.pad = flags->pad;
    281      1.1  mrg       if (flags->decimal != DECIMAL_UNSPECIFIED)
    282      1.1  mrg 	u->flags.decimal = flags->decimal;
    283      1.1  mrg       if (flags->encoding != ENCODING_UNSPECIFIED)
    284      1.1  mrg 	u->flags.encoding = flags->encoding;
    285      1.1  mrg       if (flags->async != ASYNC_UNSPECIFIED)
    286      1.1  mrg 	u->flags.async = flags->async;
    287      1.1  mrg       if (flags->round != ROUND_UNSPECIFIED)
    288      1.1  mrg 	u->flags.round = flags->round;
    289      1.1  mrg       if (flags->sign != SIGN_UNSPECIFIED)
    290      1.1  mrg 	u->flags.sign = flags->sign;
    291      1.1  mrg 
    292      1.1  mrg       /* Reposition the file if necessary.  */
    293      1.1  mrg 
    294      1.1  mrg       switch (flags->position)
    295      1.1  mrg 	{
    296      1.1  mrg 	case POSITION_UNSPECIFIED:
    297      1.1  mrg 	case POSITION_ASIS:
    298      1.1  mrg 	  break;
    299      1.1  mrg 
    300      1.1  mrg 	case POSITION_REWIND:
    301      1.1  mrg 	  if (sseek (u->s, 0, SEEK_SET) != 0)
    302      1.1  mrg 	    goto seek_error;
    303      1.1  mrg 
    304      1.1  mrg 	  u->current_record = 0;
    305      1.1  mrg 	  u->last_record = 0;
    306      1.1  mrg 
    307      1.1  mrg 	  test_endfile (u);
    308      1.1  mrg 	  break;
    309      1.1  mrg 
    310      1.1  mrg 	case POSITION_APPEND:
    311      1.1  mrg 	  if (sseek (u->s, 0, SEEK_END) < 0)
    312      1.1  mrg 	    goto seek_error;
    313      1.1  mrg 
    314      1.1  mrg 	  if (flags->access != ACCESS_STREAM)
    315      1.1  mrg 	    u->current_record = 0;
    316      1.1  mrg 
    317      1.1  mrg 	  u->endfile = AT_ENDFILE;	/* We are at the end.  */
    318      1.1  mrg 	  break;
    319      1.1  mrg 
    320      1.1  mrg 	seek_error:
    321      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OS, NULL);
    322      1.1  mrg 	  break;
    323      1.1  mrg 	}
    324      1.1  mrg     }
    325      1.1  mrg 
    326      1.1  mrg   unlock_unit (u);
    327      1.1  mrg }
    328      1.1  mrg 
    329      1.1  mrg 
    330      1.1  mrg /* Open an unused unit.  */
    331      1.1  mrg 
    332      1.1  mrg gfc_unit *
    333      1.1  mrg new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags *flags)
    334      1.1  mrg {
    335      1.1  mrg   gfc_unit *u2;
    336      1.1  mrg   stream *s;
    337      1.1  mrg   char tmpname[5 /* fort. */ + 10 /* digits of unit number */ + 1 /* 0 */];
    338      1.1  mrg 
    339      1.1  mrg   /* Change unspecifieds to defaults.  Leave (flags->action ==
    340      1.1  mrg      ACTION_UNSPECIFIED) alone so open_external() can set it based on
    341      1.1  mrg      what type of open actually works.  */
    342      1.1  mrg 
    343      1.1  mrg   if (flags->access == ACCESS_UNSPECIFIED)
    344      1.1  mrg     flags->access = ACCESS_SEQUENTIAL;
    345      1.1  mrg 
    346      1.1  mrg   if (flags->form == FORM_UNSPECIFIED)
    347      1.1  mrg     flags->form = (flags->access == ACCESS_SEQUENTIAL)
    348      1.1  mrg       ? FORM_FORMATTED : FORM_UNFORMATTED;
    349      1.1  mrg 
    350      1.1  mrg   if (flags->async == ASYNC_UNSPECIFIED)
    351      1.1  mrg     flags->async = ASYNC_NO;
    352      1.1  mrg 
    353      1.1  mrg   if (flags->status == STATUS_UNSPECIFIED)
    354      1.1  mrg     flags->status = STATUS_UNKNOWN;
    355      1.1  mrg 
    356      1.1  mrg   if (flags->cc == CC_UNSPECIFIED)
    357      1.1  mrg     flags->cc = flags->form == FORM_UNFORMATTED ? CC_NONE : CC_LIST;
    358      1.1  mrg   else if (flags->form == FORM_UNFORMATTED && flags->cc != CC_NONE)
    359      1.1  mrg     {
    360      1.1  mrg       generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    361      1.1  mrg 	  "CARRIAGECONTROL parameter conflicts with UNFORMATTED form in "
    362      1.1  mrg 	  "OPEN statement");
    363      1.1  mrg       goto fail;
    364      1.1  mrg     }
    365      1.1  mrg 
    366      1.1  mrg   /* Checks.  */
    367      1.1  mrg 
    368      1.1  mrg   if (flags->delim != DELIM_UNSPECIFIED
    369      1.1  mrg       && flags->form == FORM_UNFORMATTED)
    370      1.1  mrg     {
    371      1.1  mrg       generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    372      1.1  mrg 		      "DELIM parameter conflicts with UNFORMATTED form in "
    373      1.1  mrg 		      "OPEN statement");
    374      1.1  mrg       goto fail;
    375      1.1  mrg     }
    376      1.1  mrg 
    377      1.1  mrg   if (flags->blank == BLANK_UNSPECIFIED)
    378      1.1  mrg     flags->blank = BLANK_NULL;
    379      1.1  mrg   else
    380      1.1  mrg     {
    381      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    382      1.1  mrg 	{
    383      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    384      1.1  mrg 			  "BLANK parameter conflicts with UNFORMATTED form in "
    385      1.1  mrg 			  "OPEN statement");
    386      1.1  mrg 	  goto fail;
    387      1.1  mrg 	}
    388      1.1  mrg     }
    389      1.1  mrg 
    390      1.1  mrg   if (flags->pad == PAD_UNSPECIFIED)
    391      1.1  mrg     flags->pad = PAD_YES;
    392      1.1  mrg   else
    393      1.1  mrg     {
    394      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    395      1.1  mrg 	{
    396      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    397      1.1  mrg 			  "PAD parameter conflicts with UNFORMATTED form in "
    398      1.1  mrg 			  "OPEN statement");
    399      1.1  mrg 	  goto fail;
    400      1.1  mrg 	}
    401      1.1  mrg     }
    402      1.1  mrg 
    403      1.1  mrg   if (flags->decimal == DECIMAL_UNSPECIFIED)
    404      1.1  mrg     flags->decimal = DECIMAL_POINT;
    405      1.1  mrg   else
    406      1.1  mrg     {
    407      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    408      1.1  mrg 	{
    409      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    410      1.1  mrg 			  "DECIMAL parameter conflicts with UNFORMATTED form "
    411      1.1  mrg 			  "in OPEN statement");
    412      1.1  mrg 	  goto fail;
    413      1.1  mrg 	}
    414      1.1  mrg     }
    415      1.1  mrg 
    416      1.1  mrg   if (flags->encoding == ENCODING_UNSPECIFIED)
    417      1.1  mrg     flags->encoding = ENCODING_DEFAULT;
    418      1.1  mrg   else
    419      1.1  mrg     {
    420      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    421      1.1  mrg 	{
    422      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    423      1.1  mrg 			  "ENCODING parameter conflicts with UNFORMATTED form in "
    424      1.1  mrg 			  "OPEN statement");
    425      1.1  mrg 	  goto fail;
    426      1.1  mrg 	}
    427      1.1  mrg     }
    428      1.1  mrg 
    429      1.1  mrg   /* NB: the value for ROUND when it's not specified by the user does not
    430      1.1  mrg          have to be PROCESSOR_DEFINED; the standard says that it is
    431      1.1  mrg 	 processor dependent, and requires that it is one of the
    432      1.1  mrg 	 possible value (see F2003, 9.4.5.13).  */
    433      1.1  mrg   if (flags->round == ROUND_UNSPECIFIED)
    434      1.1  mrg     flags->round = ROUND_PROCDEFINED;
    435      1.1  mrg   else
    436      1.1  mrg     {
    437      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    438      1.1  mrg 	{
    439      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    440      1.1  mrg 			  "ROUND parameter conflicts with UNFORMATTED form in "
    441      1.1  mrg 			  "OPEN statement");
    442      1.1  mrg 	  goto fail;
    443      1.1  mrg 	}
    444      1.1  mrg     }
    445      1.1  mrg 
    446      1.1  mrg   if (flags->sign == SIGN_UNSPECIFIED)
    447      1.1  mrg     flags->sign = SIGN_PROCDEFINED;
    448      1.1  mrg   else
    449      1.1  mrg     {
    450      1.1  mrg       if (flags->form == FORM_UNFORMATTED)
    451      1.1  mrg 	{
    452      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    453      1.1  mrg 			  "SIGN parameter conflicts with UNFORMATTED form in "
    454      1.1  mrg 			  "OPEN statement");
    455      1.1  mrg 	  goto fail;
    456      1.1  mrg 	}
    457      1.1  mrg     }
    458      1.1  mrg 
    459      1.1  mrg   if (flags->position != POSITION_ASIS && flags->access == ACCESS_DIRECT)
    460      1.1  mrg    {
    461      1.1  mrg      generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
    462      1.1  mrg                      "ACCESS parameter conflicts with SEQUENTIAL access in "
    463      1.1  mrg                      "OPEN statement");
    464      1.1  mrg      goto fail;
    465      1.1  mrg    }
    466      1.1  mrg   else
    467      1.1  mrg    if (flags->position == POSITION_UNSPECIFIED)
    468      1.1  mrg      flags->position = POSITION_ASIS;
    469      1.1  mrg 
    470      1.1  mrg   if (flags->access == ACCESS_DIRECT
    471      1.1  mrg       && (opp->common.flags & IOPARM_OPEN_HAS_RECL_IN) == 0)
    472      1.1  mrg     {
    473      1.1  mrg       generate_error (&opp->common, LIBERROR_MISSING_OPTION,
    474      1.1  mrg 		      "Missing RECL parameter in OPEN statement");
    475      1.1  mrg       goto fail;
    476      1.1  mrg     }
    477      1.1  mrg 
    478      1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN) && opp->recl_in <= 0)
    479      1.1  mrg     {
    480      1.1  mrg       generate_error (&opp->common, LIBERROR_BAD_OPTION,
    481      1.1  mrg 		      "RECL parameter is non-positive in OPEN statement");
    482      1.1  mrg       goto fail;
    483      1.1  mrg     }
    484      1.1  mrg 
    485      1.1  mrg   switch (flags->status)
    486      1.1  mrg     {
    487      1.1  mrg     case STATUS_SCRATCH:
    488      1.1  mrg       if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) == 0)
    489      1.1  mrg 	{
    490      1.1  mrg 	  opp->file = NULL;
    491      1.1  mrg 	  break;
    492      1.1  mrg 	}
    493      1.1  mrg 
    494      1.1  mrg       generate_error (&opp->common, LIBERROR_BAD_OPTION,
    495      1.1  mrg 		      "FILE parameter must not be present in OPEN statement");
    496      1.1  mrg       goto fail;
    497      1.1  mrg 
    498      1.1  mrg     case STATUS_OLD:
    499      1.1  mrg     case STATUS_NEW:
    500      1.1  mrg     case STATUS_REPLACE:
    501      1.1  mrg     case STATUS_UNKNOWN:
    502      1.1  mrg       if ((opp->common.flags & IOPARM_OPEN_HAS_FILE))
    503      1.1  mrg 	break;
    504      1.1  mrg 
    505      1.1  mrg       opp->file = tmpname;
    506      1.1  mrg       opp->file_len = snprintf(opp->file, sizeof (tmpname), "fort.%d",
    507      1.1  mrg 			       (int) opp->common.unit);
    508      1.1  mrg       break;
    509      1.1  mrg 
    510      1.1  mrg     default:
    511      1.1  mrg       internal_error (&opp->common, "new_unit(): Bad status");
    512      1.1  mrg     }
    513      1.1  mrg 
    514      1.1  mrg   /* Make sure the file isn't already open someplace else.
    515      1.1  mrg      Do not error if opening file preconnected to stdin, stdout, stderr.  */
    516      1.1  mrg 
    517      1.1  mrg   u2 = NULL;
    518  1.1.1.2  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) != 0
    519  1.1.1.2  mrg       && !(compile_options.allow_std & GFC_STD_F2018))
    520      1.1  mrg     u2 = find_file (opp->file, opp->file_len);
    521      1.1  mrg   if (u2 != NULL
    522      1.1  mrg       && (options.stdin_unit < 0 || u2->unit_number != options.stdin_unit)
    523      1.1  mrg       && (options.stdout_unit < 0 || u2->unit_number != options.stdout_unit)
    524      1.1  mrg       && (options.stderr_unit < 0 || u2->unit_number != options.stderr_unit))
    525      1.1  mrg     {
    526      1.1  mrg       unlock_unit (u2);
    527      1.1  mrg       generate_error (&opp->common, LIBERROR_ALREADY_OPEN, NULL);
    528      1.1  mrg       goto cleanup;
    529      1.1  mrg     }
    530      1.1  mrg 
    531      1.1  mrg   if (u2 != NULL)
    532      1.1  mrg     unlock_unit (u2);
    533      1.1  mrg 
    534      1.1  mrg   /* If the unit specified is preconnected with a file specified to be open,
    535      1.1  mrg      then clear the format buffer.  */
    536      1.1  mrg   if ((opp->common.unit == options.stdin_unit ||
    537      1.1  mrg        opp->common.unit == options.stdout_unit ||
    538      1.1  mrg        opp->common.unit == options.stderr_unit)
    539      1.1  mrg       && (opp->common.flags & IOPARM_OPEN_HAS_FILE) != 0)
    540      1.1  mrg     fbuf_destroy (u);
    541      1.1  mrg 
    542      1.1  mrg   /* Open file.  */
    543      1.1  mrg 
    544      1.1  mrg   s = open_external (opp, flags);
    545      1.1  mrg   if (s == NULL)
    546      1.1  mrg     {
    547      1.1  mrg       char errbuf[256];
    548      1.1  mrg       char *path = fc_strdup (opp->file, opp->file_len);
    549      1.1  mrg       size_t msglen = opp->file_len + 22 + sizeof (errbuf);
    550      1.1  mrg       char *msg = xmalloc (msglen);
    551      1.1  mrg       snprintf (msg, msglen, "Cannot open file '%s': %s", path,
    552      1.1  mrg 		gf_strerror (errno, errbuf, sizeof (errbuf)));
    553      1.1  mrg       generate_error (&opp->common, LIBERROR_OS, msg);
    554      1.1  mrg       free (msg);
    555      1.1  mrg       free (path);
    556      1.1  mrg       goto cleanup;
    557      1.1  mrg     }
    558      1.1  mrg 
    559      1.1  mrg   if (flags->status == STATUS_NEW || flags->status == STATUS_REPLACE)
    560      1.1  mrg     flags->status = STATUS_OLD;
    561      1.1  mrg 
    562      1.1  mrg   /* Create the unit structure.  */
    563      1.1  mrg 
    564      1.1  mrg   if (u->unit_number != opp->common.unit)
    565      1.1  mrg     internal_error (&opp->common, "Unit number changed");
    566      1.1  mrg   u->s = s;
    567      1.1  mrg   u->flags = *flags;
    568      1.1  mrg   u->read_bad = 0;
    569      1.1  mrg   u->endfile = NO_ENDFILE;
    570      1.1  mrg   u->last_record = 0;
    571      1.1  mrg   u->current_record = 0;
    572      1.1  mrg   u->mode = READING;
    573      1.1  mrg   u->maxrec = 0;
    574      1.1  mrg   u->bytes_left = 0;
    575      1.1  mrg   u->saved_pos = 0;
    576      1.1  mrg 
    577      1.1  mrg   if (flags->position == POSITION_APPEND)
    578      1.1  mrg     {
    579      1.1  mrg       if (sseek (u->s, 0, SEEK_END) < 0)
    580      1.1  mrg 	{
    581      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OS, NULL);
    582      1.1  mrg 	  goto cleanup;
    583      1.1  mrg 	}
    584      1.1  mrg       u->endfile = AT_ENDFILE;
    585      1.1  mrg     }
    586      1.1  mrg 
    587      1.1  mrg   /* Unspecified recl ends up with a processor dependent value.  */
    588      1.1  mrg 
    589      1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN))
    590      1.1  mrg     {
    591      1.1  mrg       u->flags.has_recl = 1;
    592      1.1  mrg       u->recl = opp->recl_in;
    593      1.1  mrg       u->recl_subrecord = u->recl;
    594      1.1  mrg       u->bytes_left = u->recl;
    595      1.1  mrg     }
    596      1.1  mrg   else
    597      1.1  mrg     {
    598      1.1  mrg       u->flags.has_recl = 0;
    599      1.1  mrg       u->recl = default_recl;
    600      1.1  mrg       if (compile_options.max_subrecord_length)
    601      1.1  mrg 	{
    602      1.1  mrg 	  u->recl_subrecord = compile_options.max_subrecord_length;
    603      1.1  mrg 	}
    604      1.1  mrg       else
    605      1.1  mrg 	{
    606      1.1  mrg 	  switch (compile_options.record_marker)
    607      1.1  mrg 	    {
    608      1.1  mrg 	    case 0:
    609      1.1  mrg 	      /* Fall through */
    610      1.1  mrg 	    case sizeof (GFC_INTEGER_4):
    611      1.1  mrg 	      u->recl_subrecord = GFC_MAX_SUBRECORD_LENGTH;
    612      1.1  mrg 	      break;
    613      1.1  mrg 
    614      1.1  mrg 	    case sizeof (GFC_INTEGER_8):
    615      1.1  mrg 	      u->recl_subrecord = max_offset - 16;
    616      1.1  mrg 	      break;
    617      1.1  mrg 
    618      1.1  mrg 	    default:
    619      1.1  mrg 	      runtime_error ("Illegal value for record marker");
    620      1.1  mrg 	      break;
    621      1.1  mrg 	    }
    622      1.1  mrg 	}
    623      1.1  mrg     }
    624      1.1  mrg 
    625      1.1  mrg   /* If the file is direct access, calculate the maximum record number
    626      1.1  mrg      via a division now instead of letting the multiplication overflow
    627      1.1  mrg      later.  */
    628      1.1  mrg 
    629      1.1  mrg   if (flags->access == ACCESS_DIRECT)
    630      1.1  mrg     u->maxrec = max_offset / u->recl;
    631      1.1  mrg 
    632      1.1  mrg   if (flags->access == ACCESS_STREAM)
    633      1.1  mrg     {
    634      1.1  mrg       u->maxrec = max_offset;
    635      1.1  mrg       /* F2018 (N2137) 12.10.2.26: If the connection is for stream
    636      1.1  mrg 	 access recl is assigned the value -2.  */
    637      1.1  mrg       u->recl = -2;
    638      1.1  mrg       u->bytes_left = 1;
    639      1.1  mrg       u->strm_pos = stell (u->s) + 1;
    640      1.1  mrg     }
    641      1.1  mrg 
    642      1.1  mrg   u->filename = fc_strdup (opp->file, opp->file_len);
    643      1.1  mrg 
    644      1.1  mrg   /* Curiously, the standard requires that the
    645      1.1  mrg      position specifier be ignored for new files so a newly connected
    646      1.1  mrg      file starts out at the initial point.  We still need to figure
    647      1.1  mrg      out if the file is at the end or not.  */
    648      1.1  mrg 
    649      1.1  mrg   test_endfile (u);
    650      1.1  mrg 
    651      1.1  mrg   if (flags->status == STATUS_SCRATCH && opp->file != NULL)
    652      1.1  mrg     free (opp->file);
    653      1.1  mrg 
    654      1.1  mrg   if (flags->form == FORM_FORMATTED)
    655      1.1  mrg     {
    656      1.1  mrg       if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN))
    657      1.1  mrg         fbuf_init (u, u->recl);
    658      1.1  mrg       else
    659      1.1  mrg         fbuf_init (u, 0);
    660      1.1  mrg     }
    661      1.1  mrg   else
    662      1.1  mrg     u->fbuf = NULL;
    663      1.1  mrg 
    664      1.1  mrg   /* Check if asynchrounous.  */
    665      1.1  mrg   if (flags->async == ASYNC_YES)
    666      1.1  mrg     init_async_unit (u);
    667      1.1  mrg   else
    668      1.1  mrg     u->au = NULL;
    669      1.1  mrg 
    670      1.1  mrg   return u;
    671      1.1  mrg 
    672      1.1  mrg  cleanup:
    673      1.1  mrg 
    674      1.1  mrg   /* Free memory associated with a temporary filename.  */
    675      1.1  mrg 
    676      1.1  mrg   if (flags->status == STATUS_SCRATCH && opp->file != NULL)
    677      1.1  mrg     free (opp->file);
    678      1.1  mrg 
    679      1.1  mrg  fail:
    680      1.1  mrg 
    681      1.1  mrg   close_unit (u);
    682      1.1  mrg   return NULL;
    683      1.1  mrg }
    684      1.1  mrg 
    685      1.1  mrg 
    686      1.1  mrg /* Open a unit which is already open.  This involves changing the
    687      1.1  mrg    modes or closing what is there now and opening the new file.  */
    688      1.1  mrg 
    689      1.1  mrg static void
    690      1.1  mrg already_open (st_parameter_open *opp, gfc_unit *u, unit_flags *flags)
    691      1.1  mrg {
    692      1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) == 0)
    693      1.1  mrg     {
    694      1.1  mrg       edit_modes (opp, u, flags);
    695      1.1  mrg       return;
    696      1.1  mrg     }
    697      1.1  mrg 
    698      1.1  mrg   /* If the file is connected to something else, close it and open a
    699      1.1  mrg      new unit.  */
    700      1.1  mrg 
    701      1.1  mrg   if (!compare_file_filename (u, opp->file, opp->file_len))
    702      1.1  mrg     {
    703      1.1  mrg       if (sclose (u->s) == -1)
    704      1.1  mrg 	{
    705      1.1  mrg 	  unlock_unit (u);
    706      1.1  mrg 	  generate_error (&opp->common, LIBERROR_OS,
    707      1.1  mrg 			  "Error closing file in OPEN statement");
    708      1.1  mrg 	  return;
    709      1.1  mrg 	}
    710      1.1  mrg 
    711      1.1  mrg       u->s = NULL;
    712      1.1  mrg 
    713      1.1  mrg #if !HAVE_UNLINK_OPEN_FILE
    714      1.1  mrg       if (u->filename && u->flags.status == STATUS_SCRATCH)
    715      1.1  mrg 	remove (u->filename);
    716      1.1  mrg #endif
    717      1.1  mrg       free (u->filename);
    718      1.1  mrg       u->filename = NULL;
    719      1.1  mrg 
    720      1.1  mrg       u = new_unit (opp, u, flags);
    721      1.1  mrg       if (u != NULL)
    722      1.1  mrg       unlock_unit (u);
    723      1.1  mrg       return;
    724      1.1  mrg     }
    725      1.1  mrg 
    726      1.1  mrg   edit_modes (opp, u, flags);
    727      1.1  mrg }
    728      1.1  mrg 
    729      1.1  mrg 
    730      1.1  mrg /* Open file.  */
    731      1.1  mrg 
    732      1.1  mrg extern void st_open (st_parameter_open *opp);
    733      1.1  mrg export_proto(st_open);
    734      1.1  mrg 
    735      1.1  mrg void
    736      1.1  mrg st_open (st_parameter_open *opp)
    737      1.1  mrg {
    738      1.1  mrg   unit_flags flags;
    739      1.1  mrg   gfc_unit *u = NULL;
    740      1.1  mrg   GFC_INTEGER_4 cf = opp->common.flags;
    741      1.1  mrg   unit_convert conv;
    742      1.1  mrg 
    743      1.1  mrg   library_start (&opp->common);
    744      1.1  mrg 
    745      1.1  mrg   /* Decode options.  */
    746      1.1  mrg   flags.readonly = !(cf & IOPARM_OPEN_HAS_READONLY) ? 0 : opp->readonly;
    747      1.1  mrg 
    748      1.1  mrg   flags.access = !(cf & IOPARM_OPEN_HAS_ACCESS) ? ACCESS_UNSPECIFIED :
    749      1.1  mrg     find_option (&opp->common, opp->access, opp->access_len,
    750      1.1  mrg 		 access_opt, "Bad ACCESS parameter in OPEN statement");
    751      1.1  mrg 
    752      1.1  mrg   flags.action = !(cf & IOPARM_OPEN_HAS_ACTION) ? ACTION_UNSPECIFIED :
    753      1.1  mrg     find_option (&opp->common, opp->action, opp->action_len,
    754      1.1  mrg 		 action_opt, "Bad ACTION parameter in OPEN statement");
    755      1.1  mrg 
    756      1.1  mrg   flags.cc = !(cf & IOPARM_OPEN_HAS_CC) ? CC_UNSPECIFIED :
    757      1.1  mrg     find_option (&opp->common, opp->cc, opp->cc_len,
    758      1.1  mrg 		 cc_opt, "Bad CARRIAGECONTROL parameter in OPEN statement");
    759      1.1  mrg 
    760      1.1  mrg   flags.share = !(cf & IOPARM_OPEN_HAS_SHARE) ? SHARE_UNSPECIFIED :
    761      1.1  mrg     find_option (&opp->common, opp->share, opp->share_len,
    762      1.1  mrg 		 share_opt, "Bad SHARE parameter in OPEN statement");
    763      1.1  mrg 
    764      1.1  mrg   flags.blank = !(cf & IOPARM_OPEN_HAS_BLANK) ? BLANK_UNSPECIFIED :
    765      1.1  mrg     find_option (&opp->common, opp->blank, opp->blank_len,
    766      1.1  mrg 		 blank_opt, "Bad BLANK parameter in OPEN statement");
    767      1.1  mrg 
    768      1.1  mrg   flags.delim = !(cf & IOPARM_OPEN_HAS_DELIM) ? DELIM_UNSPECIFIED :
    769      1.1  mrg     find_option (&opp->common, opp->delim, opp->delim_len,
    770      1.1  mrg 		 delim_opt, "Bad DELIM parameter in OPEN statement");
    771      1.1  mrg 
    772      1.1  mrg   flags.pad = !(cf & IOPARM_OPEN_HAS_PAD) ? PAD_UNSPECIFIED :
    773      1.1  mrg     find_option (&opp->common, opp->pad, opp->pad_len,
    774      1.1  mrg 		 pad_opt, "Bad PAD parameter in OPEN statement");
    775      1.1  mrg 
    776      1.1  mrg   flags.decimal = !(cf & IOPARM_OPEN_HAS_DECIMAL) ? DECIMAL_UNSPECIFIED :
    777      1.1  mrg     find_option (&opp->common, opp->decimal, opp->decimal_len,
    778      1.1  mrg 		 decimal_opt, "Bad DECIMAL parameter in OPEN statement");
    779      1.1  mrg 
    780      1.1  mrg   flags.encoding = !(cf & IOPARM_OPEN_HAS_ENCODING) ? ENCODING_UNSPECIFIED :
    781      1.1  mrg     find_option (&opp->common, opp->encoding, opp->encoding_len,
    782      1.1  mrg 		 encoding_opt, "Bad ENCODING parameter in OPEN statement");
    783      1.1  mrg 
    784      1.1  mrg   flags.async = !(cf & IOPARM_OPEN_HAS_ASYNCHRONOUS) ? ASYNC_UNSPECIFIED :
    785      1.1  mrg     find_option (&opp->common, opp->asynchronous, opp->asynchronous_len,
    786      1.1  mrg 		 async_opt, "Bad ASYNCHRONOUS parameter in OPEN statement");
    787      1.1  mrg 
    788      1.1  mrg   flags.round = !(cf & IOPARM_OPEN_HAS_ROUND) ? ROUND_UNSPECIFIED :
    789      1.1  mrg     find_option (&opp->common, opp->round, opp->round_len,
    790      1.1  mrg 		 round_opt, "Bad ROUND parameter in OPEN statement");
    791      1.1  mrg 
    792      1.1  mrg   flags.sign = !(cf & IOPARM_OPEN_HAS_SIGN) ? SIGN_UNSPECIFIED :
    793      1.1  mrg     find_option (&opp->common, opp->sign, opp->sign_len,
    794      1.1  mrg 		 sign_opt, "Bad SIGN parameter in OPEN statement");
    795      1.1  mrg 
    796      1.1  mrg   flags.form = !(cf & IOPARM_OPEN_HAS_FORM) ? FORM_UNSPECIFIED :
    797      1.1  mrg     find_option (&opp->common, opp->form, opp->form_len,
    798      1.1  mrg 		 form_opt, "Bad FORM parameter in OPEN statement");
    799      1.1  mrg 
    800      1.1  mrg   flags.position = !(cf & IOPARM_OPEN_HAS_POSITION) ? POSITION_UNSPECIFIED :
    801      1.1  mrg     find_option (&opp->common, opp->position, opp->position_len,
    802      1.1  mrg 		 position_opt, "Bad POSITION parameter in OPEN statement");
    803      1.1  mrg 
    804      1.1  mrg   flags.status = !(cf & IOPARM_OPEN_HAS_STATUS) ? STATUS_UNSPECIFIED :
    805      1.1  mrg     find_option (&opp->common, opp->status, opp->status_len,
    806      1.1  mrg 		 status_opt, "Bad STATUS parameter in OPEN statement");
    807      1.1  mrg 
    808      1.1  mrg   /* First, we check wether the convert flag has been set via environment
    809      1.1  mrg      variable.  This overrides the convert tag in the open statement.  */
    810      1.1  mrg 
    811      1.1  mrg   conv = get_unformatted_convert (opp->common.unit);
    812      1.1  mrg 
    813      1.1  mrg   if (conv == GFC_CONVERT_NONE)
    814      1.1  mrg     {
    815      1.1  mrg       /* Nothing has been set by environment variable, check the convert tag.  */
    816      1.1  mrg       if (cf & IOPARM_OPEN_HAS_CONVERT)
    817      1.1  mrg 	conv = find_option (&opp->common, opp->convert, opp->convert_len,
    818      1.1  mrg 			    convert_opt,
    819      1.1  mrg 			    "Bad CONVERT parameter in OPEN statement");
    820      1.1  mrg       else
    821      1.1  mrg 	conv = compile_options.convert;
    822      1.1  mrg     }
    823      1.1  mrg 
    824      1.1  mrg   switch (conv)
    825      1.1  mrg     {
    826      1.1  mrg     case GFC_CONVERT_NATIVE:
    827      1.1  mrg     case GFC_CONVERT_SWAP:
    828      1.1  mrg       break;
    829      1.1  mrg 
    830      1.1  mrg     case GFC_CONVERT_BIG:
    831      1.1  mrg       conv = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? GFC_CONVERT_NATIVE : GFC_CONVERT_SWAP;
    832      1.1  mrg       break;
    833      1.1  mrg 
    834      1.1  mrg     case GFC_CONVERT_LITTLE:
    835      1.1  mrg       conv = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? GFC_CONVERT_SWAP : GFC_CONVERT_NATIVE;
    836      1.1  mrg       break;
    837      1.1  mrg 
    838      1.1  mrg     default:
    839      1.1  mrg       internal_error (&opp->common, "Illegal value for CONVERT");
    840      1.1  mrg       break;
    841      1.1  mrg     }
    842      1.1  mrg 
    843      1.1  mrg   flags.convert = conv;
    844      1.1  mrg 
    845      1.1  mrg   if (flags.position != POSITION_UNSPECIFIED
    846      1.1  mrg       && flags.access == ACCESS_DIRECT)
    847      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    848      1.1  mrg 		    "Cannot use POSITION with direct access files");
    849      1.1  mrg 
    850      1.1  mrg   if (flags.readonly
    851      1.1  mrg       && flags.action != ACTION_UNSPECIFIED && flags.action != ACTION_READ)
    852      1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    853      1.1  mrg 		    "ACTION conflicts with READONLY in OPEN statement");
    854      1.1  mrg 
    855      1.1  mrg   if (flags.access == ACCESS_APPEND)
    856      1.1  mrg     {
    857      1.1  mrg       if (flags.position != POSITION_UNSPECIFIED
    858      1.1  mrg 	  && flags.position != POSITION_APPEND)
    859      1.1  mrg 	generate_error (&opp->common, LIBERROR_BAD_OPTION,
    860      1.1  mrg 			"Conflicting ACCESS and POSITION flags in"
    861      1.1  mrg 			" OPEN statement");
    862      1.1  mrg 
    863      1.1  mrg       notify_std (&opp->common, GFC_STD_GNU,
    864      1.1  mrg 		  "Extension: APPEND as a value for ACCESS in OPEN statement");
    865      1.1  mrg       flags.access = ACCESS_SEQUENTIAL;
    866      1.1  mrg       flags.position = POSITION_APPEND;
    867      1.1  mrg     }
    868      1.1  mrg 
    869      1.1  mrg   if (flags.position == POSITION_UNSPECIFIED)
    870      1.1  mrg     flags.position = POSITION_ASIS;
    871      1.1  mrg 
    872      1.1  mrg   if ((opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
    873      1.1  mrg     {
    874      1.1  mrg       if ((opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT))
    875      1.1  mrg 	opp->common.unit = newunit_alloc ();
    876      1.1  mrg       else if (opp->common.unit < 0)
    877      1.1  mrg 	{
    878      1.1  mrg 	  u = find_unit (opp->common.unit);
    879      1.1  mrg 	  if (u == NULL) /* Negative unit and no NEWUNIT-created unit found.  */
    880      1.1  mrg 	    {
    881      1.1  mrg 	      generate_error (&opp->common, LIBERROR_BAD_OPTION,
    882      1.1  mrg 			      "Bad unit number in OPEN statement");
    883      1.1  mrg 	      library_end ();
    884      1.1  mrg 	      return;
    885      1.1  mrg 	    }
    886      1.1  mrg 	}
    887      1.1  mrg 
    888      1.1  mrg       if (u == NULL)
    889      1.1  mrg 	u = find_or_create_unit (opp->common.unit);
    890      1.1  mrg       if (u->s == NULL)
    891      1.1  mrg 	{
    892      1.1  mrg 	  u = new_unit (opp, u, &flags);
    893      1.1  mrg 	  if (u != NULL)
    894      1.1  mrg 	    unlock_unit (u);
    895      1.1  mrg 	}
    896      1.1  mrg       else
    897      1.1  mrg 	already_open (opp, u, &flags);
    898      1.1  mrg     }
    899      1.1  mrg 
    900      1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT)
    901      1.1  mrg       && (opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
    902      1.1  mrg     *opp->newunit = opp->common.unit;
    903      1.1  mrg 
    904      1.1  mrg   library_end ();
    905      1.1  mrg }
    906