Home | History | Annotate | Line # | Download | only in io
open.c revision 1.1
      1  1.1  mrg /* Copyright (C) 2002-2019 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  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) != 0)
    519  1.1  mrg     u2 = find_file (opp->file, opp->file_len);
    520  1.1  mrg   if (u2 != NULL
    521  1.1  mrg       && (options.stdin_unit < 0 || u2->unit_number != options.stdin_unit)
    522  1.1  mrg       && (options.stdout_unit < 0 || u2->unit_number != options.stdout_unit)
    523  1.1  mrg       && (options.stderr_unit < 0 || u2->unit_number != options.stderr_unit))
    524  1.1  mrg     {
    525  1.1  mrg       unlock_unit (u2);
    526  1.1  mrg       generate_error (&opp->common, LIBERROR_ALREADY_OPEN, NULL);
    527  1.1  mrg       goto cleanup;
    528  1.1  mrg     }
    529  1.1  mrg 
    530  1.1  mrg   if (u2 != NULL)
    531  1.1  mrg     unlock_unit (u2);
    532  1.1  mrg 
    533  1.1  mrg   /* If the unit specified is preconnected with a file specified to be open,
    534  1.1  mrg      then clear the format buffer.  */
    535  1.1  mrg   if ((opp->common.unit == options.stdin_unit ||
    536  1.1  mrg        opp->common.unit == options.stdout_unit ||
    537  1.1  mrg        opp->common.unit == options.stderr_unit)
    538  1.1  mrg       && (opp->common.flags & IOPARM_OPEN_HAS_FILE) != 0)
    539  1.1  mrg     fbuf_destroy (u);
    540  1.1  mrg 
    541  1.1  mrg   /* Open file.  */
    542  1.1  mrg 
    543  1.1  mrg   s = open_external (opp, flags);
    544  1.1  mrg   if (s == NULL)
    545  1.1  mrg     {
    546  1.1  mrg       char errbuf[256];
    547  1.1  mrg       char *path = fc_strdup (opp->file, opp->file_len);
    548  1.1  mrg       size_t msglen = opp->file_len + 22 + sizeof (errbuf);
    549  1.1  mrg       char *msg = xmalloc (msglen);
    550  1.1  mrg       snprintf (msg, msglen, "Cannot open file '%s': %s", path,
    551  1.1  mrg 		gf_strerror (errno, errbuf, sizeof (errbuf)));
    552  1.1  mrg       generate_error (&opp->common, LIBERROR_OS, msg);
    553  1.1  mrg       free (msg);
    554  1.1  mrg       free (path);
    555  1.1  mrg       goto cleanup;
    556  1.1  mrg     }
    557  1.1  mrg 
    558  1.1  mrg   if (flags->status == STATUS_NEW || flags->status == STATUS_REPLACE)
    559  1.1  mrg     flags->status = STATUS_OLD;
    560  1.1  mrg 
    561  1.1  mrg   /* Create the unit structure.  */
    562  1.1  mrg 
    563  1.1  mrg   if (u->unit_number != opp->common.unit)
    564  1.1  mrg     internal_error (&opp->common, "Unit number changed");
    565  1.1  mrg   u->s = s;
    566  1.1  mrg   u->flags = *flags;
    567  1.1  mrg   u->read_bad = 0;
    568  1.1  mrg   u->endfile = NO_ENDFILE;
    569  1.1  mrg   u->last_record = 0;
    570  1.1  mrg   u->current_record = 0;
    571  1.1  mrg   u->mode = READING;
    572  1.1  mrg   u->maxrec = 0;
    573  1.1  mrg   u->bytes_left = 0;
    574  1.1  mrg   u->saved_pos = 0;
    575  1.1  mrg 
    576  1.1  mrg   if (flags->position == POSITION_APPEND)
    577  1.1  mrg     {
    578  1.1  mrg       if (sseek (u->s, 0, SEEK_END) < 0)
    579  1.1  mrg 	{
    580  1.1  mrg 	  generate_error (&opp->common, LIBERROR_OS, NULL);
    581  1.1  mrg 	  goto cleanup;
    582  1.1  mrg 	}
    583  1.1  mrg       u->endfile = AT_ENDFILE;
    584  1.1  mrg     }
    585  1.1  mrg 
    586  1.1  mrg   /* Unspecified recl ends up with a processor dependent value.  */
    587  1.1  mrg 
    588  1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN))
    589  1.1  mrg     {
    590  1.1  mrg       u->flags.has_recl = 1;
    591  1.1  mrg       u->recl = opp->recl_in;
    592  1.1  mrg       u->recl_subrecord = u->recl;
    593  1.1  mrg       u->bytes_left = u->recl;
    594  1.1  mrg     }
    595  1.1  mrg   else
    596  1.1  mrg     {
    597  1.1  mrg       u->flags.has_recl = 0;
    598  1.1  mrg       u->recl = default_recl;
    599  1.1  mrg       if (compile_options.max_subrecord_length)
    600  1.1  mrg 	{
    601  1.1  mrg 	  u->recl_subrecord = compile_options.max_subrecord_length;
    602  1.1  mrg 	}
    603  1.1  mrg       else
    604  1.1  mrg 	{
    605  1.1  mrg 	  switch (compile_options.record_marker)
    606  1.1  mrg 	    {
    607  1.1  mrg 	    case 0:
    608  1.1  mrg 	      /* Fall through */
    609  1.1  mrg 	    case sizeof (GFC_INTEGER_4):
    610  1.1  mrg 	      u->recl_subrecord = GFC_MAX_SUBRECORD_LENGTH;
    611  1.1  mrg 	      break;
    612  1.1  mrg 
    613  1.1  mrg 	    case sizeof (GFC_INTEGER_8):
    614  1.1  mrg 	      u->recl_subrecord = max_offset - 16;
    615  1.1  mrg 	      break;
    616  1.1  mrg 
    617  1.1  mrg 	    default:
    618  1.1  mrg 	      runtime_error ("Illegal value for record marker");
    619  1.1  mrg 	      break;
    620  1.1  mrg 	    }
    621  1.1  mrg 	}
    622  1.1  mrg     }
    623  1.1  mrg 
    624  1.1  mrg   /* If the file is direct access, calculate the maximum record number
    625  1.1  mrg      via a division now instead of letting the multiplication overflow
    626  1.1  mrg      later.  */
    627  1.1  mrg 
    628  1.1  mrg   if (flags->access == ACCESS_DIRECT)
    629  1.1  mrg     u->maxrec = max_offset / u->recl;
    630  1.1  mrg 
    631  1.1  mrg   if (flags->access == ACCESS_STREAM)
    632  1.1  mrg     {
    633  1.1  mrg       u->maxrec = max_offset;
    634  1.1  mrg       /* F2018 (N2137) 12.10.2.26: If the connection is for stream
    635  1.1  mrg 	 access recl is assigned the value -2.  */
    636  1.1  mrg       u->recl = -2;
    637  1.1  mrg       u->bytes_left = 1;
    638  1.1  mrg       u->strm_pos = stell (u->s) + 1;
    639  1.1  mrg     }
    640  1.1  mrg 
    641  1.1  mrg   u->filename = fc_strdup (opp->file, opp->file_len);
    642  1.1  mrg 
    643  1.1  mrg   /* Curiously, the standard requires that the
    644  1.1  mrg      position specifier be ignored for new files so a newly connected
    645  1.1  mrg      file starts out at the initial point.  We still need to figure
    646  1.1  mrg      out if the file is at the end or not.  */
    647  1.1  mrg 
    648  1.1  mrg   test_endfile (u);
    649  1.1  mrg 
    650  1.1  mrg   if (flags->status == STATUS_SCRATCH && opp->file != NULL)
    651  1.1  mrg     free (opp->file);
    652  1.1  mrg 
    653  1.1  mrg   if (flags->form == FORM_FORMATTED)
    654  1.1  mrg     {
    655  1.1  mrg       if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN))
    656  1.1  mrg         fbuf_init (u, u->recl);
    657  1.1  mrg       else
    658  1.1  mrg         fbuf_init (u, 0);
    659  1.1  mrg     }
    660  1.1  mrg   else
    661  1.1  mrg     u->fbuf = NULL;
    662  1.1  mrg 
    663  1.1  mrg   /* Check if asynchrounous.  */
    664  1.1  mrg   if (flags->async == ASYNC_YES)
    665  1.1  mrg     init_async_unit (u);
    666  1.1  mrg   else
    667  1.1  mrg     u->au = NULL;
    668  1.1  mrg 
    669  1.1  mrg   return u;
    670  1.1  mrg 
    671  1.1  mrg  cleanup:
    672  1.1  mrg 
    673  1.1  mrg   /* Free memory associated with a temporary filename.  */
    674  1.1  mrg 
    675  1.1  mrg   if (flags->status == STATUS_SCRATCH && opp->file != NULL)
    676  1.1  mrg     free (opp->file);
    677  1.1  mrg 
    678  1.1  mrg  fail:
    679  1.1  mrg 
    680  1.1  mrg   close_unit (u);
    681  1.1  mrg   return NULL;
    682  1.1  mrg }
    683  1.1  mrg 
    684  1.1  mrg 
    685  1.1  mrg /* Open a unit which is already open.  This involves changing the
    686  1.1  mrg    modes or closing what is there now and opening the new file.  */
    687  1.1  mrg 
    688  1.1  mrg static void
    689  1.1  mrg already_open (st_parameter_open *opp, gfc_unit *u, unit_flags *flags)
    690  1.1  mrg {
    691  1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) == 0)
    692  1.1  mrg     {
    693  1.1  mrg       edit_modes (opp, u, flags);
    694  1.1  mrg       return;
    695  1.1  mrg     }
    696  1.1  mrg 
    697  1.1  mrg   /* If the file is connected to something else, close it and open a
    698  1.1  mrg      new unit.  */
    699  1.1  mrg 
    700  1.1  mrg   if (!compare_file_filename (u, opp->file, opp->file_len))
    701  1.1  mrg     {
    702  1.1  mrg       if (sclose (u->s) == -1)
    703  1.1  mrg 	{
    704  1.1  mrg 	  unlock_unit (u);
    705  1.1  mrg 	  generate_error (&opp->common, LIBERROR_OS,
    706  1.1  mrg 			  "Error closing file in OPEN statement");
    707  1.1  mrg 	  return;
    708  1.1  mrg 	}
    709  1.1  mrg 
    710  1.1  mrg       u->s = NULL;
    711  1.1  mrg 
    712  1.1  mrg #if !HAVE_UNLINK_OPEN_FILE
    713  1.1  mrg       if (u->filename && u->flags.status == STATUS_SCRATCH)
    714  1.1  mrg 	remove (u->filename);
    715  1.1  mrg #endif
    716  1.1  mrg       free (u->filename);
    717  1.1  mrg       u->filename = NULL;
    718  1.1  mrg 
    719  1.1  mrg       u = new_unit (opp, u, flags);
    720  1.1  mrg       if (u != NULL)
    721  1.1  mrg       unlock_unit (u);
    722  1.1  mrg       return;
    723  1.1  mrg     }
    724  1.1  mrg 
    725  1.1  mrg   edit_modes (opp, u, flags);
    726  1.1  mrg }
    727  1.1  mrg 
    728  1.1  mrg 
    729  1.1  mrg /* Open file.  */
    730  1.1  mrg 
    731  1.1  mrg extern void st_open (st_parameter_open *opp);
    732  1.1  mrg export_proto(st_open);
    733  1.1  mrg 
    734  1.1  mrg void
    735  1.1  mrg st_open (st_parameter_open *opp)
    736  1.1  mrg {
    737  1.1  mrg   unit_flags flags;
    738  1.1  mrg   gfc_unit *u = NULL;
    739  1.1  mrg   GFC_INTEGER_4 cf = opp->common.flags;
    740  1.1  mrg   unit_convert conv;
    741  1.1  mrg 
    742  1.1  mrg   library_start (&opp->common);
    743  1.1  mrg 
    744  1.1  mrg   /* Decode options.  */
    745  1.1  mrg   flags.readonly = !(cf & IOPARM_OPEN_HAS_READONLY) ? 0 : opp->readonly;
    746  1.1  mrg 
    747  1.1  mrg   flags.access = !(cf & IOPARM_OPEN_HAS_ACCESS) ? ACCESS_UNSPECIFIED :
    748  1.1  mrg     find_option (&opp->common, opp->access, opp->access_len,
    749  1.1  mrg 		 access_opt, "Bad ACCESS parameter in OPEN statement");
    750  1.1  mrg 
    751  1.1  mrg   flags.action = !(cf & IOPARM_OPEN_HAS_ACTION) ? ACTION_UNSPECIFIED :
    752  1.1  mrg     find_option (&opp->common, opp->action, opp->action_len,
    753  1.1  mrg 		 action_opt, "Bad ACTION parameter in OPEN statement");
    754  1.1  mrg 
    755  1.1  mrg   flags.cc = !(cf & IOPARM_OPEN_HAS_CC) ? CC_UNSPECIFIED :
    756  1.1  mrg     find_option (&opp->common, opp->cc, opp->cc_len,
    757  1.1  mrg 		 cc_opt, "Bad CARRIAGECONTROL parameter in OPEN statement");
    758  1.1  mrg 
    759  1.1  mrg   flags.share = !(cf & IOPARM_OPEN_HAS_SHARE) ? SHARE_UNSPECIFIED :
    760  1.1  mrg     find_option (&opp->common, opp->share, opp->share_len,
    761  1.1  mrg 		 share_opt, "Bad SHARE parameter in OPEN statement");
    762  1.1  mrg 
    763  1.1  mrg   flags.blank = !(cf & IOPARM_OPEN_HAS_BLANK) ? BLANK_UNSPECIFIED :
    764  1.1  mrg     find_option (&opp->common, opp->blank, opp->blank_len,
    765  1.1  mrg 		 blank_opt, "Bad BLANK parameter in OPEN statement");
    766  1.1  mrg 
    767  1.1  mrg   flags.delim = !(cf & IOPARM_OPEN_HAS_DELIM) ? DELIM_UNSPECIFIED :
    768  1.1  mrg     find_option (&opp->common, opp->delim, opp->delim_len,
    769  1.1  mrg 		 delim_opt, "Bad DELIM parameter in OPEN statement");
    770  1.1  mrg 
    771  1.1  mrg   flags.pad = !(cf & IOPARM_OPEN_HAS_PAD) ? PAD_UNSPECIFIED :
    772  1.1  mrg     find_option (&opp->common, opp->pad, opp->pad_len,
    773  1.1  mrg 		 pad_opt, "Bad PAD parameter in OPEN statement");
    774  1.1  mrg 
    775  1.1  mrg   flags.decimal = !(cf & IOPARM_OPEN_HAS_DECIMAL) ? DECIMAL_UNSPECIFIED :
    776  1.1  mrg     find_option (&opp->common, opp->decimal, opp->decimal_len,
    777  1.1  mrg 		 decimal_opt, "Bad DECIMAL parameter in OPEN statement");
    778  1.1  mrg 
    779  1.1  mrg   flags.encoding = !(cf & IOPARM_OPEN_HAS_ENCODING) ? ENCODING_UNSPECIFIED :
    780  1.1  mrg     find_option (&opp->common, opp->encoding, opp->encoding_len,
    781  1.1  mrg 		 encoding_opt, "Bad ENCODING parameter in OPEN statement");
    782  1.1  mrg 
    783  1.1  mrg   flags.async = !(cf & IOPARM_OPEN_HAS_ASYNCHRONOUS) ? ASYNC_UNSPECIFIED :
    784  1.1  mrg     find_option (&opp->common, opp->asynchronous, opp->asynchronous_len,
    785  1.1  mrg 		 async_opt, "Bad ASYNCHRONOUS parameter in OPEN statement");
    786  1.1  mrg 
    787  1.1  mrg   flags.round = !(cf & IOPARM_OPEN_HAS_ROUND) ? ROUND_UNSPECIFIED :
    788  1.1  mrg     find_option (&opp->common, opp->round, opp->round_len,
    789  1.1  mrg 		 round_opt, "Bad ROUND parameter in OPEN statement");
    790  1.1  mrg 
    791  1.1  mrg   flags.sign = !(cf & IOPARM_OPEN_HAS_SIGN) ? SIGN_UNSPECIFIED :
    792  1.1  mrg     find_option (&opp->common, opp->sign, opp->sign_len,
    793  1.1  mrg 		 sign_opt, "Bad SIGN parameter in OPEN statement");
    794  1.1  mrg 
    795  1.1  mrg   flags.form = !(cf & IOPARM_OPEN_HAS_FORM) ? FORM_UNSPECIFIED :
    796  1.1  mrg     find_option (&opp->common, opp->form, opp->form_len,
    797  1.1  mrg 		 form_opt, "Bad FORM parameter in OPEN statement");
    798  1.1  mrg 
    799  1.1  mrg   flags.position = !(cf & IOPARM_OPEN_HAS_POSITION) ? POSITION_UNSPECIFIED :
    800  1.1  mrg     find_option (&opp->common, opp->position, opp->position_len,
    801  1.1  mrg 		 position_opt, "Bad POSITION parameter in OPEN statement");
    802  1.1  mrg 
    803  1.1  mrg   flags.status = !(cf & IOPARM_OPEN_HAS_STATUS) ? STATUS_UNSPECIFIED :
    804  1.1  mrg     find_option (&opp->common, opp->status, opp->status_len,
    805  1.1  mrg 		 status_opt, "Bad STATUS parameter in OPEN statement");
    806  1.1  mrg 
    807  1.1  mrg   /* First, we check wether the convert flag has been set via environment
    808  1.1  mrg      variable.  This overrides the convert tag in the open statement.  */
    809  1.1  mrg 
    810  1.1  mrg   conv = get_unformatted_convert (opp->common.unit);
    811  1.1  mrg 
    812  1.1  mrg   if (conv == GFC_CONVERT_NONE)
    813  1.1  mrg     {
    814  1.1  mrg       /* Nothing has been set by environment variable, check the convert tag.  */
    815  1.1  mrg       if (cf & IOPARM_OPEN_HAS_CONVERT)
    816  1.1  mrg 	conv = find_option (&opp->common, opp->convert, opp->convert_len,
    817  1.1  mrg 			    convert_opt,
    818  1.1  mrg 			    "Bad CONVERT parameter in OPEN statement");
    819  1.1  mrg       else
    820  1.1  mrg 	conv = compile_options.convert;
    821  1.1  mrg     }
    822  1.1  mrg 
    823  1.1  mrg   switch (conv)
    824  1.1  mrg     {
    825  1.1  mrg     case GFC_CONVERT_NATIVE:
    826  1.1  mrg     case GFC_CONVERT_SWAP:
    827  1.1  mrg       break;
    828  1.1  mrg 
    829  1.1  mrg     case GFC_CONVERT_BIG:
    830  1.1  mrg       conv = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? GFC_CONVERT_NATIVE : GFC_CONVERT_SWAP;
    831  1.1  mrg       break;
    832  1.1  mrg 
    833  1.1  mrg     case GFC_CONVERT_LITTLE:
    834  1.1  mrg       conv = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? GFC_CONVERT_SWAP : GFC_CONVERT_NATIVE;
    835  1.1  mrg       break;
    836  1.1  mrg 
    837  1.1  mrg     default:
    838  1.1  mrg       internal_error (&opp->common, "Illegal value for CONVERT");
    839  1.1  mrg       break;
    840  1.1  mrg     }
    841  1.1  mrg 
    842  1.1  mrg   flags.convert = conv;
    843  1.1  mrg 
    844  1.1  mrg   if (flags.position != POSITION_UNSPECIFIED
    845  1.1  mrg       && flags.access == ACCESS_DIRECT)
    846  1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    847  1.1  mrg 		    "Cannot use POSITION with direct access files");
    848  1.1  mrg 
    849  1.1  mrg   if (flags.readonly
    850  1.1  mrg       && flags.action != ACTION_UNSPECIFIED && flags.action != ACTION_READ)
    851  1.1  mrg     generate_error (&opp->common, LIBERROR_BAD_OPTION,
    852  1.1  mrg 		    "ACTION conflicts with READONLY in OPEN statement");
    853  1.1  mrg 
    854  1.1  mrg   if (flags.access == ACCESS_APPEND)
    855  1.1  mrg     {
    856  1.1  mrg       if (flags.position != POSITION_UNSPECIFIED
    857  1.1  mrg 	  && flags.position != POSITION_APPEND)
    858  1.1  mrg 	generate_error (&opp->common, LIBERROR_BAD_OPTION,
    859  1.1  mrg 			"Conflicting ACCESS and POSITION flags in"
    860  1.1  mrg 			" OPEN statement");
    861  1.1  mrg 
    862  1.1  mrg       notify_std (&opp->common, GFC_STD_GNU,
    863  1.1  mrg 		  "Extension: APPEND as a value for ACCESS in OPEN statement");
    864  1.1  mrg       flags.access = ACCESS_SEQUENTIAL;
    865  1.1  mrg       flags.position = POSITION_APPEND;
    866  1.1  mrg     }
    867  1.1  mrg 
    868  1.1  mrg   if (flags.position == POSITION_UNSPECIFIED)
    869  1.1  mrg     flags.position = POSITION_ASIS;
    870  1.1  mrg 
    871  1.1  mrg   if ((opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
    872  1.1  mrg     {
    873  1.1  mrg       if ((opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT))
    874  1.1  mrg 	opp->common.unit = newunit_alloc ();
    875  1.1  mrg       else if (opp->common.unit < 0)
    876  1.1  mrg 	{
    877  1.1  mrg 	  u = find_unit (opp->common.unit);
    878  1.1  mrg 	  if (u == NULL) /* Negative unit and no NEWUNIT-created unit found.  */
    879  1.1  mrg 	    {
    880  1.1  mrg 	      generate_error (&opp->common, LIBERROR_BAD_OPTION,
    881  1.1  mrg 			      "Bad unit number in OPEN statement");
    882  1.1  mrg 	      library_end ();
    883  1.1  mrg 	      return;
    884  1.1  mrg 	    }
    885  1.1  mrg 	}
    886  1.1  mrg 
    887  1.1  mrg       if (u == NULL)
    888  1.1  mrg 	u = find_or_create_unit (opp->common.unit);
    889  1.1  mrg       if (u->s == NULL)
    890  1.1  mrg 	{
    891  1.1  mrg 	  u = new_unit (opp, u, &flags);
    892  1.1  mrg 	  if (u != NULL)
    893  1.1  mrg 	    unlock_unit (u);
    894  1.1  mrg 	}
    895  1.1  mrg       else
    896  1.1  mrg 	already_open (opp, u, &flags);
    897  1.1  mrg     }
    898  1.1  mrg 
    899  1.1  mrg   if ((opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT)
    900  1.1  mrg       && (opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
    901  1.1  mrg     *opp->newunit = opp->common.unit;
    902  1.1  mrg 
    903  1.1  mrg   library_end ();
    904  1.1  mrg }
    905