* configure.ac (GCJ_JAVAC): Run false rather than no.
[official-gcc.git] / libgfortran / io / open.c
blobd7448c007f137ae5f637d4ecd12ff189cae6d1fd
1 /* Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
2 Free Software Foundation, Inc.
3 Contributed by Andy Vaught
4 F2003 I/O support contributed by Jerry DeLisle
6 This file is part of the GNU Fortran runtime library (libgfortran).
8 Libgfortran is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 Libgfortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. */
27 #include "io.h"
28 #include "fbuf.h"
29 #include "unix.h"
30 #include <unistd.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <stdlib.h>
36 static const st_option access_opt[] = {
37 {"sequential", ACCESS_SEQUENTIAL},
38 {"direct", ACCESS_DIRECT},
39 {"append", ACCESS_APPEND},
40 {"stream", ACCESS_STREAM},
41 {NULL, 0}
44 static const st_option action_opt[] =
46 { "read", ACTION_READ},
47 { "write", ACTION_WRITE},
48 { "readwrite", ACTION_READWRITE},
49 { NULL, 0}
52 static const st_option blank_opt[] =
54 { "null", BLANK_NULL},
55 { "zero", BLANK_ZERO},
56 { NULL, 0}
59 static const st_option delim_opt[] =
61 { "none", DELIM_NONE},
62 { "apostrophe", DELIM_APOSTROPHE},
63 { "quote", DELIM_QUOTE},
64 { NULL, 0}
67 static const st_option form_opt[] =
69 { "formatted", FORM_FORMATTED},
70 { "unformatted", FORM_UNFORMATTED},
71 { NULL, 0}
74 static const st_option position_opt[] =
76 { "asis", POSITION_ASIS},
77 { "rewind", POSITION_REWIND},
78 { "append", POSITION_APPEND},
79 { NULL, 0}
82 static const st_option status_opt[] =
84 { "unknown", STATUS_UNKNOWN},
85 { "old", STATUS_OLD},
86 { "new", STATUS_NEW},
87 { "replace", STATUS_REPLACE},
88 { "scratch", STATUS_SCRATCH},
89 { NULL, 0}
92 static const st_option pad_opt[] =
94 { "yes", PAD_YES},
95 { "no", PAD_NO},
96 { NULL, 0}
99 static const st_option decimal_opt[] =
101 { "point", DECIMAL_POINT},
102 { "comma", DECIMAL_COMMA},
103 { NULL, 0}
106 static const st_option encoding_opt[] =
108 { "utf-8", ENCODING_UTF8},
109 { "default", ENCODING_DEFAULT},
110 { NULL, 0}
113 static const st_option round_opt[] =
115 { "up", ROUND_UP},
116 { "down", ROUND_DOWN},
117 { "zero", ROUND_ZERO},
118 { "nearest", ROUND_NEAREST},
119 { "compatible", ROUND_COMPATIBLE},
120 { "processor_defined", ROUND_PROCDEFINED},
121 { NULL, 0}
124 static const st_option sign_opt[] =
126 { "plus", SIGN_PLUS},
127 { "suppress", SIGN_SUPPRESS},
128 { "processor_defined", SIGN_PROCDEFINED},
129 { NULL, 0}
132 static const st_option convert_opt[] =
134 { "native", GFC_CONVERT_NATIVE},
135 { "swap", GFC_CONVERT_SWAP},
136 { "big_endian", GFC_CONVERT_BIG},
137 { "little_endian", GFC_CONVERT_LITTLE},
138 { NULL, 0}
141 static const st_option async_opt[] =
143 { "yes", ASYNC_YES},
144 { "no", ASYNC_NO},
145 { NULL, 0}
148 /* Given a unit, test to see if the file is positioned at the terminal
149 point, and if so, change state from NO_ENDFILE flag to AT_ENDFILE.
150 This prevents us from changing the state from AFTER_ENDFILE to
151 AT_ENDFILE. */
153 static void
154 test_endfile (gfc_unit * u)
156 if (u->endfile == NO_ENDFILE && file_length (u->s) == stell (u->s))
157 u->endfile = AT_ENDFILE;
161 /* Change the modes of a file, those that are allowed * to be
162 changed. */
164 static void
165 edit_modes (st_parameter_open *opp, gfc_unit * u, unit_flags * flags)
167 /* Complain about attempts to change the unchangeable. */
169 if (flags->status != STATUS_UNSPECIFIED && flags->status != STATUS_OLD &&
170 u->flags.status != flags->status)
171 generate_error (&opp->common, LIBERROR_BAD_OPTION,
172 "Cannot change STATUS parameter in OPEN statement");
174 if (flags->access != ACCESS_UNSPECIFIED && u->flags.access != flags->access)
175 generate_error (&opp->common, LIBERROR_BAD_OPTION,
176 "Cannot change ACCESS parameter in OPEN statement");
178 if (flags->form != FORM_UNSPECIFIED && u->flags.form != flags->form)
179 generate_error (&opp->common, LIBERROR_BAD_OPTION,
180 "Cannot change FORM parameter in OPEN statement");
182 if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN)
183 && opp->recl_in != u->recl)
184 generate_error (&opp->common, LIBERROR_BAD_OPTION,
185 "Cannot change RECL parameter in OPEN statement");
187 if (flags->action != ACTION_UNSPECIFIED && u->flags.action != flags->action)
188 generate_error (&opp->common, LIBERROR_BAD_OPTION,
189 "Cannot change ACTION parameter in OPEN statement");
191 /* Status must be OLD if present. */
193 if (flags->status != STATUS_UNSPECIFIED && flags->status != STATUS_OLD &&
194 flags->status != STATUS_UNKNOWN)
196 if (flags->status == STATUS_SCRATCH)
197 notify_std (&opp->common, GFC_STD_GNU,
198 "OPEN statement must have a STATUS of OLD or UNKNOWN");
199 else
200 generate_error (&opp->common, LIBERROR_BAD_OPTION,
201 "OPEN statement must have a STATUS of OLD or UNKNOWN");
204 if (u->flags.form == FORM_UNFORMATTED)
206 if (flags->delim != DELIM_UNSPECIFIED)
207 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
208 "DELIM parameter conflicts with UNFORMATTED form in "
209 "OPEN statement");
211 if (flags->blank != BLANK_UNSPECIFIED)
212 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
213 "BLANK parameter conflicts with UNFORMATTED form in "
214 "OPEN statement");
216 if (flags->pad != PAD_UNSPECIFIED)
217 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
218 "PAD parameter conflicts with UNFORMATTED form in "
219 "OPEN statement");
221 if (flags->decimal != DECIMAL_UNSPECIFIED)
222 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
223 "DECIMAL parameter conflicts with UNFORMATTED form in "
224 "OPEN statement");
226 if (flags->encoding != ENCODING_UNSPECIFIED)
227 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
228 "ENCODING parameter conflicts with UNFORMATTED form in "
229 "OPEN statement");
231 if (flags->round != ROUND_UNSPECIFIED)
232 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
233 "ROUND parameter conflicts with UNFORMATTED form in "
234 "OPEN statement");
236 if (flags->sign != SIGN_UNSPECIFIED)
237 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
238 "SIGN parameter conflicts with UNFORMATTED form in "
239 "OPEN statement");
242 if ((opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
244 /* Change the changeable: */
245 if (flags->blank != BLANK_UNSPECIFIED)
246 u->flags.blank = flags->blank;
247 if (flags->delim != DELIM_UNSPECIFIED)
248 u->flags.delim = flags->delim;
249 if (flags->pad != PAD_UNSPECIFIED)
250 u->flags.pad = flags->pad;
251 if (flags->decimal != DECIMAL_UNSPECIFIED)
252 u->flags.decimal = flags->decimal;
253 if (flags->encoding != ENCODING_UNSPECIFIED)
254 u->flags.encoding = flags->encoding;
255 if (flags->async != ASYNC_UNSPECIFIED)
256 u->flags.async = flags->async;
257 if (flags->round != ROUND_UNSPECIFIED)
258 u->flags.round = flags->round;
259 if (flags->sign != SIGN_UNSPECIFIED)
260 u->flags.sign = flags->sign;
263 /* Reposition the file if necessary. */
265 switch (flags->position)
267 case POSITION_UNSPECIFIED:
268 case POSITION_ASIS:
269 break;
271 case POSITION_REWIND:
272 if (sseek (u->s, 0, SEEK_SET) != 0)
273 goto seek_error;
275 u->current_record = 0;
276 u->last_record = 0;
278 test_endfile (u);
279 break;
281 case POSITION_APPEND:
282 if (sseek (u->s, 0, SEEK_END) < 0)
283 goto seek_error;
285 if (flags->access != ACCESS_STREAM)
286 u->current_record = 0;
288 u->endfile = AT_ENDFILE; /* We are at the end. */
289 break;
291 seek_error:
292 generate_error (&opp->common, LIBERROR_OS, NULL);
293 break;
296 unlock_unit (u);
300 /* Open an unused unit. */
302 gfc_unit *
303 new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags * flags)
305 gfc_unit *u2;
306 stream *s;
307 char tmpname[5 /* fort. */ + 10 /* digits of unit number */ + 1 /* 0 */];
309 /* Change unspecifieds to defaults. Leave (flags->action ==
310 ACTION_UNSPECIFIED) alone so open_external() can set it based on
311 what type of open actually works. */
313 if (flags->access == ACCESS_UNSPECIFIED)
314 flags->access = ACCESS_SEQUENTIAL;
316 if (flags->form == FORM_UNSPECIFIED)
317 flags->form = (flags->access == ACCESS_SEQUENTIAL)
318 ? FORM_FORMATTED : FORM_UNFORMATTED;
320 if (flags->async == ASYNC_UNSPECIFIED)
321 flags->async = ASYNC_NO;
323 if (flags->status == STATUS_UNSPECIFIED)
324 flags->status = STATUS_UNKNOWN;
326 /* Checks. */
328 if (flags->delim == DELIM_UNSPECIFIED)
329 flags->delim = DELIM_NONE;
330 else
332 if (flags->form == FORM_UNFORMATTED)
334 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
335 "DELIM parameter conflicts with UNFORMATTED form in "
336 "OPEN statement");
337 goto fail;
341 if (flags->blank == BLANK_UNSPECIFIED)
342 flags->blank = BLANK_NULL;
343 else
345 if (flags->form == FORM_UNFORMATTED)
347 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
348 "BLANK parameter conflicts with UNFORMATTED form in "
349 "OPEN statement");
350 goto fail;
354 if (flags->pad == PAD_UNSPECIFIED)
355 flags->pad = PAD_YES;
356 else
358 if (flags->form == FORM_UNFORMATTED)
360 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
361 "PAD parameter conflicts with UNFORMATTED form in "
362 "OPEN statement");
363 goto fail;
367 if (flags->decimal == DECIMAL_UNSPECIFIED)
368 flags->decimal = DECIMAL_POINT;
369 else
371 if (flags->form == FORM_UNFORMATTED)
373 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
374 "DECIMAL parameter conflicts with UNFORMATTED form "
375 "in OPEN statement");
376 goto fail;
380 if (flags->encoding == ENCODING_UNSPECIFIED)
381 flags->encoding = ENCODING_DEFAULT;
382 else
384 if (flags->form == FORM_UNFORMATTED)
386 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
387 "ENCODING parameter conflicts with UNFORMATTED form in "
388 "OPEN statement");
389 goto fail;
393 /* NB: the value for ROUND when it's not specified by the user does not
394 have to be PROCESSOR_DEFINED; the standard says that it is
395 processor dependent, and requires that it is one of the
396 possible value (see F2003, 9.4.5.13). */
397 if (flags->round == ROUND_UNSPECIFIED)
398 flags->round = ROUND_PROCDEFINED;
399 else
401 if (flags->form == FORM_UNFORMATTED)
403 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
404 "ROUND parameter conflicts with UNFORMATTED form in "
405 "OPEN statement");
406 goto fail;
410 if (flags->sign == SIGN_UNSPECIFIED)
411 flags->sign = SIGN_PROCDEFINED;
412 else
414 if (flags->form == FORM_UNFORMATTED)
416 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
417 "SIGN parameter conflicts with UNFORMATTED form in "
418 "OPEN statement");
419 goto fail;
423 if (flags->position != POSITION_ASIS && flags->access == ACCESS_DIRECT)
425 generate_error (&opp->common, LIBERROR_OPTION_CONFLICT,
426 "ACCESS parameter conflicts with SEQUENTIAL access in "
427 "OPEN statement");
428 goto fail;
430 else
431 if (flags->position == POSITION_UNSPECIFIED)
432 flags->position = POSITION_ASIS;
434 if (flags->access == ACCESS_DIRECT
435 && (opp->common.flags & IOPARM_OPEN_HAS_RECL_IN) == 0)
437 generate_error (&opp->common, LIBERROR_MISSING_OPTION,
438 "Missing RECL parameter in OPEN statement");
439 goto fail;
442 if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN) && opp->recl_in <= 0)
444 generate_error (&opp->common, LIBERROR_BAD_OPTION,
445 "RECL parameter is non-positive in OPEN statement");
446 goto fail;
449 switch (flags->status)
451 case STATUS_SCRATCH:
452 if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) == 0)
454 opp->file = NULL;
455 break;
458 generate_error (&opp->common, LIBERROR_BAD_OPTION,
459 "FILE parameter must not be present in OPEN statement");
460 goto fail;
462 case STATUS_OLD:
463 case STATUS_NEW:
464 case STATUS_REPLACE:
465 case STATUS_UNKNOWN:
466 if ((opp->common.flags & IOPARM_OPEN_HAS_FILE))
467 break;
469 opp->file = tmpname;
470 #ifdef HAVE_SNPRINTF
471 opp->file_len = snprintf(opp->file, sizeof (tmpname), "fort.%d",
472 (int) opp->common.unit);
473 #else
474 opp->file_len = sprintf(opp->file, "fort.%d", (int) opp->common.unit);
475 #endif
476 break;
478 default:
479 internal_error (&opp->common, "new_unit(): Bad status");
482 /* Make sure the file isn't already open someplace else.
483 Do not error if opening file preconnected to stdin, stdout, stderr. */
485 u2 = NULL;
486 if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) != 0)
487 u2 = find_file (opp->file, opp->file_len);
488 if (u2 != NULL
489 && (options.stdin_unit < 0 || u2->unit_number != options.stdin_unit)
490 && (options.stdout_unit < 0 || u2->unit_number != options.stdout_unit)
491 && (options.stderr_unit < 0 || u2->unit_number != options.stderr_unit))
493 unlock_unit (u2);
494 generate_error (&opp->common, LIBERROR_ALREADY_OPEN, NULL);
495 goto cleanup;
498 if (u2 != NULL)
499 unlock_unit (u2);
501 /* Open file. */
503 s = open_external (opp, flags);
504 if (s == NULL)
506 char *path, *msg;
507 path = (char *) gfc_alloca (opp->file_len + 1);
508 msg = (char *) gfc_alloca (opp->file_len + 51);
509 unpack_filename (path, opp->file, opp->file_len);
511 switch (errno)
513 case ENOENT:
514 sprintf (msg, "File '%s' does not exist", path);
515 break;
517 case EEXIST:
518 sprintf (msg, "File '%s' already exists", path);
519 break;
521 case EACCES:
522 sprintf (msg, "Permission denied trying to open file '%s'", path);
523 break;
525 case EISDIR:
526 sprintf (msg, "'%s' is a directory", path);
527 break;
529 default:
530 msg = NULL;
533 generate_error (&opp->common, LIBERROR_OS, msg);
534 goto cleanup;
537 if (flags->status == STATUS_NEW || flags->status == STATUS_REPLACE)
538 flags->status = STATUS_OLD;
540 /* Create the unit structure. */
542 u->file = get_mem (opp->file_len);
543 if (u->unit_number != opp->common.unit)
544 internal_error (&opp->common, "Unit number changed");
545 u->s = s;
546 u->flags = *flags;
547 u->read_bad = 0;
548 u->endfile = NO_ENDFILE;
549 u->last_record = 0;
550 u->current_record = 0;
551 u->mode = READING;
552 u->maxrec = 0;
553 u->bytes_left = 0;
554 u->saved_pos = 0;
556 if (flags->position == POSITION_APPEND)
558 if (file_size (opp->file, opp->file_len) > 0 && sseek (u->s, 0, SEEK_END) < 0)
559 generate_error (&opp->common, LIBERROR_OS, NULL);
560 u->endfile = AT_ENDFILE;
563 /* Unspecified recl ends up with a processor dependent value. */
565 if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN))
567 u->flags.has_recl = 1;
568 u->recl = opp->recl_in;
569 u->recl_subrecord = u->recl;
570 u->bytes_left = u->recl;
572 else
574 u->flags.has_recl = 0;
575 u->recl = max_offset;
576 if (compile_options.max_subrecord_length)
578 u->recl_subrecord = compile_options.max_subrecord_length;
580 else
582 switch (compile_options.record_marker)
584 case 0:
585 /* Fall through */
586 case sizeof (GFC_INTEGER_4):
587 u->recl_subrecord = GFC_MAX_SUBRECORD_LENGTH;
588 break;
590 case sizeof (GFC_INTEGER_8):
591 u->recl_subrecord = max_offset - 16;
592 break;
594 default:
595 runtime_error ("Illegal value for record marker");
596 break;
601 /* If the file is direct access, calculate the maximum record number
602 via a division now instead of letting the multiplication overflow
603 later. */
605 if (flags->access == ACCESS_DIRECT)
606 u->maxrec = max_offset / u->recl;
608 if (flags->access == ACCESS_STREAM)
610 u->maxrec = max_offset;
611 u->recl = 1;
612 u->bytes_left = 1;
613 u->strm_pos = stell (u->s) + 1;
616 memmove (u->file, opp->file, opp->file_len);
617 u->file_len = opp->file_len;
619 /* Curiously, the standard requires that the
620 position specifier be ignored for new files so a newly connected
621 file starts out at the initial point. We still need to figure
622 out if the file is at the end or not. */
624 test_endfile (u);
626 if (flags->status == STATUS_SCRATCH && opp->file != NULL)
627 free (opp->file);
629 if (flags->form == FORM_FORMATTED)
631 if ((opp->common.flags & IOPARM_OPEN_HAS_RECL_IN))
632 fbuf_init (u, u->recl);
633 else
634 fbuf_init (u, 0);
636 else
637 u->fbuf = NULL;
641 return u;
643 cleanup:
645 /* Free memory associated with a temporary filename. */
647 if (flags->status == STATUS_SCRATCH && opp->file != NULL)
648 free (opp->file);
650 fail:
652 close_unit (u);
653 return NULL;
657 /* Open a unit which is already open. This involves changing the
658 modes or closing what is there now and opening the new file. */
660 static void
661 already_open (st_parameter_open *opp, gfc_unit * u, unit_flags * flags)
663 if ((opp->common.flags & IOPARM_OPEN_HAS_FILE) == 0)
665 edit_modes (opp, u, flags);
666 return;
669 /* If the file is connected to something else, close it and open a
670 new unit. */
672 if (!compare_file_filename (u, opp->file, opp->file_len))
674 #if !HAVE_UNLINK_OPEN_FILE
675 char *path = NULL;
676 if (u->file && u->flags.status == STATUS_SCRATCH)
678 path = (char *) gfc_alloca (u->file_len + 1);
679 unpack_filename (path, u->file, u->file_len);
681 #endif
683 if (sclose (u->s) == -1)
685 unlock_unit (u);
686 generate_error (&opp->common, LIBERROR_OS,
687 "Error closing file in OPEN statement");
688 return;
691 u->s = NULL;
692 if (u->file)
693 free (u->file);
694 u->file = NULL;
695 u->file_len = 0;
697 #if !HAVE_UNLINK_OPEN_FILE
698 if (path != NULL)
699 unlink (path);
700 #endif
702 u = new_unit (opp, u, flags);
703 if (u != NULL)
704 unlock_unit (u);
705 return;
708 edit_modes (opp, u, flags);
712 /* Open file. */
714 extern void st_open (st_parameter_open *opp);
715 export_proto(st_open);
717 void
718 st_open (st_parameter_open *opp)
720 unit_flags flags;
721 gfc_unit *u = NULL;
722 GFC_INTEGER_4 cf = opp->common.flags;
723 unit_convert conv;
725 library_start (&opp->common);
727 /* Decode options. */
729 flags.access = !(cf & IOPARM_OPEN_HAS_ACCESS) ? ACCESS_UNSPECIFIED :
730 find_option (&opp->common, opp->access, opp->access_len,
731 access_opt, "Bad ACCESS parameter in OPEN statement");
733 flags.action = !(cf & IOPARM_OPEN_HAS_ACTION) ? ACTION_UNSPECIFIED :
734 find_option (&opp->common, opp->action, opp->action_len,
735 action_opt, "Bad ACTION parameter in OPEN statement");
737 flags.blank = !(cf & IOPARM_OPEN_HAS_BLANK) ? BLANK_UNSPECIFIED :
738 find_option (&opp->common, opp->blank, opp->blank_len,
739 blank_opt, "Bad BLANK parameter in OPEN statement");
741 flags.delim = !(cf & IOPARM_OPEN_HAS_DELIM) ? DELIM_UNSPECIFIED :
742 find_option (&opp->common, opp->delim, opp->delim_len,
743 delim_opt, "Bad DELIM parameter in OPEN statement");
745 flags.pad = !(cf & IOPARM_OPEN_HAS_PAD) ? PAD_UNSPECIFIED :
746 find_option (&opp->common, opp->pad, opp->pad_len,
747 pad_opt, "Bad PAD parameter in OPEN statement");
749 flags.decimal = !(cf & IOPARM_OPEN_HAS_DECIMAL) ? DECIMAL_UNSPECIFIED :
750 find_option (&opp->common, opp->decimal, opp->decimal_len,
751 decimal_opt, "Bad DECIMAL parameter in OPEN statement");
753 flags.encoding = !(cf & IOPARM_OPEN_HAS_ENCODING) ? ENCODING_UNSPECIFIED :
754 find_option (&opp->common, opp->encoding, opp->encoding_len,
755 encoding_opt, "Bad ENCODING parameter in OPEN statement");
757 flags.async = !(cf & IOPARM_OPEN_HAS_ASYNCHRONOUS) ? ASYNC_UNSPECIFIED :
758 find_option (&opp->common, opp->asynchronous, opp->asynchronous_len,
759 async_opt, "Bad ASYNCHRONOUS parameter in OPEN statement");
761 flags.round = !(cf & IOPARM_OPEN_HAS_ROUND) ? ROUND_UNSPECIFIED :
762 find_option (&opp->common, opp->round, opp->round_len,
763 round_opt, "Bad ROUND parameter in OPEN statement");
765 flags.sign = !(cf & IOPARM_OPEN_HAS_SIGN) ? SIGN_UNSPECIFIED :
766 find_option (&opp->common, opp->sign, opp->sign_len,
767 sign_opt, "Bad SIGN parameter in OPEN statement");
769 flags.form = !(cf & IOPARM_OPEN_HAS_FORM) ? FORM_UNSPECIFIED :
770 find_option (&opp->common, opp->form, opp->form_len,
771 form_opt, "Bad FORM parameter in OPEN statement");
773 flags.position = !(cf & IOPARM_OPEN_HAS_POSITION) ? POSITION_UNSPECIFIED :
774 find_option (&opp->common, opp->position, opp->position_len,
775 position_opt, "Bad POSITION parameter in OPEN statement");
777 flags.status = !(cf & IOPARM_OPEN_HAS_STATUS) ? STATUS_UNSPECIFIED :
778 find_option (&opp->common, opp->status, opp->status_len,
779 status_opt, "Bad STATUS parameter in OPEN statement");
781 /* First, we check wether the convert flag has been set via environment
782 variable. This overrides the convert tag in the open statement. */
784 conv = get_unformatted_convert (opp->common.unit);
786 if (conv == GFC_CONVERT_NONE)
788 /* Nothing has been set by environment variable, check the convert tag. */
789 if (cf & IOPARM_OPEN_HAS_CONVERT)
790 conv = find_option (&opp->common, opp->convert, opp->convert_len,
791 convert_opt,
792 "Bad CONVERT parameter in OPEN statement");
793 else
794 conv = compile_options.convert;
797 /* We use big_endian, which is 0 on little-endian machines
798 and 1 on big-endian machines. */
799 switch (conv)
801 case GFC_CONVERT_NATIVE:
802 case GFC_CONVERT_SWAP:
803 break;
805 case GFC_CONVERT_BIG:
806 conv = big_endian ? GFC_CONVERT_NATIVE : GFC_CONVERT_SWAP;
807 break;
809 case GFC_CONVERT_LITTLE:
810 conv = big_endian ? GFC_CONVERT_SWAP : GFC_CONVERT_NATIVE;
811 break;
813 default:
814 internal_error (&opp->common, "Illegal value for CONVERT");
815 break;
818 flags.convert = conv;
820 if (!(opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT) && opp->common.unit < 0)
821 generate_error (&opp->common, LIBERROR_BAD_OPTION,
822 "Bad unit number in OPEN statement");
824 if (flags.position != POSITION_UNSPECIFIED
825 && flags.access == ACCESS_DIRECT)
826 generate_error (&opp->common, LIBERROR_BAD_OPTION,
827 "Cannot use POSITION with direct access files");
829 if (flags.access == ACCESS_APPEND)
831 if (flags.position != POSITION_UNSPECIFIED
832 && flags.position != POSITION_APPEND)
833 generate_error (&opp->common, LIBERROR_BAD_OPTION,
834 "Conflicting ACCESS and POSITION flags in"
835 " OPEN statement");
837 notify_std (&opp->common, GFC_STD_GNU,
838 "Extension: APPEND as a value for ACCESS in OPEN statement");
839 flags.access = ACCESS_SEQUENTIAL;
840 flags.position = POSITION_APPEND;
843 if (flags.position == POSITION_UNSPECIFIED)
844 flags.position = POSITION_ASIS;
846 if ((opp->common.flags & IOPARM_LIBRETURN_MASK) == IOPARM_LIBRETURN_OK)
848 if ((opp->common.flags & IOPARM_OPEN_HAS_NEWUNIT))
850 *opp->newunit = get_unique_unit_number(opp);
851 opp->common.unit = *opp->newunit;
854 u = find_or_create_unit (opp->common.unit);
855 if (u->s == NULL)
857 u = new_unit (opp, u, &flags);
858 if (u != NULL)
859 unlock_unit (u);
861 else
862 already_open (opp, u, &flags);
865 library_end ();