1 /* Copyright (C) 2002-2020 Free Software Foundation, Inc.
2    Contributed by Andy Vaught
3 
4 This file is part of the GNU Fortran runtime library (libgfortran).
5 
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)
9 any later version.
10 
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.
15 
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.
19 
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/>.  */
24 
25 
26 /* Implement the non-IOLENGTH variant of the INQUIRY statement */
27 
28 #include "io.h"
29 #include "async.h"
30 #include "unix.h"
31 #include <string.h>
32 
33 
34 static const char yes[] = "YES", no[] = "NO", undefined[] = "UNDEFINED";
35 
36 
37 /* inquire_via_unit()-- Inquiry via unit number.  The unit might not exist. */
38 
39 static void
inquire_via_unit(st_parameter_inquire * iqp,gfc_unit * u)40 inquire_via_unit (st_parameter_inquire *iqp, gfc_unit *u)
41 {
42   const char *p;
43   GFC_INTEGER_4 cf = iqp->common.flags;
44 
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);
49 
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);
55 
56   if ((cf & IOPARM_INQUIRE_HAS_OPENED) != 0)
57     *iqp->opened = (u != NULL);
58 
59   if ((cf & IOPARM_INQUIRE_HAS_NUMBER) != 0)
60     *iqp->number = (u != NULL) ? u->unit_number : -1;
61 
62   if ((cf & IOPARM_INQUIRE_HAS_NAMED) != 0)
63     *iqp->named = (u != NULL && u->flags.status != STATUS_SCRATCH);
64 
65   if ((cf & IOPARM_INQUIRE_HAS_NAME) != 0
66       && u != NULL && u->flags.status != STATUS_SCRATCH)
67     {
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)
72 	{
73 	  int err = stream_ttyname (u->s, iqp->name, iqp->name_len);
74 	  if (err == 0)
75 	    {
76 	      gfc_charlen_type tmplen = strlen (iqp->name);
77 	      if (iqp->name_len > tmplen)
78 		memset (&iqp->name[tmplen], ' ', iqp->name_len - tmplen);
79 	    }
80 	  else /* If ttyname does not work, go with the default.  */
81 	    cf_strcpy (iqp->name, iqp->name_len, u->filename);
82 	}
83       else
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$"));
92       else
93 	cf_strcpy (iqp->name, iqp->name_len, u->filename);
94 #else
95       cf_strcpy (iqp->name, iqp->name_len, u->filename);
96 #endif
97     }
98 
99   if ((cf & IOPARM_INQUIRE_HAS_ACCESS) != 0)
100     {
101       if (u == NULL)
102 	p = undefined;
103       else
104 	switch (u->flags.access)
105 	  {
106 	  case ACCESS_SEQUENTIAL:
107 	    p = "SEQUENTIAL";
108 	    break;
109 	  case ACCESS_DIRECT:
110 	    p = "DIRECT";
111 	    break;
112 	  case ACCESS_STREAM:
113 	    p = "STREAM";
114 	    break;
115 	  default:
116 	    internal_error (&iqp->common, "inquire_via_unit(): Bad access");
117 	  }
118 
119       cf_strcpy (iqp->access, iqp->access_len, p);
120     }
121 
122   if ((cf & IOPARM_INQUIRE_HAS_SEQUENTIAL) != 0)
123     {
124       if (u == NULL)
125 	p = inquire_sequential (NULL, 0);
126       else
127 	switch (u->flags.access)
128 	  {
129 	  case ACCESS_DIRECT:
130 	  case ACCESS_STREAM:
131 	    p = no;
132 	    break;
133 	  case ACCESS_SEQUENTIAL:
134 	    p = yes;
135 	    break;
136 	  default:
137 	    internal_error (&iqp->common, "inquire_via_unit(): Bad access");
138 	  }
139 
140       cf_strcpy (iqp->sequential, iqp->sequential_len, p);
141     }
142 
143   if ((cf & IOPARM_INQUIRE_HAS_DIRECT) != 0)
144     {
145       if (u == NULL)
146 	p = inquire_direct (NULL, 0);
147       else
148 	switch (u->flags.access)
149 	  {
150 	  case ACCESS_SEQUENTIAL:
151 	  case ACCESS_STREAM:
152 	    p = no;
153 	    break;
154 	  case ACCESS_DIRECT:
155 	    p = yes;
156 	    break;
157 	  default:
158 	    internal_error (&iqp->common, "inquire_via_unit(): Bad access");
159 	  }
160 
161       cf_strcpy (iqp->direct, iqp->direct_len, p);
162     }
163 
164   if ((cf & IOPARM_INQUIRE_HAS_FORM) != 0)
165     {
166       if (u == NULL)
167 	p = undefined;
168       else
169 	switch (u->flags.form)
170 	  {
171 	  case FORM_FORMATTED:
172 	    p = "FORMATTED";
173 	    break;
174 	  case FORM_UNFORMATTED:
175 	    p = "UNFORMATTED";
176 	    break;
177 	  default:
178 	    internal_error (&iqp->common, "inquire_via_unit(): Bad form");
179 	  }
180 
181       cf_strcpy (iqp->form, iqp->form_len, p);
182     }
183 
184   if ((cf & IOPARM_INQUIRE_HAS_FORMATTED) != 0)
185     {
186       if (u == NULL)
187 	p = inquire_formatted (NULL, 0);
188       else
189 	switch (u->flags.form)
190 	  {
191 	  case FORM_FORMATTED:
192 	    p = yes;
193 	    break;
194 	  case FORM_UNFORMATTED:
195 	    p = no;
196 	    break;
197 	  default:
198 	    internal_error (&iqp->common, "inquire_via_unit(): Bad form");
199 	  }
200 
201       cf_strcpy (iqp->formatted, iqp->formatted_len, p);
202     }
203 
204   if ((cf & IOPARM_INQUIRE_HAS_UNFORMATTED) != 0)
205     {
206       if (u == NULL)
207 	p = inquire_unformatted (NULL, 0);
208       else
209 	switch (u->flags.form)
210 	  {
211 	  case FORM_FORMATTED:
212 	    p = no;
213 	    break;
214 	  case FORM_UNFORMATTED:
215 	    p = yes;
216 	    break;
217 	  default:
218 	    internal_error (&iqp->common, "inquire_via_unit(): Bad form");
219 	  }
220 
221       cf_strcpy (iqp->unformatted, iqp->unformatted_len, p);
222     }
223 
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;
228 
229   if ((cf & IOPARM_INQUIRE_HAS_STRM_POS_OUT) != 0)
230     *iqp->strm_pos_out = (u != NULL) ? u->strm_pos : 0;
231 
232   if ((cf & IOPARM_INQUIRE_HAS_NEXTREC) != 0)
233     {
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;
237       else
238 	*iqp->nextrec = 0;
239     }
240 
241   if ((cf & IOPARM_INQUIRE_HAS_BLANK) != 0)
242     {
243       if (u == NULL || u->flags.form != FORM_FORMATTED)
244 	p = undefined;
245       else
246 	switch (u->flags.blank)
247 	  {
248 	  case BLANK_NULL:
249 	    p = "NULL";
250 	    break;
251 	  case BLANK_ZERO:
252 	    p = "ZERO";
253 	    break;
254 	  default:
255 	    internal_error (&iqp->common, "inquire_via_unit(): Bad blank");
256 	  }
257 
258       cf_strcpy (iqp->blank, iqp->blank_len, p);
259     }
260 
261   if ((cf & IOPARM_INQUIRE_HAS_PAD) != 0)
262     {
263       if (u == NULL || u->flags.form != FORM_FORMATTED)
264 	p = undefined;
265       else
266 	switch (u->flags.pad)
267 	  {
268 	  case PAD_YES:
269 	    p = yes;
270 	    break;
271 	  case PAD_NO:
272 	    p = no;
273 	    break;
274 	  default:
275 	    internal_error (&iqp->common, "inquire_via_unit(): Bad pad");
276 	  }
277 
278       cf_strcpy (iqp->pad, iqp->pad_len, p);
279     }
280 
281   if (cf & IOPARM_INQUIRE_HAS_FLAGS2)
282     {
283       GFC_INTEGER_4 cf2 = iqp->flags2;
284 
285       if ((cf2 & IOPARM_INQUIRE_HAS_ENCODING) != 0)
286 	{
287 	  if (u == NULL || u->flags.form != FORM_FORMATTED)
288 	    p = undefined;
289           else
290 	    switch (u->flags.encoding)
291 	      {
292 	      case ENCODING_DEFAULT:
293 		p = "UNKNOWN";
294 		break;
295 	      case ENCODING_UTF8:
296 		p = "UTF-8";
297 		break;
298 	      default:
299 		internal_error (&iqp->common, "inquire_via_unit(): Bad encoding");
300 	      }
301 
302 	  cf_strcpy (iqp->encoding, iqp->encoding_len, p);
303 	}
304 
305       if ((cf2 & IOPARM_INQUIRE_HAS_DECIMAL) != 0)
306 	{
307 	  if (u == NULL || u->flags.form != FORM_FORMATTED)
308 	    p = undefined;
309 	  else
310 	    switch (u->flags.decimal)
311 	      {
312 	      case DECIMAL_POINT:
313 		p = "POINT";
314 		break;
315 	      case DECIMAL_COMMA:
316 		p = "COMMA";
317 		break;
318 	      default:
319 		internal_error (&iqp->common, "inquire_via_unit(): Bad comma");
320 	      }
321 
322 	  cf_strcpy (iqp->decimal, iqp->decimal_len, p);
323 	}
324 
325       if ((cf2 & IOPARM_INQUIRE_HAS_ASYNCHRONOUS) != 0)
326 	{
327 	  if (u == NULL)
328 	    p = undefined;
329 	  else
330 	    {
331 	      switch (u->flags.async)
332 		{
333 		case ASYNC_YES:
334 		  p = yes;
335 		  break;
336 		case ASYNC_NO:
337 		  p = no;
338 		  break;
339 		default:
340 		  internal_error (&iqp->common, "inquire_via_unit(): Bad async");
341 		}
342 	    }
343 	  cf_strcpy (iqp->asynchronous, iqp->asynchronous_len, p);
344 	}
345 
346       if ((cf2 & IOPARM_INQUIRE_HAS_PENDING) != 0)
347 	{
348 	  if (!ASYNC_IO || u->au == NULL)
349 	    *(iqp->pending) = 0;
350 	  else
351 	    {
352 	      LOCK (&(u->au->lock));
353 	      if ((cf2 & IOPARM_INQUIRE_HAS_ID) != 0)
354 		{
355 		  int id;
356 		  id = *(iqp->id);
357 		  *(iqp->pending) = id > u->au->id.low;
358 		}
359 	      else
360 		{
361 		  *(iqp->pending) = ! u->au->empty;
362 		}
363 	      UNLOCK (&(u->au->lock));
364 	    }
365 	}
366 
367       if ((cf2 & IOPARM_INQUIRE_HAS_SIGN) != 0)
368 	{
369 	  if (u == NULL)
370 	    p = undefined;
371 	  else
372 	    switch (u->flags.sign)
373 	    {
374 	      case SIGN_PROCDEFINED:
375 		p = "PROCESSOR_DEFINED";
376 		break;
377 	      case SIGN_SUPPRESS:
378 		p = "SUPPRESS";
379 		break;
380 	      case SIGN_PLUS:
381 		p = "PLUS";
382 		break;
383 	      default:
384 		internal_error (&iqp->common, "inquire_via_unit(): Bad sign");
385 	    }
386 
387 	  cf_strcpy (iqp->sign, iqp->sign_len, p);
388 	}
389 
390       if ((cf2 & IOPARM_INQUIRE_HAS_ROUND) != 0)
391 	{
392 	  if (u == NULL)
393 	    p = undefined;
394 	  else
395 	    switch (u->flags.round)
396 	    {
397 	      case ROUND_UP:
398 		p = "UP";
399 		break;
400 	      case ROUND_DOWN:
401 		p = "DOWN";
402 		break;
403 	      case ROUND_ZERO:
404 		p = "ZERO";
405 		break;
406 	      case ROUND_NEAREST:
407 		p = "NEAREST";
408 		break;
409 	      case ROUND_COMPATIBLE:
410 		p = "COMPATIBLE";
411 		break;
412 	      case ROUND_PROCDEFINED:
413 		p = "PROCESSOR_DEFINED";
414 		break;
415 	      default:
416 		internal_error (&iqp->common, "inquire_via_unit(): Bad round");
417 	    }
418 
419 	  cf_strcpy (iqp->round, iqp->round_len, p);
420 	}
421 
422       if ((cf2 & IOPARM_INQUIRE_HAS_SIZE) != 0)
423 	{
424 	  if (u == NULL)
425 	    *iqp->size = -1;
426 	  else
427 	    {
428 	      sflush (u->s);
429 	      *iqp->size = ssize (u->s);
430 	    }
431 	}
432 
433       if ((cf2 & IOPARM_INQUIRE_HAS_IQSTREAM) != 0)
434 	{
435 	  if (u == NULL)
436 	    p = "UNKNOWN";
437 	  else
438 	    switch (u->flags.access)
439 	      {
440 	      case ACCESS_SEQUENTIAL:
441 	      case ACCESS_DIRECT:
442 		p = no;
443 		break;
444 	      case ACCESS_STREAM:
445 		p = yes;
446 		break;
447 	      default:
448 		internal_error (&iqp->common, "inquire_via_unit(): Bad pad");
449 	      }
450 
451 	  cf_strcpy (iqp->iqstream, iqp->iqstream_len, p);
452 	}
453 
454       if ((cf2 & IOPARM_INQUIRE_HAS_SHARE) != 0)
455 	{
456 	  if (u == NULL)
457 	    p = "UNKNOWN";
458 	  else
459 	    switch (u->flags.share)
460 	      {
461 		case SHARE_DENYRW:
462 		  p = "DENYRW";
463 		  break;
464 		case SHARE_DENYNONE:
465 		  p = "DENYNONE";
466 		  break;
467 		case SHARE_UNSPECIFIED:
468 		  p = "NODENY";
469 		  break;
470 		default:
471 		  internal_error (&iqp->common,
472 		      "inquire_via_unit(): Bad share");
473 		  break;
474 	      }
475 
476 	  cf_strcpy (iqp->share, iqp->share_len, p);
477 	}
478 
479       if ((cf2 & IOPARM_INQUIRE_HAS_CC) != 0)
480 	{
481 	  if (u == NULL)
482 	    p = "UNKNOWN";
483 	  else
484 	    switch (u->flags.cc)
485 	      {
486 		case CC_FORTRAN:
487 		  p = "FORTRAN";
488 		  break;
489 		case CC_LIST:
490 		  p = "LIST";
491 		  break;
492 		case CC_NONE:
493 		  p = "NONE";
494 		  break;
495 		case CC_UNSPECIFIED:
496 		  p = "UNKNOWN";
497 		  break;
498 		default:
499 		  internal_error (&iqp->common, "inquire_via_unit(): Bad cc");
500 		  break;
501 	      }
502 
503 	  cf_strcpy (iqp->cc, iqp->cc_len, p);
504 	}
505     }
506 
507   if ((cf & IOPARM_INQUIRE_HAS_POSITION) != 0)
508     {
509       if (u == NULL || u->flags.access == ACCESS_DIRECT)
510         p = undefined;
511       else
512 	{
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)
516 	    {
517 	      gfc_offset cur = stell (u->s);
518 	      if (cur == 0)
519 		u->flags.position = POSITION_REWIND;
520 	      else if (cur != -1 && (ssize (u->s) == cur))
521 		u->flags.position = POSITION_APPEND;
522 	    }
523 	  switch (u->flags.position)
524 	    {
525 	    case POSITION_REWIND:
526 	      p = "REWIND";
527 	      break;
528 	    case POSITION_APPEND:
529 	      p = "APPEND";
530 	      break;
531 	    case POSITION_ASIS:
532 	      p = "ASIS";
533 	      break;
534 	    default:
535 	      /* If the position has changed and is not rewind or
536 		 append, it must be set to a processor-dependent
537 		 value.  */
538 	      p = "UNSPECIFIED";
539 	      break;
540 	    }
541 	}
542       cf_strcpy (iqp->position, iqp->position_len, p);
543     }
544 
545   if ((cf & IOPARM_INQUIRE_HAS_ACTION) != 0)
546     {
547       if (u == NULL)
548 	p = undefined;
549       else
550 	switch (u->flags.action)
551 	  {
552 	  case ACTION_READ:
553 	    p = "READ";
554 	    break;
555 	  case ACTION_WRITE:
556 	    p = "WRITE";
557 	    break;
558 	  case ACTION_READWRITE:
559 	    p = "READWRITE";
560 	    break;
561 	  default:
562 	    internal_error (&iqp->common, "inquire_via_unit(): Bad action");
563 	  }
564 
565       cf_strcpy (iqp->action, iqp->action_len, p);
566     }
567 
568   if ((cf & IOPARM_INQUIRE_HAS_READ) != 0)
569     {
570       p = (!u || u->flags.action == ACTION_WRITE) ? no : yes;
571       cf_strcpy (iqp->read, iqp->read_len, p);
572     }
573 
574   if ((cf & IOPARM_INQUIRE_HAS_WRITE) != 0)
575     {
576       p = (!u || u->flags.action == ACTION_READ) ? no : yes;
577       cf_strcpy (iqp->write, iqp->write_len, p);
578     }
579 
580   if ((cf & IOPARM_INQUIRE_HAS_READWRITE) != 0)
581     {
582       p = (!u || u->flags.action != ACTION_READWRITE) ? no : yes;
583       cf_strcpy (iqp->readwrite, iqp->readwrite_len, p);
584     }
585 
586   if ((cf & IOPARM_INQUIRE_HAS_DELIM) != 0)
587     {
588       if (u == NULL || u->flags.form != FORM_FORMATTED)
589 	p = undefined;
590       else
591 	switch (u->flags.delim)
592 	  {
593 	  case DELIM_NONE:
594 	  case DELIM_UNSPECIFIED:
595 	    p = "NONE";
596 	    break;
597 	  case DELIM_QUOTE:
598 	    p = "QUOTE";
599 	    break;
600 	  case DELIM_APOSTROPHE:
601 	    p = "APOSTROPHE";
602 	    break;
603 	  default:
604 	    internal_error (&iqp->common, "inquire_via_unit(): Bad delim");
605 	  }
606 
607       cf_strcpy (iqp->delim, iqp->delim_len, p);
608     }
609 
610   if ((cf & IOPARM_INQUIRE_HAS_PAD) != 0)
611     {
612       if (u == NULL || u->flags.form != FORM_FORMATTED)
613 	p = undefined;
614       else
615 	switch (u->flags.pad)
616 	  {
617 	  case PAD_NO:
618 	    p = no;
619 	    break;
620 	  case PAD_YES:
621 	    p = yes;
622 	    break;
623 	  default:
624 	    internal_error (&iqp->common, "inquire_via_unit(): Bad pad");
625 	  }
626 
627       cf_strcpy (iqp->pad, iqp->pad_len, p);
628     }
629 
630   if ((cf & IOPARM_INQUIRE_HAS_CONVERT) != 0)
631     {
632       if (u == NULL)
633 	p = undefined;
634       else
635 	switch (u->flags.convert)
636 	  {
637 	  case GFC_CONVERT_NATIVE:
638 	    p = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? "BIG_ENDIAN" : "LITTLE_ENDIAN";
639 	    break;
640 
641 	  case GFC_CONVERT_SWAP:
642 	    p = __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? "LITTLE_ENDIAN" : "BIG_ENDIAN";
643 	    break;
644 
645 	  default:
646 	    internal_error (&iqp->common, "inquire_via_unit(): Bad convert");
647 	  }
648 
649       cf_strcpy (iqp->convert, iqp->convert_len, p);
650     }
651 }
652 
653 
654 /* inquire_via_filename()-- Inquiry via filename.  This subroutine is
655    only used if the filename is *not* connected to a unit number. */
656 
657 static void
inquire_via_filename(st_parameter_inquire * iqp)658 inquire_via_filename (st_parameter_inquire *iqp)
659 {
660   const char *p;
661   GFC_INTEGER_4 cf = iqp->common.flags;
662 
663   if ((cf & IOPARM_INQUIRE_HAS_EXIST) != 0)
664     *iqp->exist = file_exists (iqp->file, iqp->file_len);
665 
666   if ((cf & IOPARM_INQUIRE_HAS_OPENED) != 0)
667     *iqp->opened = 0;
668 
669   if ((cf & IOPARM_INQUIRE_HAS_NUMBER) != 0)
670     *iqp->number = -1;
671 
672   if ((cf & IOPARM_INQUIRE_HAS_NAMED) != 0)
673     *iqp->named = 1;
674 
675   if ((cf & IOPARM_INQUIRE_HAS_NAME) != 0)
676     fstrcpy (iqp->name, iqp->name_len, iqp->file, iqp->file_len);
677 
678   if ((cf & IOPARM_INQUIRE_HAS_ACCESS) != 0)
679     cf_strcpy (iqp->access, iqp->access_len, undefined);
680 
681   if ((cf & IOPARM_INQUIRE_HAS_SEQUENTIAL) != 0)
682     {
683       p = "UNKNOWN";
684       cf_strcpy (iqp->sequential, iqp->sequential_len, p);
685     }
686 
687   if ((cf & IOPARM_INQUIRE_HAS_DIRECT) != 0)
688     {
689       p = "UNKNOWN";
690       cf_strcpy (iqp->direct, iqp->direct_len, p);
691     }
692 
693   if ((cf & IOPARM_INQUIRE_HAS_FORM) != 0)
694     cf_strcpy (iqp->form, iqp->form_len, undefined);
695 
696   if ((cf & IOPARM_INQUIRE_HAS_FORMATTED) != 0)
697     {
698       p = "UNKNOWN";
699       cf_strcpy (iqp->formatted, iqp->formatted_len, p);
700     }
701 
702   if ((cf & IOPARM_INQUIRE_HAS_UNFORMATTED) != 0)
703     {
704       p = "UNKNOWN";
705       cf_strcpy (iqp->unformatted, iqp->unformatted_len, p);
706     }
707 
708   if ((cf & IOPARM_INQUIRE_HAS_RECL_OUT) != 0)
709     /* F2018 (N2137) 12.10.2.26: If there is no connection, recl is
710        assigned the value -1.  */
711     *iqp->recl_out = -1;
712 
713   if ((cf & IOPARM_INQUIRE_HAS_NEXTREC) != 0)
714     *iqp->nextrec = 0;
715 
716   if ((cf & IOPARM_INQUIRE_HAS_BLANK) != 0)
717     cf_strcpy (iqp->blank, iqp->blank_len, undefined);
718 
719   if ((cf & IOPARM_INQUIRE_HAS_PAD) != 0)
720     cf_strcpy (iqp->pad, iqp->pad_len, undefined);
721 
722   if (cf & IOPARM_INQUIRE_HAS_FLAGS2)
723     {
724       GFC_INTEGER_4 cf2 = iqp->flags2;
725 
726       if ((cf2 & IOPARM_INQUIRE_HAS_ENCODING) != 0)
727 	cf_strcpy (iqp->encoding, iqp->encoding_len, undefined);
728 
729       if ((cf2 & IOPARM_INQUIRE_HAS_DELIM) != 0)
730 	cf_strcpy (iqp->delim, iqp->delim_len, undefined);
731 
732       if ((cf2 & IOPARM_INQUIRE_HAS_DECIMAL) != 0)
733 	cf_strcpy (iqp->decimal, iqp->decimal_len, undefined);
734 
735       if ((cf2 & IOPARM_INQUIRE_HAS_DELIM) != 0)
736 	cf_strcpy (iqp->delim, iqp->delim_len, undefined);
737 
738       if ((cf2 & IOPARM_INQUIRE_HAS_PAD) != 0)
739 	cf_strcpy (iqp->pad, iqp->pad_len, undefined);
740 
741       if ((cf2 & IOPARM_INQUIRE_HAS_ENCODING) != 0)
742 	cf_strcpy (iqp->encoding, iqp->encoding_len, undefined);
743 
744       if ((cf2 & IOPARM_INQUIRE_HAS_SIZE) != 0)
745 	*iqp->size = file_size (iqp->file, iqp->file_len);
746 
747       if ((cf2 & IOPARM_INQUIRE_HAS_IQSTREAM) != 0)
748 	cf_strcpy (iqp->iqstream, iqp->iqstream_len, "UNKNOWN");
749 
750       if ((cf2 & IOPARM_INQUIRE_HAS_SHARE) != 0)
751 	cf_strcpy (iqp->share, iqp->share_len, "UNKNOWN");
752 
753       if ((cf2 & IOPARM_INQUIRE_HAS_CC) != 0)
754 	cf_strcpy (iqp->cc, iqp->cc_len, "UNKNOWN");
755     }
756 
757   if ((cf & IOPARM_INQUIRE_HAS_POSITION) != 0)
758     cf_strcpy (iqp->position, iqp->position_len, undefined);
759 
760   if ((cf & IOPARM_INQUIRE_HAS_ACCESS) != 0)
761     cf_strcpy (iqp->access, iqp->access_len, undefined);
762 
763   if ((cf & IOPARM_INQUIRE_HAS_READ) != 0)
764     {
765       p = inquire_read (iqp->file, iqp->file_len);
766       cf_strcpy (iqp->read, iqp->read_len, p);
767     }
768 
769   if ((cf & IOPARM_INQUIRE_HAS_WRITE) != 0)
770     {
771       p = inquire_write (iqp->file, iqp->file_len);
772       cf_strcpy (iqp->write, iqp->write_len, p);
773     }
774 
775   if ((cf & IOPARM_INQUIRE_HAS_READWRITE) != 0)
776     {
777       p = inquire_read (iqp->file, iqp->file_len);
778       cf_strcpy (iqp->readwrite, iqp->readwrite_len, p);
779     }
780 }
781 
782 
783 /* Library entry point for the INQUIRE statement (non-IOLENGTH
784    form).  */
785 
786 extern void st_inquire (st_parameter_inquire *);
787 export_proto(st_inquire);
788 
789 void
st_inquire(st_parameter_inquire * iqp)790 st_inquire (st_parameter_inquire *iqp)
791 {
792   gfc_unit *u;
793 
794   library_start (&iqp->common);
795 
796   if ((iqp->common.flags & IOPARM_INQUIRE_HAS_FILE) == 0)
797     {
798       u = find_unit (iqp->common.unit);
799       inquire_via_unit (iqp, u);
800     }
801   else
802     {
803       u = find_file (iqp->file, iqp->file_len);
804       if (u == NULL)
805 	inquire_via_filename (iqp);
806       else
807 	inquire_via_unit (iqp, u);
808     }
809   if (u != NULL)
810     unlock_unit (u);
811 
812   library_end ();
813 }
814