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