1 /* Copyright (C) 2002-2018 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
4 This file is part of the GNU Fortran 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 3, or (at your option)
11 Libgfortran is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
26 /* Implement the non-IOLENGTH variant of the INQUIRY statement */
34 static const char yes
[] = "YES", no
[] = "NO", undefined
[] = "UNDEFINED";
37 /* inquire_via_unit()-- Inquiry via unit number. The unit might not exist. */
40 inquire_via_unit (st_parameter_inquire
*iqp
, gfc_unit
*u
)
43 GFC_INTEGER_4 cf
= iqp
->common
.flags
;
45 if (iqp
->common
.unit
== GFC_INTERNAL_UNIT
||
46 iqp
->common
.unit
== GFC_INTERNAL_UNIT4
||
47 (u
!= NULL
&& u
->internal_unit_kind
!= 0))
48 generate_error (&iqp
->common
, LIBERROR_INQUIRE_INTERNAL_UNIT
, NULL
);
50 if ((cf
& IOPARM_INQUIRE_HAS_EXIST
) != 0)
51 *iqp
->exist
= (u
!= NULL
&&
52 iqp
->common
.unit
!= GFC_INTERNAL_UNIT
&&
53 iqp
->common
.unit
!= GFC_INTERNAL_UNIT4
)
54 || (iqp
->common
.unit
>= 0);
56 if ((cf
& IOPARM_INQUIRE_HAS_OPENED
) != 0)
57 *iqp
->opened
= (u
!= NULL
);
59 if ((cf
& IOPARM_INQUIRE_HAS_NUMBER
) != 0)
60 *iqp
->number
= (u
!= NULL
) ? u
->unit_number
: -1;
62 if ((cf
& IOPARM_INQUIRE_HAS_NAMED
) != 0)
63 *iqp
->named
= (u
!= NULL
&& u
->flags
.status
!= STATUS_SCRATCH
);
65 if ((cf
& IOPARM_INQUIRE_HAS_NAME
) != 0
66 && u
!= NULL
&& u
->flags
.status
!= STATUS_SCRATCH
)
68 #if defined(HAVE_TTYNAME_R) || defined(HAVE_TTYNAME)
69 if (u
->unit_number
== options
.stdin_unit
70 || u
->unit_number
== options
.stdout_unit
71 || u
->unit_number
== options
.stderr_unit
)
73 int err
= stream_ttyname (u
->s
, iqp
->name
, iqp
->name_len
);
76 gfc_charlen_type tmplen
= strlen (iqp
->name
);
77 if (iqp
->name_len
> tmplen
)
78 memset (&iqp
->name
[tmplen
], ' ', iqp
->name_len
- tmplen
);
80 else /* If ttyname does not work, go with the default. */
81 cf_strcpy (iqp
->name
, iqp
->name_len
, u
->filename
);
84 cf_strcpy (iqp
->name
, iqp
->name_len
, u
->filename
);
85 #elif defined __MINGW32__
86 if (u
->unit_number
== options
.stdin_unit
)
87 fstrcpy (iqp
->name
, iqp
->name_len
, "CONIN$", sizeof("CONIN$"));
88 else if (u
->unit_number
== options
.stdout_unit
)
89 fstrcpy (iqp
->name
, iqp
->name_len
, "CONOUT$", sizeof("CONOUT$"));
90 else if (u
->unit_number
== options
.stderr_unit
)
91 fstrcpy (iqp
->name
, iqp
->name_len
, "CONERR$", sizeof("CONERR$"));
93 cf_strcpy (iqp
->name
, iqp
->name_len
, u
->filename
);
95 cf_strcpy (iqp
->name
, iqp
->name_len
, u
->filename
);
99 if ((cf
& IOPARM_INQUIRE_HAS_ACCESS
) != 0)
104 switch (u
->flags
.access
)
106 case ACCESS_SEQUENTIAL
:
116 internal_error (&iqp
->common
, "inquire_via_unit(): Bad access");
119 cf_strcpy (iqp
->access
, iqp
->access_len
, p
);
122 if ((cf
& IOPARM_INQUIRE_HAS_SEQUENTIAL
) != 0)
125 p
= inquire_sequential (NULL
, 0);
127 switch (u
->flags
.access
)
133 case ACCESS_SEQUENTIAL
:
137 internal_error (&iqp
->common
, "inquire_via_unit(): Bad access");
140 cf_strcpy (iqp
->sequential
, iqp
->sequential_len
, p
);
143 if ((cf
& IOPARM_INQUIRE_HAS_DIRECT
) != 0)
146 p
= inquire_direct (NULL
, 0);
148 switch (u
->flags
.access
)
150 case ACCESS_SEQUENTIAL
:
158 internal_error (&iqp
->common
, "inquire_via_unit(): Bad access");
161 cf_strcpy (iqp
->direct
, iqp
->direct_len
, p
);
164 if ((cf
& IOPARM_INQUIRE_HAS_FORM
) != 0)
169 switch (u
->flags
.form
)
174 case FORM_UNFORMATTED
:
178 internal_error (&iqp
->common
, "inquire_via_unit(): Bad form");
181 cf_strcpy (iqp
->form
, iqp
->form_len
, p
);
184 if ((cf
& IOPARM_INQUIRE_HAS_FORMATTED
) != 0)
187 p
= inquire_formatted (NULL
, 0);
189 switch (u
->flags
.form
)
194 case FORM_UNFORMATTED
:
198 internal_error (&iqp
->common
, "inquire_via_unit(): Bad form");
201 cf_strcpy (iqp
->formatted
, iqp
->formatted_len
, p
);
204 if ((cf
& IOPARM_INQUIRE_HAS_UNFORMATTED
) != 0)
207 p
= inquire_unformatted (NULL
, 0);
209 switch (u
->flags
.form
)
214 case FORM_UNFORMATTED
:
218 internal_error (&iqp
->common
, "inquire_via_unit(): Bad form");
221 cf_strcpy (iqp
->unformatted
, iqp
->unformatted_len
, p
);
224 if ((cf
& IOPARM_INQUIRE_HAS_RECL_OUT
) != 0)
225 /* F2018 (N2137) 12.10.2.26: If there is no connection, recl is
226 assigned the value -1. */
227 *iqp
->recl_out
= (u
!= NULL
) ? u
->recl
: -1;
229 if ((cf
& IOPARM_INQUIRE_HAS_STRM_POS_OUT
) != 0)
230 *iqp
->strm_pos_out
= (u
!= NULL
) ? u
->strm_pos
: 0;
232 if ((cf
& IOPARM_INQUIRE_HAS_NEXTREC
) != 0)
234 /* This only makes sense in the context of DIRECT access. */
235 if (u
!= NULL
&& u
->flags
.access
== ACCESS_DIRECT
)
236 *iqp
->nextrec
= u
->last_record
+ 1;
241 if ((cf
& IOPARM_INQUIRE_HAS_BLANK
) != 0)
243 if (u
== NULL
|| u
->flags
.form
!= FORM_FORMATTED
)
246 switch (u
->flags
.blank
)
255 internal_error (&iqp
->common
, "inquire_via_unit(): Bad blank");
258 cf_strcpy (iqp
->blank
, iqp
->blank_len
, p
);
261 if ((cf
& IOPARM_INQUIRE_HAS_PAD
) != 0)
263 if (u
== NULL
|| u
->flags
.form
!= FORM_FORMATTED
)
266 switch (u
->flags
.pad
)
275 internal_error (&iqp
->common
, "inquire_via_unit(): Bad pad");
278 cf_strcpy (iqp
->pad
, iqp
->pad_len
, p
);
281 if (cf
& IOPARM_INQUIRE_HAS_FLAGS2
)
283 GFC_INTEGER_4 cf2
= iqp
->flags2
;
285 if ((cf2
& IOPARM_INQUIRE_HAS_ENCODING
) != 0)
287 if (u
== NULL
|| u
->flags
.form
!= FORM_FORMATTED
)
290 switch (u
->flags
.encoding
)
292 case ENCODING_DEFAULT
:
299 internal_error (&iqp
->common
, "inquire_via_unit(): Bad encoding");
302 cf_strcpy (iqp
->encoding
, iqp
->encoding_len
, p
);
305 if ((cf2
& IOPARM_INQUIRE_HAS_DECIMAL
) != 0)
307 if (u
== NULL
|| u
->flags
.form
!= FORM_FORMATTED
)
310 switch (u
->flags
.decimal
)
319 internal_error (&iqp
->common
, "inquire_via_unit(): Bad comma");
322 cf_strcpy (iqp
->decimal
, iqp
->decimal_len
, p
);
325 if ((cf2
& IOPARM_INQUIRE_HAS_ASYNCHRONOUS
) != 0)
331 switch (u
->flags
.async
)
340 internal_error (&iqp
->common
, "inquire_via_unit(): Bad async");
343 cf_strcpy (iqp
->asynchronous
, iqp
->asynchronous_len
, p
);
346 if ((cf2
& IOPARM_INQUIRE_HAS_PENDING
) != 0)
348 if (!ASYNC_IO
|| u
->au
== NULL
)
352 LOCK (&(u
->au
->lock
));
353 if ((cf2
& IOPARM_INQUIRE_HAS_ID
) != 0)
357 *(iqp
->pending
) = id
> u
->au
->id
.low
;
361 *(iqp
->pending
) = ! u
->au
->empty
;
363 UNLOCK (&(u
->au
->lock
));
367 if ((cf2
& IOPARM_INQUIRE_HAS_SIGN
) != 0)
372 switch (u
->flags
.sign
)
374 case SIGN_PROCDEFINED
:
375 p
= "PROCESSOR_DEFINED";
384 internal_error (&iqp
->common
, "inquire_via_unit(): Bad sign");
387 cf_strcpy (iqp
->sign
, iqp
->sign_len
, p
);
390 if ((cf2
& IOPARM_INQUIRE_HAS_ROUND
) != 0)
395 switch (u
->flags
.round
)
409 case ROUND_COMPATIBLE
:
412 case ROUND_PROCDEFINED
:
413 p
= "PROCESSOR_DEFINED";
416 internal_error (&iqp
->common
, "inquire_via_unit(): Bad round");
419 cf_strcpy (iqp
->round
, iqp
->round_len
, p
);
422 if ((cf2
& IOPARM_INQUIRE_HAS_SIZE
) != 0)
429 *iqp
->size
= ssize (u
->s
);
433 if ((cf2
& IOPARM_INQUIRE_HAS_IQSTREAM
) != 0)
438 switch (u
->flags
.access
)
440 case ACCESS_SEQUENTIAL
:
448 internal_error (&iqp
->common
, "inquire_via_unit(): Bad pad");
451 cf_strcpy (iqp
->iqstream
, iqp
->iqstream_len
, p
);
454 if ((cf2
& IOPARM_INQUIRE_HAS_SHARE
) != 0)
459 switch (u
->flags
.share
)
467 case SHARE_UNSPECIFIED
:
471 internal_error (&iqp
->common
,
472 "inquire_via_unit(): Bad share");
476 cf_strcpy (iqp
->share
, iqp
->share_len
, p
);
479 if ((cf2
& IOPARM_INQUIRE_HAS_CC
) != 0)
499 internal_error (&iqp
->common
, "inquire_via_unit(): Bad cc");
503 cf_strcpy (iqp
->cc
, iqp
->cc_len
, p
);
507 if ((cf
& IOPARM_INQUIRE_HAS_POSITION
) != 0)
509 if (u
== NULL
|| u
->flags
.access
== ACCESS_DIRECT
)
513 /* If the position is unspecified, check if we can figure
514 out whether it's at the beginning or end. */
515 if (u
->flags
.position
== POSITION_UNSPECIFIED
)
517 gfc_offset cur
= stell (u
->s
);
519 u
->flags
.position
= POSITION_REWIND
;
520 else if (cur
!= -1 && (ssize (u
->s
) == cur
))
521 u
->flags
.position
= POSITION_APPEND
;
523 switch (u
->flags
.position
)
525 case POSITION_REWIND
:
528 case POSITION_APPEND
:
535 /* If the position has changed and is not rewind or
536 append, it must be set to a processor-dependent
542 cf_strcpy (iqp
->position
, iqp
->position_len
, p
);
545 if ((cf
& IOPARM_INQUIRE_HAS_ACTION
) != 0)
550 switch (u
->flags
.action
)
558 case ACTION_READWRITE
:
562 internal_error (&iqp
->common
, "inquire_via_unit(): Bad action");
565 cf_strcpy (iqp
->action
, iqp
->action_len
, p
);
568 if ((cf
& IOPARM_INQUIRE_HAS_READ
) != 0)
570 p
= (!u
|| u
->flags
.action
== ACTION_WRITE
) ? no
: yes
;
571 cf_strcpy (iqp
->read
, iqp
->read_len
, p
);
574 if ((cf
& IOPARM_INQUIRE_HAS_WRITE
) != 0)
576 p
= (!u
|| u
->flags
.action
== ACTION_READ
) ? no
: yes
;
577 cf_strcpy (iqp
->write
, iqp
->write_len
, p
);
580 if ((cf
& IOPARM_INQUIRE_HAS_READWRITE
) != 0)
582 p
= (!u
|| u
->flags
.action
!= ACTION_READWRITE
) ? no
: yes
;
583 cf_strcpy (iqp
->readwrite
, iqp
->readwrite_len
, p
);
586 if ((cf
& IOPARM_INQUIRE_HAS_DELIM
) != 0)
588 if (u
== NULL
|| u
->flags
.form
!= FORM_FORMATTED
)
591 switch (u
->flags
.delim
)
594 case DELIM_UNSPECIFIED
:
600 case DELIM_APOSTROPHE
:
604 internal_error (&iqp
->common
, "inquire_via_unit(): Bad delim");
607 cf_strcpy (iqp
->delim
, iqp
->delim_len
, p
);
610 if ((cf
& IOPARM_INQUIRE_HAS_PAD
) != 0)
612 if (u
== NULL
|| u
->flags
.form
!= FORM_FORMATTED
)
615 switch (u
->flags
.pad
)
624 internal_error (&iqp
->common
, "inquire_via_unit(): Bad pad");
627 cf_strcpy (iqp
->pad
, iqp
->pad_len
, p
);
630 if ((cf
& IOPARM_INQUIRE_HAS_CONVERT
) != 0)
635 switch (u
->flags
.convert
)
637 case GFC_CONVERT_NATIVE
:
638 p
= __BYTE_ORDER__
== __ORDER_BIG_ENDIAN__
? "BIG_ENDIAN" : "LITTLE_ENDIAN";
641 case GFC_CONVERT_SWAP
:
642 p
= __BYTE_ORDER__
== __ORDER_BIG_ENDIAN__
? "LITTLE_ENDIAN" : "BIG_ENDIAN";
646 internal_error (&iqp
->common
, "inquire_via_unit(): Bad convert");
649 cf_strcpy (iqp
->convert
, iqp
->convert_len
, p
);
654 /* inquire_via_filename()-- Inquiry via filename. This subroutine is
655 only used if the filename is *not* connected to a unit number. */
658 inquire_via_filename (st_parameter_inquire
*iqp
)
661 GFC_INTEGER_4 cf
= iqp
->common
.flags
;
663 if ((cf
& IOPARM_INQUIRE_HAS_EXIST
) != 0)
664 *iqp
->exist
= file_exists (iqp
->file
, iqp
->file_len
);
666 if ((cf
& IOPARM_INQUIRE_HAS_OPENED
) != 0)
669 if ((cf
& IOPARM_INQUIRE_HAS_NUMBER
) != 0)
672 if ((cf
& IOPARM_INQUIRE_HAS_NAMED
) != 0)
675 if ((cf
& IOPARM_INQUIRE_HAS_NAME
) != 0)
676 fstrcpy (iqp
->name
, iqp
->name_len
, iqp
->file
, iqp
->file_len
);
678 if ((cf
& IOPARM_INQUIRE_HAS_ACCESS
) != 0)
679 cf_strcpy (iqp
->access
, iqp
->access_len
, undefined
);
681 if ((cf
& IOPARM_INQUIRE_HAS_SEQUENTIAL
) != 0)
684 cf_strcpy (iqp
->sequential
, iqp
->sequential_len
, p
);
687 if ((cf
& IOPARM_INQUIRE_HAS_DIRECT
) != 0)
690 cf_strcpy (iqp
->direct
, iqp
->direct_len
, p
);
693 if ((cf
& IOPARM_INQUIRE_HAS_FORM
) != 0)
694 cf_strcpy (iqp
->form
, iqp
->form_len
, undefined
);
696 if ((cf
& IOPARM_INQUIRE_HAS_FORMATTED
) != 0)
699 cf_strcpy (iqp
->formatted
, iqp
->formatted_len
, p
);
702 if ((cf
& IOPARM_INQUIRE_HAS_UNFORMATTED
) != 0)
705 cf_strcpy (iqp
->unformatted
, iqp
->unformatted_len
, p
);
708 if ((cf
& IOPARM_INQUIRE_HAS_RECL_OUT
) != 0)
711 if ((cf
& IOPARM_INQUIRE_HAS_NEXTREC
) != 0)
714 if ((cf
& IOPARM_INQUIRE_HAS_BLANK
) != 0)
715 cf_strcpy (iqp
->blank
, iqp
->blank_len
, undefined
);
717 if ((cf
& IOPARM_INQUIRE_HAS_PAD
) != 0)
718 cf_strcpy (iqp
->pad
, iqp
->pad_len
, undefined
);
720 if (cf
& IOPARM_INQUIRE_HAS_FLAGS2
)
722 GFC_INTEGER_4 cf2
= iqp
->flags2
;
724 if ((cf2
& IOPARM_INQUIRE_HAS_ENCODING
) != 0)
725 cf_strcpy (iqp
->encoding
, iqp
->encoding_len
, undefined
);
727 if ((cf2
& IOPARM_INQUIRE_HAS_DELIM
) != 0)
728 cf_strcpy (iqp
->delim
, iqp
->delim_len
, undefined
);
730 if ((cf2
& IOPARM_INQUIRE_HAS_DECIMAL
) != 0)
731 cf_strcpy (iqp
->decimal
, iqp
->decimal_len
, undefined
);
733 if ((cf2
& IOPARM_INQUIRE_HAS_DELIM
) != 0)
734 cf_strcpy (iqp
->delim
, iqp
->delim_len
, undefined
);
736 if ((cf2
& IOPARM_INQUIRE_HAS_PAD
) != 0)
737 cf_strcpy (iqp
->pad
, iqp
->pad_len
, undefined
);
739 if ((cf2
& IOPARM_INQUIRE_HAS_ENCODING
) != 0)
740 cf_strcpy (iqp
->encoding
, iqp
->encoding_len
, undefined
);
742 if ((cf2
& IOPARM_INQUIRE_HAS_SIZE
) != 0)
743 *iqp
->size
= file_size (iqp
->file
, iqp
->file_len
);
745 if ((cf2
& IOPARM_INQUIRE_HAS_IQSTREAM
) != 0)
746 cf_strcpy (iqp
->iqstream
, iqp
->iqstream_len
, "UNKNOWN");
748 if ((cf2
& IOPARM_INQUIRE_HAS_SHARE
) != 0)
749 cf_strcpy (iqp
->share
, iqp
->share_len
, "UNKNOWN");
751 if ((cf2
& IOPARM_INQUIRE_HAS_CC
) != 0)
752 cf_strcpy (iqp
->cc
, iqp
->cc_len
, "UNKNOWN");
755 if ((cf
& IOPARM_INQUIRE_HAS_POSITION
) != 0)
756 cf_strcpy (iqp
->position
, iqp
->position_len
, undefined
);
758 if ((cf
& IOPARM_INQUIRE_HAS_ACCESS
) != 0)
759 cf_strcpy (iqp
->access
, iqp
->access_len
, undefined
);
761 if ((cf
& IOPARM_INQUIRE_HAS_READ
) != 0)
763 p
= inquire_read (iqp
->file
, iqp
->file_len
);
764 cf_strcpy (iqp
->read
, iqp
->read_len
, p
);
767 if ((cf
& IOPARM_INQUIRE_HAS_WRITE
) != 0)
769 p
= inquire_write (iqp
->file
, iqp
->file_len
);
770 cf_strcpy (iqp
->write
, iqp
->write_len
, p
);
773 if ((cf
& IOPARM_INQUIRE_HAS_READWRITE
) != 0)
775 p
= inquire_read (iqp
->file
, iqp
->file_len
);
776 cf_strcpy (iqp
->readwrite
, iqp
->readwrite_len
, p
);
781 /* Library entry point for the INQUIRE statement (non-IOLENGTH
784 extern void st_inquire (st_parameter_inquire
*);
785 export_proto(st_inquire
);
788 st_inquire (st_parameter_inquire
*iqp
)
792 library_start (&iqp
->common
);
794 if ((iqp
->common
.flags
& IOPARM_INQUIRE_HAS_FILE
) == 0)
796 u
= find_unit (iqp
->common
.unit
);
797 inquire_via_unit (iqp
, u
);
801 u
= find_file (iqp
->file
, iqp
->file_len
);
803 inquire_via_filename (iqp
);
805 inquire_via_unit (iqp
, u
);