]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libgfortran/io/open.c
1 /* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
4 This file is part of the GNU Fortran 95 runtime library (libgfortran).
6 Libgfortran is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 In addition to the permissions in the GNU General Public License, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of this file into combinations with other programs,
14 and to distribute those combinations without any restriction coming
15 from the use of this file. (The General Public License restrictions
16 do apply in other respects; for example, they cover modification of
17 the file, and distribution when not linked into a combine
20 Libgfortran is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with Libgfortran; see the file COPYING. If not, write to
27 the Free Software Foundation, 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA. */
34 #include "libgfortran.h"
38 static st_option access_opt
[] = {
39 {"sequential", ACCESS_SEQUENTIAL
},
40 {"direct", ACCESS_DIRECT
},
44 static st_option action_opt
[] =
46 { "read", ACTION_READ
},
47 { "write", ACTION_WRITE
},
48 { "readwrite", ACTION_READWRITE
},
52 static st_option blank_opt
[] =
54 { "null", BLANK_NULL
},
55 { "zero", BLANK_ZERO
},
59 static st_option delim_opt
[] =
61 { "none", DELIM_NONE
},
62 { "apostrophe", DELIM_APOSTROPHE
},
63 { "quote", DELIM_QUOTE
},
67 static st_option form_opt
[] =
69 { "formatted", FORM_FORMATTED
},
70 { "unformatted", FORM_UNFORMATTED
},
74 static st_option position_opt
[] =
76 { "asis", POSITION_ASIS
},
77 { "rewind", POSITION_REWIND
},
78 { "append", POSITION_APPEND
},
82 static st_option status_opt
[] =
84 { "unknown", STATUS_UNKNOWN
},
87 { "replace", STATUS_REPLACE
},
88 { "scratch", STATUS_SCRATCH
},
92 static st_option pad_opt
[] =
100 /* Given a unit, test to see if the file is positioned at the terminal
101 point, and if so, change state from NO_ENDFILE flag to AT_ENDFILE.
102 This prevents us from changing the state from AFTER_ENDFILE to
106 test_endfile (gfc_unit
* u
)
108 if (u
->endfile
== NO_ENDFILE
&& file_length (u
->s
) == file_position (u
->s
))
109 u
->endfile
= AT_ENDFILE
;
113 /* Change the modes of a file, those that are allowed * to be
117 edit_modes (gfc_unit
* u
, unit_flags
* flags
)
119 /* Complain about attempts to change the unchangeable. */
121 if (flags
->status
!= STATUS_UNSPECIFIED
&&
122 u
->flags
.status
!= flags
->position
)
123 generate_error (ERROR_BAD_OPTION
,
124 "Cannot change STATUS parameter in OPEN statement");
126 if (flags
->access
!= ACCESS_UNSPECIFIED
&& u
->flags
.access
!= flags
->access
)
127 generate_error (ERROR_BAD_OPTION
,
128 "Cannot change ACCESS parameter in OPEN statement");
130 if (flags
->form
!= FORM_UNSPECIFIED
&& u
->flags
.form
!= flags
->form
)
131 generate_error (ERROR_BAD_OPTION
,
132 "Cannot change FORM parameter in OPEN statement");
134 if (ioparm
.recl_in
!= 0 && ioparm
.recl_in
!= u
->recl
)
135 generate_error (ERROR_BAD_OPTION
,
136 "Cannot change RECL parameter in OPEN statement");
138 if (flags
->action
!= ACTION_UNSPECIFIED
&& u
->flags
.access
!= flags
->access
)
139 generate_error (ERROR_BAD_OPTION
,
140 "Cannot change ACTION parameter in OPEN statement");
142 /* Status must be OLD if present. */
144 if (flags
->status
!= STATUS_UNSPECIFIED
&& flags
->status
!= STATUS_OLD
)
145 generate_error (ERROR_BAD_OPTION
,
146 "OPEN statement must have a STATUS of OLD");
148 if (u
->flags
.form
== FORM_UNFORMATTED
)
150 if (flags
->delim
!= DELIM_UNSPECIFIED
)
151 generate_error (ERROR_OPTION_CONFLICT
,
152 "DELIM parameter conflicts with UNFORMATTED form in "
155 if (flags
->blank
!= BLANK_UNSPECIFIED
)
156 generate_error (ERROR_OPTION_CONFLICT
,
157 "BLANK parameter conflicts with UNFORMATTED form in "
160 if (flags
->pad
!= PAD_UNSPECIFIED
)
161 generate_error (ERROR_OPTION_CONFLICT
,
162 "PAD paramter conflicts with UNFORMATTED form in "
166 if (ioparm
.library_return
== LIBRARY_OK
)
168 /* Change the changeable: */
169 if (flags
->blank
!= BLANK_UNSPECIFIED
)
170 u
->flags
.blank
= flags
->blank
;
171 if (flags
->delim
!= DELIM_UNSPECIFIED
)
172 u
->flags
.delim
= flags
->delim
;
173 if (flags
->pad
!= PAD_UNSPECIFIED
)
174 u
->flags
.pad
= flags
->pad
;
177 /* Reposition the file if necessary. */
179 switch (flags
->position
)
181 case POSITION_UNSPECIFIED
:
185 case POSITION_REWIND
:
186 if (sseek (u
->s
, 0) == FAILURE
)
189 u
->current_record
= 0;
192 test_endfile (u
); /* We might be at the end. */
195 case POSITION_APPEND
:
196 if (sseek (u
->s
, file_length (u
->s
)) == FAILURE
)
199 u
->current_record
= 0;
200 u
->endfile
= AT_ENDFILE
; /* We are at the end. */
204 generate_error (ERROR_OS
, NULL
);
210 /* Open an unused unit. */
213 new_unit (unit_flags
* flags
)
217 char tmpname
[5 /* fort. */ + 10 /* digits of unit number */ + 1 /* 0 */];
219 /* Change unspecifieds to defaults. Leave (flags->action ==
220 ACTION_UNSPECIFIED) alone so open_external() can set it based on
221 what type of open actually works. */
223 if (flags
->access
== ACCESS_UNSPECIFIED
)
224 flags
->access
= ACCESS_SEQUENTIAL
;
226 if (flags
->form
== FORM_UNSPECIFIED
)
227 flags
->form
= (flags
->access
== ACCESS_SEQUENTIAL
)
228 ? FORM_FORMATTED
: FORM_UNFORMATTED
;
231 if (flags
->delim
== DELIM_UNSPECIFIED
)
232 flags
->delim
= DELIM_NONE
;
235 if (flags
->form
== FORM_UNFORMATTED
)
237 generate_error (ERROR_OPTION_CONFLICT
,
238 "DELIM parameter conflicts with UNFORMATTED form in "
244 if (flags
->blank
== BLANK_UNSPECIFIED
)
245 flags
->blank
= BLANK_NULL
;
248 if (flags
->form
== FORM_UNFORMATTED
)
250 generate_error (ERROR_OPTION_CONFLICT
,
251 "BLANK parameter conflicts with UNFORMATTED form in "
257 if (flags
->pad
== PAD_UNSPECIFIED
)
258 flags
->pad
= PAD_YES
;
261 if (flags
->form
== FORM_UNFORMATTED
)
263 generate_error (ERROR_OPTION_CONFLICT
,
264 "PAD paramter conflicts with UNFORMATTED form in "
270 if (flags
->position
!= POSITION_ASIS
&& flags
->access
== ACCESS_DIRECT
)
272 generate_error (ERROR_OPTION_CONFLICT
,
273 "ACCESS parameter conflicts with SEQUENTIAL access in "
278 if (flags
->position
== POSITION_UNSPECIFIED
)
279 flags
->position
= POSITION_ASIS
;
282 if (flags
->status
== STATUS_UNSPECIFIED
)
283 flags
->status
= STATUS_UNKNOWN
;
287 if (flags
->access
== ACCESS_DIRECT
&& ioparm
.recl_in
== 0)
289 generate_error (ERROR_MISSING_OPTION
,
290 "Missing RECL parameter in OPEN statement");
294 if (ioparm
.recl_in
!= 0 && ioparm
.recl_in
<= 0)
296 generate_error (ERROR_BAD_OPTION
,
297 "RECL parameter is non-positive in OPEN statement");
301 switch (flags
->status
)
304 if (ioparm
.file
== NULL
)
307 generate_error (ERROR_BAD_OPTION
,
308 "FILE parameter must not be present in OPEN statement");
315 if (ioparm
.file
!= NULL
)
318 ioparm
.file
= tmpname
;
319 ioparm
.file_len
= sprintf(ioparm
.file
, "fort.%d", ioparm
.unit
);
323 internal_error ("new_unit(): Bad status");
326 /* Make sure the file isn't already open someplace else. */
328 if (find_file () != NULL
)
330 generate_error (ERROR_ALREADY_OPEN
, NULL
);
336 s
= open_external (flags
);
339 generate_error (ERROR_OS
, NULL
);
343 if (flags
->status
== STATUS_NEW
|| flags
->status
== STATUS_REPLACE
)
344 flags
->status
= STATUS_OLD
;
346 /* Create the unit structure. */
348 u
= get_mem (sizeof (gfc_unit
) + ioparm
.file_len
);
350 u
->unit_number
= ioparm
.unit
;
354 /* Unspecified recl ends up with a processor dependent value. */
356 u
->recl
= (ioparm
.recl_in
!= 0) ? ioparm
.recl_in
: DEFAULT_RECL
;
358 u
->current_record
= 0;
360 /* If the file is direct access, calculate the maximum record number
361 via a division now instead of letting the multiplication overflow
364 if (flags
->access
== ACCESS_DIRECT
)
365 u
->maxrec
= g
.max_offset
/ u
->recl
;
367 memmove (u
->file
, ioparm
.file
, ioparm
.file_len
);
368 u
->file_len
= ioparm
.file_len
;
372 /* The file is now connected. Errors after this point leave the
373 file connected. Curiously, the standard requires that the
374 position specifier be ignored for new files so a newly connected
375 file starts out that the initial point. We still need to figure
376 out if the file is at the end or not. */
382 /* Free memory associated with a temporary filename. */
384 if (flags
->status
== STATUS_SCRATCH
)
385 free_mem (ioparm
.file
);
389 /* Open a unit which is already open. This involves changing the
390 modes or closing what is there now and opening the new file. */
393 already_open (gfc_unit
* u
, unit_flags
* flags
)
395 if (ioparm
.file
== NULL
)
397 edit_modes (u
, flags
);
401 /* If the file is connected to something else, close it and open a
404 if (!compare_file_filename (u
->s
, ioparm
.file
, ioparm
.file_len
))
408 generate_error (ERROR_OS
, "Error closing file in OPEN statement");
416 edit_modes (u
, flags
);
422 extern void st_open (void);
423 export_proto(st_open
);
433 /* Decode options. */
435 flags
.access
= (ioparm
.access
== NULL
) ? ACCESS_UNSPECIFIED
:
436 find_option (ioparm
.access
, ioparm
.access_len
, access_opt
,
437 "Bad ACCESS parameter in OPEN statement");
439 flags
.action
= (ioparm
.action
== NULL
) ? ACTION_UNSPECIFIED
:
440 find_option (ioparm
.action
, ioparm
.action_len
, action_opt
,
441 "Bad ACTION parameter in OPEN statement");
443 flags
.blank
= (ioparm
.blank
== NULL
) ? BLANK_UNSPECIFIED
:
444 find_option (ioparm
.blank
, ioparm
.blank_len
, blank_opt
,
445 "Bad BLANK parameter in OPEN statement");
447 flags
.delim
= (ioparm
.delim
== NULL
) ? DELIM_UNSPECIFIED
:
448 find_option (ioparm
.delim
, ioparm
.delim_len
, delim_opt
,
449 "Bad DELIM parameter in OPEN statement");
451 flags
.pad
= (ioparm
.pad
== NULL
) ? PAD_UNSPECIFIED
:
452 find_option (ioparm
.pad
, ioparm
.pad_len
, pad_opt
,
453 "Bad PAD parameter in OPEN statement");
455 flags
.form
= (ioparm
.form
== NULL
) ? FORM_UNSPECIFIED
:
456 find_option (ioparm
.form
, ioparm
.form_len
, form_opt
,
457 "Bad FORM parameter in OPEN statement");
459 flags
.position
= (ioparm
.position
== NULL
) ? POSITION_UNSPECIFIED
:
460 find_option (ioparm
.position
, ioparm
.position_len
, position_opt
,
461 "Bad POSITION parameter in OPEN statement");
463 flags
.status
= (ioparm
.status
== NULL
) ? STATUS_UNSPECIFIED
:
464 find_option (ioparm
.status
, ioparm
.status_len
, status_opt
,
465 "Bad STATUS parameter in OPEN statement");
468 generate_error (ERROR_BAD_OPTION
, "Bad unit number in OPEN statement");
470 if (flags
.position
!= POSITION_UNSPECIFIED
471 && flags
.access
== ACCESS_DIRECT
)
472 generate_error (ERROR_BAD_OPTION
,
473 "Cannot use POSITION with direct access files");
475 if (flags
.position
== POSITION_UNSPECIFIED
)
476 flags
.position
= POSITION_ASIS
;
478 if (ioparm
.library_return
!= LIBRARY_OK
)
481 u
= find_unit (ioparm
.unit
);
486 already_open (u
, &flags
);