rts-format.c
1 //! @file rts-io.c
2 //! @author J. Marcel van der Veer
3 //
4 //! @section Copyright
5 //
6 // This file is part of VIF - vintage FORTRAN compiler.
7 // Copyright 2020-2025 J. Marcel van der Veer <algol68g@xs4all.nl>.
8 //
9 //! @section License
10 //
11 // This program is free software; you can redistribute it and/or modify it
12 // under the terms of the GNU General Public License as published by the
13 // Free Software Foundation; either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful, but
17 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 // more details. You should have received a copy of the GNU General Public
20 // License along with this program. If not, see <http://www.gnu.org/licenses/>.
21
22 //! @section Synopsis
23 //!
24 //! Runtime support for formatted IO.
25
26 #include <vif.h>
27 #include <rts-real32.h>
28
29 #define SIGN(z) ((z) == 0 ? 0 : ((z) > 0 ? 1 : 0))
30 #define ERROR_CHAR '*'
31 #define POINT_CHAR '.'
32
33 void xsprintfmt (char *, const char *, ...);
34
35 // __scale__ is set by nP in formats.
36
37 int_4 __scale__ = 1;
38
39 void _fclose (int_4 k)
40 {
41 if (_ffile[k].unit != NO_FILE) {
42 (void) fclose (_ffile[k].unit);
43 _ffile[k].unit = NO_FILE;
44 }
45 }
46
47 static char *plusab (char *buf, char c)
48 {
49 char z[2];
50 z[0] = c;
51 z[1] = '\0';
52 bufcat (buf, z, RECLN);
53 return buf;
54 }
55
56 static char *plusto (char ch, char *buf)
57 {
58 memmove (&buf[1], &buf[0], strlen(buf) + 1);
59 buf[0] = ch;
60 return buf;
61 }
62
63 static char *unsign (char *buf)
64 {
65 if (buf[0] == ' ') {
66 char *q = buf;
67 while (q[0] != '\0') {
68 q[0] = q[1];
69 q++;
70 }
71 }
72 return buf;
73 }
74
75 static char *leading_spaces (char *buf, int_4 width)
76 {
77 if (width > 0) {
78 int_4 j = ABS (width) - (int_4) strlen (buf);
79 while (--j >= 0) {
80 (void) plusto (' ', buf);
81 }
82 }
83 return buf;
84 }
85
86 static char *error_chars (char *buf, int_4 n)
87 {
88 int_4 k = (n != 0 ? ABS (n) : 1);
89 buf[k] = '\0';
90 while (--k >= 0) {
91 buf[k] = ERROR_CHAR;
92 }
93 return buf;
94 }
95
96 static char digchar (int_4 k)
97 {
98 char *tab = "0123456789abcdefghijklmnopqrstuvwxyz";
99 if (k >= 0 && k < (int_4) strlen (tab)) {
100 return tab[k];
101 } else {
102 return ERROR_CHAR;
103 }
104 }
105
106 // INTEGER*8
107
108 char *intnot (char *buf, int_8 k, int_4 width)
109 {
110 int_8 n = ABS (k);
111 buf[0] = '\0';
112 do {
113 (void) plusto (digchar (n % 10), buf);
114 n /= 10;
115 } while (n != 0);
116 if (k < 0) {
117 (void) plusto ('-', buf);
118 }
119 if (width > 0 && strlen (buf) > width) {
120 (void) error_chars (buf, width);
121 } else {
122 (void) leading_spaces (buf, width);
123 }
124 return buf;
125 }
126
127 // REAL*32
128
129 void xsprintfmt (char *buffer, const char *fmt, ...)
130 {
131 NEW_RECORD (ibuff);
132 va_list ap;
133 va_start (ap, fmt);
134 vsprintf (ibuff, fmt, ap);
135 va_end (ap);
136 strcat (buffer, ibuff);
137 }
138
139 static int_4 special_value (char *s, real_32 u, int_4 sign)
140 {
141 if ((xis_pinf (&u))) {
142 if (sign != 0) {
143 *s++ = '+';
144 }
145 strcpy (s, "Inf");
146 return 1;
147 } else if ((xis_minf (&u))) {
148 strcpy (s, "-Inf");
149 return 1;
150 } else if ((xis_nan (&u))) {
151 if (sign != 0) {
152 *s++ = '\?';
153 }
154 strcpy (s, "NaN");
155 return 1;
156 } else {
157 return 0;
158 }
159 }
160
161 char *xsubfixed (char *buffer, real_32 v, logical_4 sign, int_4 digs)
162 {
163 RECCLR (buffer);
164 if ((special_value (buffer, v, sign))) {
165 return buffer;
166 }
167 real_32 u = v;
168 digs = _min (_abs (digs), FLT256_DIG);
169 // Put sign and take abs value.
170 char *p = buffer;
171 if (xlt (u, X_0)) {
172 u = xneg (u);
173 *(p++) = '-';
174 } else if (sign) {
175 *(p++) = '+';
176 } else {
177 *(p++) = ' ';
178 }
179 // Round fraction
180 real_32 eps = xmul(X_1_OVER_2, xtenup (-digs));
181 u = xsum (u, eps);
182 //
183 int_4 before;
184 if (xlt (u, X_10)) {
185 before = 1;
186 } else if (xlt (u, X_100)) {
187 before = 2;
188 } else if (xlt (u, X_1000)) {
189 before = 3;
190 } else {
191 before = (int_4) ceil (xtodbl (xlog10 (u)));
192 }
193 // Integral part.
194 u = xdiv (u, xtenup (before));
195 while (xge (u, X_1)) {
196 u = xdiv (u, X_10);
197 before++;
198 }
199 for (int_4 k = 0; k < before; ++k) {
200 u = xmul (X_10, u);
201 int_4 dig;
202 u = xsfmod (u, &dig);
203 *(p++) = (char) '0' + dig;
204 }
205 // Fraction.
206 *(p++) = '.';
207 for (int_4 k = 0; k < digs; ++k) {
208 u = xmul (X_10, u);
209 int_4 dig;
210 u = xsfmod (u, &dig);
211 *(p++) = (char) '0' + dig;
212 }
213 return buffer;
214 }
215
216 char *xfixed (char *buf, real_32 x, int_4 width, int_4 digs, int_4 precision)
217 {
218 width = _abs (width);
219 digs = _min (abs (digs), precision);
220 xsubfixed (buf, x, FALSE, digs);
221 unsign (buf);
222 if (width > 0 && strlen (buf) > width) {
223 return error_chars (buf, width);
224 } else {
225 return leading_spaces (buf, width);
226 }
227 }
228
229 char *xfloat (char *buf, real_32 z, int_4 width, int_4 digs, int_4 expos, int_4 mult, int_4 precision, char sym)
230 {
231 buf[0] = '\0';
232 width = _abs (width);
233 digs = _min (abs (digs), precision);
234 expos = _abs (expos);
235 if (expos > 5) {
236 return error_chars (buf, width);
237 }
238 // Scientific notation mult = 1, Engineering notation mult = 3
239 mult = _max (1, mult);
240 // Default __scale__ is 1.
241 int_4 q = 1;
242 char *max = "1";
243 real_32 x = xabs (z), lwb, upb;
244 //
245 if (__scale__ < 0 || __scale__ > 3) {
246 __scale__ = 1;
247 }
248 if (mult == 1) {
249 if (__scale__ == 0) {
250 lwb = X_1_OVER_10;
251 upb = X_1;
252 q = 1;
253 max = "0.1";
254 } else if (__scale__ == 1) {
255 lwb = X_1;
256 upb = X_10;
257 q = 0;
258 max = "1";
259 } else if (__scale__ == 2) {
260 lwb = X_10;
261 upb = X_100;
262 q = -1;
263 max = "10";
264 } else if (__scale__ == 3) {
265 lwb = X_100;
266 upb = X_1000;
267 max = "100";
268 q = -2;
269 }
270 }
271 // Standardize.
272 int_4 p = 0;
273 if (xnot0 (&x)) {
274 p = (int_4) round (xtodbl (xlog10 (xabs(x)))) + q;
275 x = xdiv (x, xtenup (p));
276 if (xle (x, lwb)) {
277 x = xmul (x, X_10);
278 p--;
279 }
280 if (xge (x, upb)) {
281 x = xdiv (x, X_10);
282 p++;
283 }
284 while (p % mult != 0) {
285 x = xmul (x, X_10);
286 p--;
287 }
288 }
289 // Form number.
290 NEW_RECORD (mant);
291 xsubfixed (mant, x, FALSE, digs);
292 // Correction of rounding issue by which |mant| equals UPB.
293 if (strchr (mant, ERROR_CHAR) == NO_TEXT && xge (xabs (strtox (mant, NO_REF_TEXT)), upb)) {
294 if (mant[0] == ' ' || mant[0] == '+') {
295 _srecordf (mant, "%c%s", mant[0], max);
296 } else {
297 _srecordf (mant, "%s", max);
298 }
299 if (digs > 0) {
300 plusab (mant, '.');
301 for (int_4 k = 0; k < digs; k++) {
302 plusab (mant, '0');
303 }
304 }
305 p++;
306 }
307 //
308 NEW_RECORD (fmt);
309 if (xsgn (&z) < 0) {
310 mant[0] = '-';
311 }
312 _srecordf (fmt, "%%s%c%%+0%dd", sym, expos);
313 _srecordf (buf, fmt, mant, p);
314 unsign (buf);
315 if (width > 0 && (strchr (buf, ERROR_CHAR) != NO_TEXT || strlen (buf) > width)) {
316 if (digs > 0) {
317 return xfloat (buf, z, width, digs - 1, expos, mult, precision, sym);
318 } else {
319 return error_chars (buf, width);
320 }
321 } else {
322 return leading_spaces (buf, width);
323 }
324 }
325
326 void _fprintf_int_8 (char *str, char *fmt, int_8 elem)
327 {
328 int_4 len = 0;
329 if (fmt[0] == '%') {
330 fmt++;
331 }
332 if (isdigit (fmt[0])) {
333 len = strtol (fmt, NO_REF_TEXT, 10);
334 }
335 intnot (str, elem, len);
336 }
337
338 void _fprintf_real_32 (char *buf, char *fmt, real_32 item, int_4 expw, int_4 precision)
339 {
340 int_4 dec = 0, len = 0, expos = 0;
341 if (fmt[0] == '%') {
342 fmt++;
343 }
344 char expo_char = fmt[strlen (fmt) - 1];
345 if (expo_char == 'n') {
346 expo_char = 'e';
347 } else if (expo_char == 'N') {
348 expo_char = 'E';
349 }
350 char *p1, *p2, *expo;
351 if (fmt[0] == '.') {
352 fmt++;
353 dec = strtol (fmt, &p2, 10);
354 } else {
355 len = strtol (fmt, &p1, 10);
356 dec = strtol (&p1[1], &p2, 10);
357 }
358 if (tolower (expo_char) == 'e') {
359 int_4 ee = strtol (&p2[1], &expo, 10);
360 expos = (ee == 0 ? expw : ee);
361 }
362 if (tolower (expo_char) == 'f') {
363 xfixed (buf, item, len, dec, precision);
364 } else if (tolower (expo[0]) == 'n') {
365 xfloat (buf, item, len, dec, expos, 3, precision, expo_char);
366 } else {
367 xfloat (buf, item, len, dec, expos, 1, precision, expo_char);
368 }
369 return;
370 }
371
372 int_4 _vif_printf (int_4 unit, char *fmt, void *elem, int_4 type, int_4 len)
373 {
374 FTNFILE *_f = &_ffile[unit];
375 if (fmt == NO_TEXT) {
376 return ERR;
377 }
378 if (fmt == FMT_TERM) {
379 return 1;
380 }
381 if (strlen (fmt) == 0) {
382 return 1;
383 }
384 if (strcmp (fmt, "\n") == 0) {
385 fprintf (_f->unit, "\n");
386 return 1;
387 }
388 if (fmt != NO_TEXT && type == NOTYPE) {
389 if (strcmp (fmt, "0") == 0) {
390 __scale__ = 0;
391 } else if (strcmp (fmt, "1") == 0) {
392 __scale__ = 1;
393 } else if (strcmp (fmt, "2") == 0) {
394 __scale__ = 2;
395 } else if (strcmp (fmt, "3") == 0) {
396 __scale__ = 3;
397 } else {
398 fprintf (_f->unit, fmt);
399 }
400 return 1;
401 }
402 //
403 char mod = tolower (fmt[strlen (fmt) - 1]);
404 if (mod == 's') {
405 if (type == NOTYPE) {
406 fprintf (_f->unit, fmt);
407 return 1;
408 } else if (type == CHARACTER) {
409 fprintf (_f->unit, fmt, (char *) elem);
410 return 1;
411 } else if (type == LOGICAL) {
412 fprintf (_f->unit, fmt, (*(int_4 *) elem ? 't' : 'f'));
413 return 1;
414 } else if (type == INTEGER && len == 4) {
415 int_4 awid = len, width;
416 if (sscanf (fmt, "%%%ds", &width) == 1) {
417 awid = _abs (width);
418 }
419 int_4 sum = *(int_4 *) elem;
420 for (int_4 k = 0; k < len && k < awid; k++) {
421 char ch = sum % (UCHAR_MAX + 1);
422 fprintf (_f->unit, "%c", ch);
423 sum /= (UCHAR_MAX + 1);
424 }
425 return 1;
426 } else if (type == REAL && len == 8) {
427 int_4 awid = len, width;
428 if (sscanf (fmt, "%%%ds", &width) == 1) {
429 awid = _abs (width);
430 }
431 real_8 sum = *(real_8 *) elem;
432 for (int_4 k = 0; k < len && k < awid; k++) {
433 char ch = (int_4) fmod (sum, (UCHAR_MAX + 1));
434 fprintf (_f->unit, "%c", ch);
435 sum = floor (sum / (UCHAR_MAX + 1));
436 }
437 return 1;
438 } else {
439 return ERR;
440 }
441 } else if (mod == 'c') {
442 if (type == LOGICAL) {
443 fprintf (_f->unit, fmt, (*(int_4 *) elem ? 't' : 'f'));
444 } else {
445 return ERR;
446 }
447 return 1;
448 } else if (mod == 'd') {
449 // INTEGER
450 if (type == INTEGER && len == 2) {
451 NEW_RECORD (buf);
452 _fprintf_int_8 (buf, fmt, (int_8) *(int_2 *) elem);
453 fprintf (_f->unit, "%s", buf);
454 } else if (type == INTEGER && len == 4) {
455 NEW_RECORD (buf);
456 _fprintf_int_8 (buf, fmt, (int_8) *(int_4 *) elem);
457 fprintf (_f->unit, "%s", buf);
458 } else if (type == INTEGER && len == 8) {
459 NEW_RECORD (buf);
460 _fprintf_int_8 (buf, fmt, (int_8) *(int_8 *) elem);
461 fprintf (_f->unit, "%s", buf);
462 } else if (type == INTEGER && len == 16) {
463 NEW_RECORD (buf);
464 _fprintf_int_8 (buf, fmt, (int_8) *(int_8 *) elem);
465 fprintf (_f->unit, "%s", buf);
466 } else {
467 return ERR;
468 }
469 return 1;
470 } else if (mod == 'e' || mod == 'n' || mod == 'f') {
471 // REAL and COMPLEX
472 NEW_RECORD (buf);
473 if (type == INTEGER && len == 2) {
474 _fprintf_real_32 (buf, fmt, flttox ((real_4) *(int_2 *) elem), 4, FLT_DIG);
475 fprintf (_f->unit, "%s", buf);
476 } else if (type == INTEGER && len == 4) {
477 _fprintf_real_32 (buf, fmt, dbltox ((real_8) *(int_4 *) elem), 4, FLT_DIG);
478 fprintf (_f->unit, "%s", buf);
479 } else if (type == INTEGER && len == 8) {
480 _fprintf_real_32 (buf, fmt, dbltox ((real_8) *(int_8 *) elem), 4, FLT_DIG);
481 fprintf (_f->unit, "%s", buf);
482 } else if (type == REAL && len == 4) {
483 _fprintf_real_32 (buf, fmt, flttox (*(real_4 *) elem), 4, FLT_DIG);
484 fprintf (_f->unit, "%s", buf);
485 } else if (type == REAL && len == 8) {
486 _fprintf_real_32 (buf, fmt, dbltox (*(real_8 *) elem), 4, DBL_DIG);
487 fprintf (_f->unit, "%s", buf);
488 } else if (type == REAL && len == 16) {
489 _fprintf_real_32 (buf, fmt, quadtox (*(real_16 *) elem), 5, FLT128_DIG);
490 fprintf (_f->unit, "%s", buf);
491 } else if (type == REAL && len == 32) {
492 _fprintf_real_32 (buf, fmt, *(real_32 *) elem, 5, FLT256_DIG);
493 fprintf (_f->unit, "%s", buf);
494 } else if (type == COMPLEX && len == 8) {
495 real_4 z = crealf (*(complex_8 *) elem);
496 _vif_printf (unit, fmt, &z, REAL, 4);
497 } else if (type == COMPLEX && len == -8) {
498 real_4 z = cimagf (*(complex_8 *) elem);
499 _vif_printf (unit, fmt, &z, REAL, 4);
500 } else if (type == COMPLEX && len == 16) {
501 real_8 z = creal (*(complex_16 *) elem);
502 _vif_printf (unit, fmt, &z, REAL, 8);
503 } else if (type == COMPLEX && len == -16) {
504 real_8 z = cimag (*(complex_16 *) elem);
505 _vif_printf (unit, fmt, &z, REAL, 8);
506 } else if (type == COMPLEX && len == 32) {
507 real_16 z = crealq (*(complex_32 *) elem);
508 _vif_printf (unit, fmt, &z, REAL, 16);
509 } else if (type == COMPLEX && len == -32) {
510 real_16 z = cimagq (*(complex_32 *) elem);
511 _vif_printf (unit, fmt, &z, REAL, 16);
512 } else if (type == COMPLEX && len == 64) {
513 real_32 z = cxreal (*(complex_64 *) elem);
514 _vif_printf (unit, fmt, &z, REAL, 32);
515 } else if (type == COMPLEX && len == -64) {
516 real_32 z = cximag (*(complex_64 *) elem);
517 _vif_printf (unit, fmt, &z, REAL, 32);
518 } else {
519 return ERR;
520 }
521 return 1;
522 }
523 return ERR;
524 }
525
526 void _fscanf_real (char *str, FTNFILE * _f, int_4 width, int_4 buflen)
527 {
528 while (_f->buff_pos < buflen && _f->buff[_f->buff_pos] == ' ') {
529 _f->buff_pos++;
530 }
531 for (int_4 k = 0; k < width && _f->buff_pos < buflen && _f->buff[_f->buff_pos] != ' '; k++) {
532 str[k] = _f->buff[_f->buff_pos++];
533 str[k + 1] = '\0';
534 }
535 }
536
537 int_4 _vif_scanf (int_4 unit, char *fmt, void *elem, int_4 type, int_4 len)
538 {
539 int_4 width = 0, rc = 0, N = 0;
540 FTNFILE *_f = &_ffile[unit];
541 // A NOP.
542 if (fmt == FMT_TERM) {
543 return 1;
544 }
545 // Re-init on next call.
546 if (fmt == NO_TEXT) {
547 _f->buff_init = FALSE;
548 return 1;
549 }
550 if (strlen (fmt) == 0) {
551 return 1;
552 }
553 // (Re)init if needed.
554 if (!_f->buff_init) {
555 _init_file_buffer (unit);
556 }
557 if (strcmp (fmt, "\n") == 0) {
558 // Reading newline just reinits the buffer.
559 _init_file_buffer (unit);
560 return 1;
561 }
562 // Textual strings are skipped and not checked.
563 if (fmt != NO_TEXT && type == NOTYPE) {
564 int_4 awid = strlen (fmt);
565 if (_f->buff_pos + awid < _f->buff_len) {
566 _f->buff_pos += awid;
567 }
568 return 1;
569 }
570 // Fortran items A, D, E, F, I and Q.
571 char mod = fmt[strlen (fmt) - 1];
572 if (mod == 's' && sscanf (fmt, "%%%ds", &width) == 1) {
573 int_4 awid = _abs (width);
574 if (type == NOTYPE || elem == NO_TEXT) {
575 if (_f->buff_pos + awid > _f->buff_len) {
576 return ERR;
577 }
578 _f->buff_pos += awid; // Just skip it. Fortran would check.
579 return 1;
580 }
581 if (type == CHARACTER) {
582 char *str = (char *) elem;
583 for (int_4 k = 0; k < awid && _f->buff_pos < _f->buff_len; k++) {
584 str[k] = _f->buff[_f->buff_pos++];
585 }
586 // In VIF trailing space is cut.
587 for (int_4 k = strlen (str) - 1; k > 0 && str[k] == ' '; k--) {
588 str[k] = '\0';
589 }
590 return 1;
591 } else if (type == INTEGER && len == 4) {
592 NEW_RECORD (str);
593 int_4 k;
594 for (k = 0; k < awid && _f->buff_pos < _f->buff_len; k++) {
595 str[k] = _f->buff[_f->buff_pos++];
596 }
597 str[k] = '\0';
598 *(int_4 *) elem = _str_to_int4 (str);
599 return 1;
600 } else if (type == REAL && len == 8) {
601 NEW_RECORD (str);
602 int_4 k;
603 for (k = 0; k < awid && _f->buff_pos < _f->buff_len; k++) {
604 str[k] = _f->buff[_f->buff_pos++];
605 }
606 str[k] = '\0';
607 *(real_8 *) elem = _str_to_real8 (str);
608 return 1;
609 }
610 return 0;
611 }
612 if (mod == 'c' && strcmp (fmt, "%c") == 0) {
613 NEW_RECORD (nfmt);
614 if (len == 4) {
615 char ch;
616 _srecordf (nfmt, "%%c%%n");
617 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, (char *) &ch, &N);
618 *(logical_4 *) elem = (ch == 't');
619 }
620 _f->buff_pos += N;
621 return rc;
622 }
623 if (mod == 'd' && strcmp (fmt, "%d") == 0) {
624 NEW_RECORD (nfmt);
625 if (len == 2) {
626 int_4 i;
627 _srecordf (nfmt, "%%d%%n");
628 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, (int_4 *) &i, &N);
629 *(int_2 *) elem = i;
630 } else if (len == 4) {
631 _srecordf (nfmt, "%%d%%n");
632 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, (int_4 *) elem, &N);
633 } else if (len == 8) {
634 _srecordf (nfmt, "%%lld%%nn");
635 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, (int_8 *) elem, &N);
636 }
637 _f->buff_pos += N;
638 return rc;
639 }
640 if (mod == 'd' && type == INTEGER && sscanf (fmt, "%%%dd", &width) == 1) {
641 NEW_RECORD (nfmt);
642 int_4 awid = _abs (width);
643 if (_f->buff_pos + awid > _f->buff_len) {
644 return ERR;
645 }
646 // Vintage Fortran reads blanks as zero.
647 char *q = &_f->buff[_f->buff_pos];
648 int_4 k = width - 1;
649 while (k >= 0) {
650 if (q[k] == ' ') {
651 q[k] = '0';
652 } else if (!isdigit(q[k])) {
653 break;
654 }
655 k--;
656 }
657 //
658 if (len == 2) {
659 int_4 i;
660 _srecordf (nfmt, "%%%dd", width);
661 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, (int_4 *) &i);
662 *(int_2 *) elem = i;
663 } else if (len == 4) {
664 _srecordf (nfmt, "%%%dd", width);
665 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, (int_4 *) elem);
666 } else if (len == 8) {
667 _srecordf (nfmt, "%%%dlld", width);
668 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, (int_8 *) elem);
669 }
670 _f->buff_pos += awid;
671 return rc;
672 }
673 // REAL, standard format
674 if (type == REAL && strcmp (fmt, "%e") == 0) {
675 if (len == 4) {
676 NEW_RECORD (nfmt);
677 _srecordf (nfmt, "%%e%%n");
678 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, (real_4 *) elem, &N);
679 _f->buff_pos += N;
680 return rc;
681 } else if (len == 8) {
682 NEW_RECORD (nfmt);
683 _srecordf (nfmt, "%%le%%n");
684 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, (real_8 *) elem, &N);
685 _f->buff_pos += N;
686 return rc;
687 } else if (len == 16) {
688 NEW_RECORD (str);
689 _fscanf_real (str, _f, RECLN - 1, _f->buff_len);
690 *(real_16 *) (elem) = _strtoquad (str, NO_REF_TEXT);
691 return 1;
692 } else if (len == 32) {
693 NEW_RECORD (str);
694 _fscanf_real (str, _f, RECLN - 1, _f->buff_len);
695 *(real_32 *) (elem) = strtox (str, NO_REF_TEXT);
696 return 1;
697 }
698 }
699 // REAL, format, note that only width can be specified.
700 if ((mod == 'e' || mod == 'f') && type == REAL && sscanf (fmt, "%%%d", &width) == 1) {
701 int_4 awid = _abs (width);
702 if (_f->buff_pos + awid > _f->buff_len) {
703 return ERR;
704 }
705 if (len == 4) {
706 rc = sscanf (&_f->buff[_f->buff_pos], fmt, (real_4 *) elem);
707 _f->buff_pos += width;
708 } else if (len == 8) {
709 NEW_RECORD (nfmt);
710 _srecordf (nfmt, "%%%dl%c", width, mod);
711 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, (real_8 *) elem);
712 _f->buff_pos += width;
713 } else if (len == 16) {
714 NEW_RECORD (str);
715 _fscanf_real (str, _f, (awid > RECLN - 1 ? RECLN - 1 : awid), _f->buff_len);
716 *(real_16 *) (elem) = _strtoquad (str, NO_REF_TEXT);
717 return 1;
718 } else if (len == 32) {
719 NEW_RECORD (str);
720 _fscanf_real (str, _f, (awid > RECLN - 1 ? RECLN - 1 : awid), _f->buff_len);
721 *(real_32 *) (elem) = strtox (str, NO_REF_TEXT);
722 return 1;
723 }
724 return rc;
725 }
726 // COMPLEX, standard
727 if (mod == 'e' && type == COMPLEX && strcmp (fmt, "%e") == 0) {
728 if (_abs (len) == 8) {
729 NEW_RECORD (nfmt);
730 real_4 x;
731 complex_8 *z = (complex_8 *) elem;
732 _srecordf (nfmt, "%%e%%n");
733 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, &x, &N);
734 _f->buff_pos += N;
735 if (len > 0) {
736 *z = CMPLXF (x, 0);
737 } else {
738 *z = CMPLXF (crealf (*z), x);
739 }
740 return rc;
741 } else if (_abs (len) == 16) {
742 NEW_RECORD (nfmt);
743 real_8 x;
744 complex_16 *z = (complex_16 *) elem;
745 _srecordf (nfmt, "%%le%%n");
746 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, &x, &N);
747 _f->buff_pos += N;
748 if (len > 0) {
749 *z = CMPLX (x, 0);
750 } else {
751 *z = CMPLX (creal (*z), x);
752 }
753 return rc;
754 } else if (_abs (len) == 32) {
755 NEW_RECORD (str);
756 complex_32 *z = (complex_32 *) elem;
757 _fscanf_real (str, _f, RECLN - 1, _f->buff_len);
758 if (len > 0) {
759 *z = CMPLXQ (_strtoquad (str, NO_REF_TEXT), 0.0q);
760 } else {
761 *z = CMPLXQ (crealq (*z), _strtoquad (str, NO_REF_TEXT));
762 }
763 return 1;
764 } else if (_abs (len) == 64) {
765 NEW_RECORD (str);
766 complex_64 *z = (complex_64 *) elem;
767 _fscanf_real (str, _f, RECLN - 1, _f->buff_len);
768 if (len > 0) {
769 z->re = strtox (str, NO_REF_TEXT);
770 } else {
771 z->im = strtox (str, NO_REF_TEXT);
772 }
773 return 1;
774 }
775 }
776 // COMPLEX, format, note that only width can be specified.
777 if ((mod == 'e' || mod == 'f') && type == COMPLEX && sscanf (fmt, "%%%de", &width) == 1) {
778 int_4 awid = _abs (width);
779 if (_f->buff_pos + awid > _f->buff_len) {
780 return ERR;
781 }
782 if (_abs (len) == 8) {
783 real_4 x;
784 complex_8 *z = (complex_8 *) elem;
785 rc = sscanf (&_f->buff[_f->buff_pos], fmt, &x);
786 _f->buff_pos += width;
787 if (len > 0) {
788 *z = CMPLXF (x, 0);
789 } else {
790 *z = CMPLXF (crealf (*z), x);
791 }
792 return rc;
793 } else if (_abs (len) == 16) {
794 real_8 x;
795 complex_16 *z = (complex_16 *) elem;
796 NEW_RECORD (nfmt);
797 _srecordf (nfmt, "%%%dl%c", width, mod);
798 rc = sscanf (&_f->buff[_f->buff_pos], nfmt, &x);
799 _f->buff_pos += width;
800 if (len > 0) {
801 *z = CMPLX (x, 0);
802 } else {
803 *z = CMPLX (creal (*z), x);
804 }
805 return rc;
806 } else if (_abs (len) == 32) {
807 NEW_RECORD (str);
808 complex_32 *z = (complex_32 *) elem;
809 _fscanf_real (str, _f, (awid > RECLN - 1 ? RECLN - 1 : awid), _f->buff_len);
810 if (len > 0) {
811 *z = CMPLXQ (_strtoquad (str, NO_REF_TEXT), 0.0q);
812 } else {
813 *z = CMPLXQ (crealq (*z), _strtoquad (str, NO_REF_TEXT));
814 }
815 return 1;
816 } else if (_abs (len) == 64) {
817 NEW_RECORD (str);
818 complex_64 *z = (complex_64 *) elem;
819 _fscanf_real (str, _f, (awid > RECLN - 1 ? RECLN - 1 : awid), _f->buff_len);
820 if (len > 0) {
821 z->re = strtox (str, NO_REF_TEXT);
822 } else {
823 z->im = strtox (str, NO_REF_TEXT);
824 }
825 return 1;
826 }
827 }
828 // No conversion :-(
829 return ERR;
830 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|