2 /* Copyright (C) 2002-2003 Free Software Foundation, Inc.
3 Contributed by Andy Vaught
5 This file is part of the GNU Fortran 95 runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Libgfortran; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
26 #include "libgfortran.h"
30 static st_option access_opt
[] = {
31 {"sequential", ACCESS_SEQUENTIAL
},
32 {"direct", ACCESS_DIRECT
},
40 "write", ACTION_WRITE
}
43 "readwrite", ACTION_READWRITE
}
67 "apostrophe", DELIM_APOSTROPHE
}
79 "formatted", FORM_FORMATTED
}
82 "unformatted", FORM_UNFORMATTED
}
91 "asis", POSITION_ASIS
}
94 "rewind", POSITION_REWIND
}
97 "append", POSITION_APPEND
}
106 "unknown", STATUS_UNKNOWN
}
115 "replace", STATUS_REPLACE
}
118 "scratch", STATUS_SCRATCH
}
137 /* test_endfile()-- Given a unit, test to see if the file is
138 * positioned at the terminal point, and if so, change state from
139 * NO_ENDFILE flag to AT_ENDFILE. This prevents us from changing the
140 * state from AFTER_ENDFILE to AT_ENDFILE. */
143 test_endfile (gfc_unit
* u
)
146 if (u
->endfile
== NO_ENDFILE
&& file_length (u
->s
) == file_position (u
->s
))
147 u
->endfile
= AT_ENDFILE
;
151 /* edit_modes()-- Change the modes of a file, those that are allowed
155 edit_modes (gfc_unit
* u
, unit_flags
* flags
)
158 /* Complain about attempts to change the unchangeable */
160 if (flags
->status
!= STATUS_UNSPECIFIED
&&
161 u
->flags
.status
!= flags
->position
)
162 generate_error (ERROR_BAD_OPTION
,
163 "Cannot change STATUS parameter in OPEN statement");
165 if (flags
->access
!= ACCESS_UNSPECIFIED
&& u
->flags
.access
!= flags
->access
)
166 generate_error (ERROR_BAD_OPTION
,
167 "Cannot change ACCESS parameter in OPEN statement");
169 if (flags
->form
!= FORM_UNSPECIFIED
&& u
->flags
.form
!= flags
->form
)
170 generate_error (ERROR_BAD_OPTION
,
171 "Cannot change FORM parameter in OPEN statement");
173 if (ioparm
.recl_in
!= 0 && ioparm
.recl_in
!= u
->recl
)
174 generate_error (ERROR_BAD_OPTION
,
175 "Cannot change RECL parameter in OPEN statement");
177 if (flags
->action
!= ACTION_UNSPECIFIED
&& u
->flags
.access
!= flags
->access
)
178 generate_error (ERROR_BAD_OPTION
,
179 "Cannot change ACTION parameter in OPEN statement");
181 /* Status must be OLD if present */
183 if (flags
->status
!= STATUS_UNSPECIFIED
&& flags
->status
!= STATUS_OLD
)
184 generate_error (ERROR_BAD_OPTION
,
185 "OPEN statement must have a STATUS of OLD");
187 if (u
->flags
.form
== FORM_UNFORMATTED
)
189 if (flags
->delim
!= DELIM_UNSPECIFIED
)
190 generate_error (ERROR_OPTION_CONFLICT
,
191 "DELIM parameter conflicts with UNFORMATTED form in "
194 if (flags
->blank
!= BLANK_UNSPECIFIED
)
195 generate_error (ERROR_OPTION_CONFLICT
,
196 "BLANK parameter conflicts with UNFORMATTED form in "
199 if (flags
->pad
!= PAD_UNSPECIFIED
)
200 generate_error (ERROR_OPTION_CONFLICT
,
201 "PAD paramter conflicts with UNFORMATTED form in "
205 if (ioparm
.library_return
== LIBRARY_OK
)
206 { /* Change the changeable */
207 if (flags
->blank
!= BLANK_UNSPECIFIED
)
208 u
->flags
.blank
= flags
->blank
;
209 if (flags
->delim
!= DELIM_UNSPECIFIED
)
210 u
->flags
.delim
= flags
->delim
;
211 if (flags
->pad
!= PAD_UNSPECIFIED
)
212 u
->flags
.pad
= flags
->pad
;
215 /* Reposition the file if necessary. */
217 switch (flags
->position
)
219 case POSITION_UNSPECIFIED
:
223 case POSITION_REWIND
:
224 if (sseek (u
->s
, 0) == FAILURE
)
227 u
->current_record
= 0;
230 test_endfile (u
); /* We might be at the end */
233 case POSITION_APPEND
:
234 if (sseek (u
->s
, file_length (u
->s
)) == FAILURE
)
237 u
->current_record
= 0;
238 u
->endfile
= AT_ENDFILE
; /* We are at the end */
242 generate_error (ERROR_OS
, NULL
);
248 /* new_unit()-- Open an unused unit */
251 new_unit (unit_flags
* flags
)
255 char tmpname
[5 /* fort. */ + 10 /* digits of unit number */ + 1 /* 0 */];
257 /* Change unspecifieds to defaults */
259 if (flags
->access
== ACCESS_UNSPECIFIED
)
260 flags
->access
= ACCESS_SEQUENTIAL
;
262 if (flags
->action
== ACTION_UNSPECIFIED
)
263 flags
->action
= ACTION_READWRITE
; /* Processor dependent */
265 if (flags
->form
== FORM_UNSPECIFIED
)
266 flags
->form
= (flags
->access
== ACCESS_SEQUENTIAL
)
267 ? FORM_FORMATTED
: FORM_UNFORMATTED
;
270 if (flags
->delim
== DELIM_UNSPECIFIED
)
271 flags
->delim
= DELIM_NONE
;
274 if (flags
->form
== FORM_UNFORMATTED
)
276 generate_error (ERROR_OPTION_CONFLICT
,
277 "DELIM parameter conflicts with UNFORMATTED form in "
283 if (flags
->blank
== BLANK_UNSPECIFIED
)
284 flags
->blank
= BLANK_NULL
;
287 if (flags
->form
== FORM_UNFORMATTED
)
289 generate_error (ERROR_OPTION_CONFLICT
,
290 "BLANK parameter conflicts with UNFORMATTED form in "
296 if (flags
->pad
== PAD_UNSPECIFIED
)
297 flags
->pad
= PAD_YES
;
300 if (flags
->form
== FORM_UNFORMATTED
)
302 generate_error (ERROR_OPTION_CONFLICT
,
303 "PAD paramter conflicts with UNFORMATTED form in "
309 if (flags
->position
!= POSITION_ASIS
&& flags
->access
== ACCESS_DIRECT
)
311 generate_error (ERROR_OPTION_CONFLICT
,
312 "ACCESS parameter conflicts with SEQUENTIAL access in "
317 if (flags
->position
== POSITION_UNSPECIFIED
)
318 flags
->position
= POSITION_ASIS
;
321 if (flags
->status
== STATUS_UNSPECIFIED
)
322 flags
->status
= STATUS_UNKNOWN
;
326 if (flags
->access
== ACCESS_DIRECT
&& ioparm
.recl_in
== 0)
328 generate_error (ERROR_MISSING_OPTION
,
329 "Missing RECL parameter in OPEN statement");
333 if (ioparm
.recl_in
!= 0 && ioparm
.recl_in
<= 0)
335 generate_error (ERROR_BAD_OPTION
,
336 "RECL parameter is non-positive in OPEN statement");
340 switch (flags
->status
)
343 if (ioparm
.file
== NULL
)
346 generate_error (ERROR_BAD_OPTION
,
347 "FILE parameter must not be present in OPEN statement");
354 if (ioparm
.file
!= NULL
)
357 ioparm
.file
= tmpname
;
358 ioparm
.file_len
= sprintf(ioparm
.file
, "fort.%d", ioparm
.unit
);
362 internal_error ("new_unit(): Bad status");
365 /* Make sure the file isn't already open someplace else */
367 if (find_file () != NULL
)
369 generate_error (ERROR_ALREADY_OPEN
, NULL
);
375 s
= open_external (flags
->action
, flags
->status
);
378 generate_error (ERROR_OS
, NULL
);
382 if (flags
->status
== STATUS_NEW
|| flags
->status
== STATUS_REPLACE
)
383 flags
->status
= STATUS_OLD
;
385 /* Create the unit structure */
387 u
= get_mem (sizeof (gfc_unit
) + ioparm
.file_len
);
389 u
->unit_number
= ioparm
.unit
;
393 /* Unspecified recl ends up with a processor dependent value */
395 u
->recl
= (ioparm
.recl_in
!= 0) ? ioparm
.recl_in
: DEFAULT_RECL
;
397 u
->current_record
= 0;
399 /* If the file is direct access, calculate the maximum record number
400 * via a division now instead of letting the multiplication overflow
403 if (flags
->access
== ACCESS_DIRECT
)
404 u
->maxrec
= g
.max_offset
/ u
->recl
;
406 memmove (u
->file
, ioparm
.file
, ioparm
.file_len
);
407 u
->file_len
= ioparm
.file_len
;
411 /* The file is now connected. Errors after this point leave the
412 * file connected. Curiously, the standard requires that the
413 * position specifier be ignored for new files so a newly connected
414 * file starts out that the initial point. We still need to figure
415 * out if the file is at the end or not. */
421 /* Free memory associated with a temporary filename */
423 if (flags
->status
== STATUS_SCRATCH
)
424 free_mem (ioparm
.file
);
428 /* already_open()-- Open a unit which is already open. This involves
429 * changing the modes or closing what is there now and opening the new
433 already_open (gfc_unit
* u
, unit_flags
* flags
)
436 if (ioparm
.file
== NULL
)
438 edit_modes (u
, flags
);
442 /* If the file is connected to something else, close it and open a
445 if (!compare_file_filename (u
->s
, ioparm
.file
, ioparm
.file_len
))
449 generate_error (ERROR_OS
, "Error closing file in OPEN statement");
457 edit_modes (u
, flags
);
474 flags
.access
= (ioparm
.access
== NULL
) ? ACCESS_UNSPECIFIED
:
475 find_option (ioparm
.access
, ioparm
.access_len
, access_opt
,
476 "Bad ACCESS parameter in OPEN statement");
478 flags
.action
= (ioparm
.action
== NULL
) ? ACTION_UNSPECIFIED
:
479 find_option (ioparm
.action
, ioparm
.action_len
, action_opt
,
480 "Bad ACTION parameter in OPEN statement");
482 flags
.blank
= (ioparm
.blank
== NULL
) ? BLANK_UNSPECIFIED
:
483 find_option (ioparm
.blank
, ioparm
.blank_len
, blank_opt
,
484 "Bad BLANK parameter in OPEN statement");
486 flags
.delim
= (ioparm
.delim
== NULL
) ? DELIM_UNSPECIFIED
:
487 find_option (ioparm
.delim
, ioparm
.delim_len
, delim_opt
,
488 "Bad DELIM parameter in OPEN statement");
490 flags
.pad
= (ioparm
.pad
== NULL
) ? PAD_UNSPECIFIED
:
491 find_option (ioparm
.pad
, ioparm
.pad_len
, pad_opt
,
492 "Bad PAD parameter in OPEN statement");
494 flags
.form
= (ioparm
.form
== NULL
) ? FORM_UNSPECIFIED
:
495 find_option (ioparm
.form
, ioparm
.form_len
, form_opt
,
496 "Bad FORM parameter in OPEN statement");
498 flags
.position
= (ioparm
.position
== NULL
) ? POSITION_UNSPECIFIED
:
499 find_option (ioparm
.position
, ioparm
.position_len
, position_opt
,
500 "Bad POSITION parameter in OPEN statement");
502 flags
.status
= (ioparm
.status
== NULL
) ? STATUS_UNSPECIFIED
:
503 find_option (ioparm
.status
, ioparm
.status_len
, status_opt
,
504 "Bad STATUS parameter in OPEN statement");
507 generate_error (ERROR_BAD_OPTION
, "Bad unit number in OPEN statement");
509 if (flags
.position
!= POSITION_UNSPECIFIED
510 && flags
.access
== ACCESS_DIRECT
)
511 generate_error (ERROR_BAD_OPTION
,
512 "Cannot use POSITION with direct access files");
514 if (flags
.position
== POSITION_UNSPECIFIED
)
515 flags
.position
= POSITION_ASIS
;
517 if (ioparm
.library_return
!= LIBRARY_OK
)
520 u
= find_unit (ioparm
.unit
);
525 already_open (u
, &flags
);