Commit for Victor Leikehman <lei@il.ibm.com>
[gcc.git] / libgfortran / io / read.c
1 /* Copyright (C) 2002-2003 Free Software Foundation, Inc.
2 Contributed by Andy Vaught
3
4 This file is part of the GNU Fortran 95 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 2, 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 You should have received a copy of the GNU General Public License
17 along with Libgfortran; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #include "config.h"
23 #include <string.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include <stdlib.h>
27 #include "libgfortran.h"
28 #include "io.h"
29
30 /* read.c -- Deal with formatted reads */
31
32 /* set_integer()-- All of the integer assignments come here to
33 * actually place the value into memory. */
34
35 void
36 set_integer (void *dest, int64_t value, int length)
37 {
38
39 switch (length)
40 {
41 case 8:
42 *((int64_t *) dest) = value;
43 break;
44 case 4:
45 *((int32_t *) dest) = value;
46 break;
47 case 2:
48 *((int16_t *) dest) = value;
49 break;
50 case 1:
51 *((int8_t *) dest) = value;
52 break;
53 default:
54 internal_error ("Bad integer kind");
55 }
56 }
57
58
59 /* max_value()-- Given a length (kind), return the maximum signed or
60 * unsigned value */
61
62 uint64_t
63 max_value (int length, int signed_flag)
64 {
65 uint64_t value;
66
67 switch (length)
68 {
69 case 8:
70 value = signed_flag ? 0x7fffffffffffffff : 0xffffffffffffffff;
71 break;
72 case 4:
73 value = signed_flag ? 0x7fffffff : 0xffffffff;
74 break;
75 case 2:
76 value = signed_flag ? 0x7fff : 0xffff;
77 break;
78 case 1:
79 value = signed_flag ? 0x7f : 0xff;
80 break;
81 default:
82 internal_error ("Bad integer kind");
83 }
84
85 return value;
86 }
87
88
89 /* convert_real()-- Convert a character representation of a floating
90 * point number to the machine number. Returns nonzero if there is a
91 * range problem during conversion. TODO: handle not-a-numbers and
92 * infinities. Handling of kind 4 is probably wrong because of double
93 * rounding. */
94
95 int
96 convert_real (void *dest, const char *buffer, int length)
97 {
98
99 errno = 0;
100
101 switch (length)
102 {
103 case 4:
104 *((float *) dest) = (float) strtod (buffer, NULL);
105 break;
106 case 8:
107 *((double *) dest) = strtod (buffer, NULL);
108 break;
109 default:
110 internal_error ("Bad real number kind");
111 }
112
113 if (errno != 0)
114 {
115 generate_error (ERROR_READ_VALUE,
116 "Range error during floating point read");
117 return 1;
118 }
119
120 return 0;
121 }
122
123 static int
124 convert_precision_real (void *dest, int sign,
125 char *buffer, int length, int exponent)
126 {
127 int w, new_dp_pos, i, slen, k, dp;
128 char * p, c;
129 double fval;
130 float tf;
131
132 fval =0.0;
133 tf = 0.0;
134 dp = 0;
135 new_dp_pos = 0;
136
137 slen = strlen (buffer);
138 w = slen;
139 p = buffer;
140
141 /* for (i = w - 1; i > 0; i --)
142 {
143 if (buffer[i] == '0' || buffer[i] == 0)
144 buffer[i] = 0;
145 else
146 break;
147 }
148 */
149 for (i = 0; i < w; i++)
150 {
151 if (buffer[i] == '.')
152 break;
153 }
154
155 new_dp_pos = i;
156 new_dp_pos += exponent;
157
158 while (w > 0)
159 {
160 c = *p;
161 switch (c)
162 {
163 case '0':
164 case '1':
165 case '2':
166 case '3':
167 case '4':
168 case '5':
169 case '6':
170 case '7':
171 case '8':
172 case '9':
173 fval = fval * 10.0 + c - '0';
174 p++;
175 w--;
176 break;
177
178 case '.':
179 dp = 1;
180 p++;
181 w--;
182 break;
183
184 default:
185 p++;
186 w--;
187 break;
188 }
189 }
190
191 if (sign)
192 fval = - fval;
193
194 i = new_dp_pos - slen + dp;
195 k = abs(i);
196 tf = 1.0;
197
198 while (k > 0)
199 {
200 tf *= 10.0 ;
201 k -- ;
202 }
203
204 if (fval != 0.0)
205 {
206 if (i < 0)
207 {
208 fval = fval / tf;
209 }
210 else
211 {
212 fval = fval * tf;
213 }
214 }
215
216 switch (length)
217 {
218 case 4:
219 *((float *) dest) = (float)fval;
220 break;
221 case 8:
222 *((double *) dest) = fval;
223 break;
224 default:
225 internal_error ("Bad real number kind");
226 }
227
228 return 0;
229 }
230
231
232 /* read_l()-- Read a logical value */
233
234 void
235 read_l (fnode * f, char *dest, int length)
236 {
237 char *p;
238 int w;
239
240 w = f->u.w;
241 p = read_block (&w);
242 if (p == NULL)
243 return;
244
245 while (*p == ' ')
246 {
247 if (--w == 0)
248 goto bad;
249 p++;
250 }
251
252 if (*p == '.')
253 {
254 if (--w == 0)
255 goto bad;
256 p++;
257 }
258
259 switch (*p)
260 {
261 case 't':
262 case 'T':
263 set_integer (dest, 1, length);
264 break;
265 case 'f':
266 case 'F':
267 set_integer (dest, 0, length);
268 break;
269 default:
270 bad:
271 generate_error (ERROR_READ_VALUE, "Bad value on logical read");
272 break;
273 }
274 }
275
276
277 /* read_a()-- Read a character record. This one is pretty easy. */
278
279 void
280 read_a (fnode * f, char *p, int length)
281 {
282 char *source;
283 int w, m, n;
284
285 w = f->u.w;
286 if (w == -1) /* '(A)' edit descriptor */
287 w = length;
288
289 source = read_block (&w);
290 if (source == NULL)
291 return;
292 if (w > length)
293 source += (w - length);
294
295 m = (w > length) ? length : w;
296 memcpy (p, source, m);
297
298 n = length - w;
299 if (n > 0)
300 memset (p + m, ' ', n);
301 }
302
303
304 /* eat_leading_spaces()-- Given a character pointer and a width,
305 * ignore the leading spaces. */
306
307 static char *
308 eat_leading_spaces (int *width, char *p)
309 {
310
311 for (;;)
312 {
313 if (*width == 0 || *p != ' ')
314 break;
315
316 (*width)--;
317 p++;
318 }
319
320 return p;
321 }
322
323
324 static char
325 next_char (char **p, int *w)
326 {
327 char c, *q;
328
329 if (*w == 0)
330 return '\0';
331
332 q = *p;
333 c = *q++;
334 *p = q;
335
336 (*w)--;
337
338 if (c != ' ')
339 return c;
340 if (g.blank_status == BLANK_ZERO)
341 return '0';
342
343 /* At this point, the rest of the field has to be trailing blanks */
344
345 while (*w > 0)
346 {
347 if (*q++ != ' ')
348 return '?';
349 (*w)--;
350 }
351
352 *p = q;
353 return '\0';
354 }
355
356
357 /* read_decimal()-- Read a decimal integer value. The values here are
358 * signed values. */
359
360 void
361 read_decimal (fnode * f, char *dest, int length)
362 {
363 unsigned value, maxv, maxv_10;
364 int v, w, negative;
365 char c, *p;
366
367 w = f->u.w;
368 p = read_block (&w);
369 if (p == NULL)
370 return;
371
372 p = eat_leading_spaces (&w, p);
373 if (w == 0)
374 {
375 set_integer (dest, 0, length);
376 return;
377 }
378
379 maxv = max_value (length, 1);
380 maxv_10 = maxv / 10;
381
382 negative = 0;
383 value = 0;
384
385 switch (*p)
386 {
387 case '-':
388 negative = 1;
389 /* Fall through */
390
391 case '+':
392 p++;
393 if (--w == 0)
394 goto bad;
395 /* Fall through */
396
397 default:
398 break;
399 }
400
401 /* At this point we have a digit-string */
402 value = 0;
403
404 for (;;)
405 {
406 c = next_char (&p, &w);
407 if (c == '\0')
408 break;
409
410 if (c < '0' || c > '9')
411 goto bad;
412
413 if (value > maxv_10)
414 goto overflow;
415
416 c -= '0';
417 value = 10 * value;
418
419 if (value > maxv - c)
420 goto overflow;
421 value += c;
422 }
423
424 v = (signed int) value;
425 if (negative)
426 v = -v;
427
428 set_integer (dest, v, length);
429 return;
430
431 bad:
432 generate_error (ERROR_READ_VALUE, "Bad value during integer read");
433 return;
434
435 overflow:
436 generate_error (ERROR_READ_OVERFLOW,
437 "Value overflowed during integer read");
438 return;
439 }
440
441
442 /* read_radix()-- This function reads values for non-decimal radixes.
443 * The difference here is that we treat the values here as unsigned
444 * values for the purposes of overflow. If minus sign is present and
445 * the top bit is set, the value will be incorrect. */
446
447 void
448 read_radix (fnode * f, char *dest, int length, int radix)
449 {
450 unsigned value, maxv, maxv_r;
451 int v, w, negative;
452 char c, *p;
453
454 w = f->u.w;
455 p = read_block (&w);
456 if (p == NULL)
457 return;
458
459 p = eat_leading_spaces (&w, p);
460 if (w == 0)
461 {
462 set_integer (dest, 0, length);
463 return;
464 }
465
466 maxv = max_value (length, 0);
467 maxv_r = maxv / radix;
468
469 negative = 0;
470 value = 0;
471
472 switch (*p)
473 {
474 case '-':
475 negative = 1;
476 /* Fall through */
477
478 case '+':
479 p++;
480 if (--w == 0)
481 goto bad;
482 /* Fall through */
483
484 default:
485 break;
486 }
487
488 /* At this point we have a digit-string */
489 value = 0;
490
491 for (;;)
492 {
493 c = next_char (&p, &w);
494 if (c == '\0')
495 break;
496
497 switch (radix)
498 {
499 case 2:
500 if (c < '0' || c > '1')
501 goto bad;
502 break;
503
504 case 8:
505 if (c < '0' || c > '7')
506 goto bad;
507 break;
508
509 case 16:
510 switch (c)
511 {
512 case '0':
513 case '1':
514 case '2':
515 case '3':
516 case '4':
517 case '5':
518 case '6':
519 case '7':
520 case '8':
521 case '9':
522 break;
523
524 case 'a':
525 case 'b':
526 case 'c':
527 case 'd':
528 case 'e':
529 case 'f':
530 c = c - 'a' + '9' + 1;
531 break;
532
533 case 'A':
534 case 'B':
535 case 'C':
536 case 'D':
537 case 'E':
538 case 'F':
539 c = c - 'A' + '9' + 1;
540 break;
541
542 default:
543 goto bad;
544 }
545
546 break;
547 }
548
549 if (value > maxv_r)
550 goto overflow;
551
552 c -= '0';
553 value = radix * value;
554
555 if (maxv - c < value)
556 goto overflow;
557 value += c;
558 }
559
560 v = (signed int) value;
561 if (negative)
562 v = -v;
563
564 set_integer (dest, v, length);
565 return;
566
567 bad:
568 generate_error (ERROR_READ_VALUE, "Bad value during integer read");
569 return;
570
571 overflow:
572 generate_error (ERROR_READ_OVERFLOW,
573 "Value overflowed during integer read");
574 return;
575 }
576
577
578 /* read_f()-- Read a floating point number with F-style editing, which
579 * is what all of the other floating point descriptors behave as. The
580 * tricky part is that optional spaces are allowed after an E or D,
581 * and the implicit decimal point if a decimal point is not present in
582 * the input. */
583
584 void
585 read_f (fnode * f, char *dest, int length)
586 {
587 int w, seen_dp, exponent;
588 int exponent_sign, val_sign;
589 char *p, *buffer, *n;
590
591 val_sign = 0;
592 seen_dp = 0;
593 w = f->u.w;
594 p = read_block (&w);
595 if (p == NULL)
596 return;
597
598 p = eat_leading_spaces (&w, p);
599 if (w == 0)
600 {
601 switch (length)
602 {
603 case 4:
604 *((float *) dest) = 0.0;
605 break;
606
607 case 8:
608 *((double *) dest) = 0.0;
609 break;
610 }
611
612 return;
613 }
614
615 if (w + 2 < SCRATCH_SIZE)
616 buffer = scratch;
617 else
618 buffer = get_mem (w + 2);
619
620 memset(buffer, 0, w + 2);
621
622 n = buffer;
623
624 /* Optional sign */
625
626 if (*p == '-' || *p == '+')
627 {
628 if (*p == '-')
629 val_sign = 1;
630 p++;
631
632 if (--w == 0)
633 goto bad_float;
634 }
635
636 exponent_sign = 1;
637
638 /* A digit (or a '.') is required at this point */
639
640 if (!isdigit (*p) && *p != '.')
641 goto bad_float;
642
643 while (w > 0)
644 {
645 switch (*p)
646 {
647 case '0':
648 case '1':
649 case '2':
650 case '3':
651 case '4':
652 case '5':
653 case '6':
654 case '7':
655 case '8':
656 case '9':
657 *n++ = *p++;
658 w--;
659 break;
660
661 case '.':
662 if (seen_dp)
663 goto bad_float;
664 seen_dp = 1;
665
666 *n++ = *p++;
667 w--;
668 break;
669
670 case ' ':
671 if (g.blank_status == BLANK_ZERO)
672 *n++ = '0';
673 p++;
674 w--;
675 break;
676
677 case '-':
678 exponent_sign = -1;
679 /* Fall through */
680
681 case '+':
682 p++;
683 w--;
684 goto exp2;
685
686 case 'd':
687 case 'e':
688 case 'D':
689 case 'E':
690 p++;
691 w--;
692 goto exp1;
693
694 default:
695 goto bad_float;
696 }
697 }
698
699 /* No exponent has been seen, so we use the current scale factor */
700
701 exponent = -g.scale_factor;
702 goto done;
703
704 bad_float:
705 generate_error (ERROR_READ_VALUE, "Bad value during floating point read");
706 if (buffer != scratch)
707 free_mem (buffer);
708 return;
709
710 /* At this point the start of an exponent has been found */
711
712 exp1:
713 while (w > 0 && *p == ' ')
714 {
715 w--;
716 p++;
717 }
718
719 switch (*p)
720 {
721 case '-':
722 exponent_sign = -1;
723 /* Fall through */
724
725 case '+':
726 p++;
727 w--;
728 break;
729 }
730
731 if (w == 0)
732 goto bad_float;
733
734 /* At this point a digit string is required. We calculate the value
735 * of the exponent in order to take account of the scale factor and
736 * the d parameter before explict conversion takes place. */
737
738 exp2:
739 if (!isdigit (*p))
740 goto bad_float;
741
742 exponent = *p - '0';
743 p++;
744 w--;
745
746 while (w > 0 && isdigit (*p))
747 {
748 exponent = 10 * exponent + *p - '0';
749 if (exponent > 999999)
750 goto bad_float;
751
752 p++;
753 w--;
754 }
755
756 /* Only allow trailing blanks */
757
758 while (w > 0)
759 {
760 if (*p != ' ')
761 goto bad_float;
762 p++;
763 w--;
764 }
765
766 exponent = exponent * exponent_sign;
767
768 done:
769 if (!seen_dp)
770 exponent -= f->u.real.d;
771
772 /* The number is syntactically correct and ready for conversion.
773 * The only thing that can go wrong at this point is overflow or
774 * underflow. */
775
776 convert_precision_real (dest, val_sign, buffer, length, exponent);
777
778 if (buffer != scratch)
779 free_mem (buffer);
780
781 return;
782 }
783
784
785 /* read_x()-- Deal with the X/TR descriptor. We just read some data
786 * and never look at it. */
787
788 void
789 read_x (fnode * f)
790 {
791 int n;
792
793 n = f->u.n;
794 read_block (&n);
795 }