| #include "config.h" |
| #include <ctype.h> |
| #include "f2c.h" |
| #include "fio.h" |
| |
| extern int f__cursor; |
| #undef abs |
| #undef min |
| #undef max |
| #include <stdlib.h> |
| |
| #include "fmt.h" |
| #include "fp.h" |
| |
| static int |
| rd_Z (Uint * n, int w, ftnlen len) |
| { |
| long x[9]; |
| char *s, *s0, *s1, *se, *t; |
| int ch, i, w1, w2; |
| static char hex[256]; |
| static int one = 1; |
| int bad = 0; |
| |
| if (!hex['0']) |
| { |
| s = "0123456789"; |
| while ((ch = *s++)) |
| hex[ch] = ch - '0' + 1; |
| s = "ABCDEF"; |
| while ((ch = *s++)) |
| hex[ch] = hex[ch + 'a' - 'A'] = ch - 'A' + 11; |
| } |
| s = s0 = (char *) x; |
| s1 = (char *) &x[4]; |
| se = (char *) &x[8]; |
| if (len > 4 * (ftnlen) sizeof (long)) |
| return errno = 117; |
| while (w) |
| { |
| GET (ch); |
| if (ch == ',' || ch == '\n') |
| break; |
| w--; |
| if (ch > ' ') |
| { |
| if (!hex[ch & 0xff]) |
| bad++; |
| *s++ = ch; |
| if (s == se) |
| { |
| /* discard excess characters */ |
| for (t = s0, s = s1; t < s1;) |
| *t++ = *s++; |
| s = s1; |
| } |
| } |
| } |
| if (bad) |
| return errno = 115; |
| w = (int) len; |
| w1 = s - s0; |
| w2 = (w1 + 1) >> 1; |
| t = (char *) n; |
| if (*(char *) &one) |
| { |
| /* little endian */ |
| t += w - 1; |
| i = -1; |
| } |
| else |
| i = 1; |
| for (; w > w2; t += i, --w) |
| *t = 0; |
| if (!w) |
| return 0; |
| if (w < w2) |
| s0 = s - (w << 1); |
| else if (w1 & 1) |
| { |
| *t = hex[*s0++ & 0xff] - 1; |
| if (!--w) |
| return 0; |
| t += i; |
| } |
| do |
| { |
| *t = (hex[*s0 & 0xff] - 1) << 4 | (hex[s0[1] & 0xff] - 1); |
| t += i; |
| s0 += 2; |
| } |
| while (--w); |
| return 0; |
| } |
| |
| static int |
| rd_I (Uint * n, int w, ftnlen len, register int base) |
| { |
| int ch, sign; |
| longint x = 0; |
| |
| if (w <= 0) |
| goto have_x; |
| for (;;) |
| { |
| GET (ch); |
| if (ch != ' ') |
| break; |
| if (!--w) |
| goto have_x; |
| } |
| sign = 0; |
| switch (ch) |
| { |
| case ',': |
| case '\n': |
| w = 0; |
| goto have_x; |
| case '-': |
| sign = 1; |
| case '+': |
| break; |
| default: |
| if (ch >= '0' && ch <= '9') |
| { |
| x = ch - '0'; |
| break; |
| } |
| goto have_x; |
| } |
| while (--w) |
| { |
| GET (ch); |
| if (ch >= '0' && ch <= '9') |
| { |
| x = x * base + ch - '0'; |
| continue; |
| } |
| if (ch != ' ') |
| { |
| if (ch == '\n' || ch == ',') |
| w = 0; |
| break; |
| } |
| if (f__cblank) |
| x *= base; |
| } |
| if (sign) |
| x = -x; |
| have_x: |
| if (len == sizeof (integer)) |
| n->il = x; |
| else if (len == sizeof (char)) |
| n->ic = (char) x; |
| #ifdef Allow_TYQUAD |
| else if (len == sizeof (longint)) |
| n->ili = x; |
| #endif |
| else |
| n->is = (short) x; |
| if (w) |
| { |
| while (--w) |
| GET (ch); |
| return errno = 115; |
| } |
| return 0; |
| } |
| |
| static int |
| rd_L (ftnint * n, int w, ftnlen len) |
| { |
| int ch, dot, lv; |
| |
| if (w <= 0) |
| goto bad; |
| for (;;) |
| { |
| GET (ch); |
| --w; |
| if (ch != ' ') |
| break; |
| if (!w) |
| goto bad; |
| } |
| dot = 0; |
| retry: |
| switch (ch) |
| { |
| case '.': |
| if (dot++ || !w) |
| goto bad; |
| GET (ch); |
| --w; |
| goto retry; |
| case 't': |
| case 'T': |
| lv = 1; |
| break; |
| case 'f': |
| case 'F': |
| lv = 0; |
| break; |
| default: |
| bad: |
| for (; w > 0; --w) |
| GET (ch); |
| /* no break */ |
| case ',': |
| case '\n': |
| return errno = 116; |
| } |
| /* The switch statement that was here |
| didn't cut it: It broke down for targets |
| where sizeof(char) == sizeof(short). */ |
| if (len == sizeof (char)) |
| *(char *) n = (char) lv; |
| else if (len == sizeof (short)) |
| *(short *) n = (short) lv; |
| else |
| *n = lv; |
| while (w-- > 0) |
| { |
| GET (ch); |
| if (ch == ',' || ch == '\n') |
| break; |
| } |
| return 0; |
| } |
| |
| static int |
| rd_F (ufloat * p, int w, int d, ftnlen len) |
| { |
| char s[FMAX + EXPMAXDIGS + 4]; |
| register int ch; |
| register char *sp, *spe, *sp1; |
| double x; |
| int scale1, se; |
| long e, exp; |
| |
| sp1 = sp = s; |
| spe = sp + FMAX; |
| exp = -d; |
| x = 0.; |
| |
| do |
| { |
| GET (ch); |
| w--; |
| } |
| while (ch == ' ' && w); |
| switch (ch) |
| { |
| case '-': |
| *sp++ = ch; |
| sp1++; |
| spe++; |
| case '+': |
| if (!w) |
| goto zero; |
| --w; |
| GET (ch); |
| } |
| while (ch == ' ') |
| { |
| blankdrop: |
| if (!w--) |
| goto zero; |
| GET (ch); |
| } |
| while (ch == '0') |
| { |
| if (!w--) |
| goto zero; |
| GET (ch); |
| } |
| if (ch == ' ' && f__cblank) |
| goto blankdrop; |
| scale1 = f__scale; |
| while (isdigit (ch)) |
| { |
| digloop1: |
| if (sp < spe) |
| *sp++ = ch; |
| else |
| ++exp; |
| digloop1e: |
| if (!w--) |
| goto done; |
| GET (ch); |
| } |
| if (ch == ' ') |
| { |
| if (f__cblank) |
| { |
| ch = '0'; |
| goto digloop1; |
| } |
| goto digloop1e; |
| } |
| if (ch == '.') |
| { |
| exp += d; |
| if (!w--) |
| goto done; |
| GET (ch); |
| if (sp == sp1) |
| { /* no digits yet */ |
| while (ch == '0') |
| { |
| skip01: |
| --exp; |
| skip0: |
| if (!w--) |
| goto done; |
| GET (ch); |
| } |
| if (ch == ' ') |
| { |
| if (f__cblank) |
| goto skip01; |
| goto skip0; |
| } |
| } |
| while (isdigit (ch)) |
| { |
| digloop2: |
| if (sp < spe) |
| { |
| *sp++ = ch; |
| --exp; |
| } |
| digloop2e: |
| if (!w--) |
| goto done; |
| GET (ch); |
| } |
| if (ch == ' ') |
| { |
| if (f__cblank) |
| { |
| ch = '0'; |
| goto digloop2; |
| } |
| goto digloop2e; |
| } |
| } |
| switch (ch) |
| { |
| default: |
| break; |
| case '-': |
| se = 1; |
| goto signonly; |
| case '+': |
| se = 0; |
| goto signonly; |
| case 'e': |
| case 'E': |
| case 'd': |
| case 'D': |
| if (!w--) |
| goto bad; |
| GET (ch); |
| while (ch == ' ') |
| { |
| if (!w--) |
| goto bad; |
| GET (ch); |
| } |
| se = 0; |
| switch (ch) |
| { |
| case '-': |
| se = 1; |
| case '+': |
| signonly: |
| if (!w--) |
| goto bad; |
| GET (ch); |
| } |
| while (ch == ' ') |
| { |
| if (!w--) |
| goto bad; |
| GET (ch); |
| } |
| if (!isdigit (ch)) |
| goto bad; |
| |
| e = ch - '0'; |
| for (;;) |
| { |
| if (!w--) |
| { |
| ch = '\n'; |
| break; |
| } |
| GET (ch); |
| if (!isdigit (ch)) |
| { |
| if (ch == ' ') |
| { |
| if (f__cblank) |
| ch = '0'; |
| else |
| continue; |
| } |
| else |
| break; |
| } |
| e = 10 * e + ch - '0'; |
| if (e > EXPMAX && sp > sp1) |
| goto bad; |
| } |
| if (se) |
| exp -= e; |
| else |
| exp += e; |
| scale1 = 0; |
| } |
| switch (ch) |
| { |
| case '\n': |
| case ',': |
| break; |
| default: |
| bad: |
| return (errno = 115); |
| } |
| done: |
| if (sp > sp1) |
| { |
| while (*--sp == '0') |
| ++exp; |
| if (exp -= scale1) |
| sprintf (sp + 1, "e%ld", exp); |
| else |
| sp[1] = 0; |
| x = atof (s); |
| } |
| zero: |
| if (len == sizeof (real)) |
| p->pf = x; |
| else |
| p->pd = x; |
| return (0); |
| } |
| |
| |
| static int |
| rd_A (char *p, ftnlen len) |
| { |
| int i, ch; |
| for (i = 0; i < len; i++) |
| { |
| GET (ch); |
| *p++ = VAL (ch); |
| } |
| return (0); |
| } |
| static int |
| rd_AW (char *p, int w, ftnlen len) |
| { |
| int i, ch; |
| if (w >= len) |
| { |
| for (i = 0; i < w - len; i++) |
| GET (ch); |
| for (i = 0; i < len; i++) |
| { |
| GET (ch); |
| *p++ = VAL (ch); |
| } |
| return (0); |
| } |
| for (i = 0; i < w; i++) |
| { |
| GET (ch); |
| *p++ = VAL (ch); |
| } |
| for (i = 0; i < len - w; i++) |
| *p++ = ' '; |
| return (0); |
| } |
| static int |
| rd_H (int n, char *s) |
| { |
| int i, ch; |
| for (i = 0; i < n; i++) |
| if ((ch = (*f__getn) ()) < 0) |
| return (ch); |
| else |
| *s++ = ch == '\n' ? ' ' : ch; |
| return (1); |
| } |
| static int |
| rd_POS (char *s) |
| { |
| char quote; |
| int ch; |
| quote = *s++; |
| for (; *s; s++) |
| if (*s == quote && *(s + 1) != quote) |
| break; |
| else if ((ch = (*f__getn) ()) < 0) |
| return (ch); |
| else |
| *s = ch == '\n' ? ' ' : ch; |
| return (1); |
| } |
| |
| int |
| rd_ed (struct syl * p, char *ptr, ftnlen len) |
| { |
| int ch; |
| for (; f__cursor > 0; f__cursor--) |
| if ((ch = (*f__getn) ()) < 0) |
| return (ch); |
| if (f__cursor < 0) |
| { |
| if (f__recpos + f__cursor < 0) /*err(elist->cierr,110,"fmt") */ |
| f__cursor = -f__recpos; /* is this in the standard? */ |
| if (f__external == 0) |
| { |
| extern char *f__icptr; |
| f__icptr += f__cursor; |
| } |
| else if (f__curunit && f__curunit->useek) |
| FSEEK (f__cf, (off_t) f__cursor, SEEK_CUR); |
| else |
| err (f__elist->cierr, 106, "fmt"); |
| f__recpos += f__cursor; |
| f__cursor = 0; |
| } |
| switch (p->op) |
| { |
| default: |
| fprintf (stderr, "rd_ed, unexpected code: %d\n", p->op); |
| sig_die (f__fmtbuf, 1); |
| case IM: |
| case I: |
| ch = rd_I ((Uint *) ptr, p->p1, len, 10); |
| break; |
| |
| /* O and OM don't work right for character, double, complex, */ |
| /* or doublecomplex, and they differ from Fortran 90 in */ |
| /* showing a minus sign for negative values. */ |
| |
| case OM: |
| case O: |
| ch = rd_I ((Uint *) ptr, p->p1, len, 8); |
| break; |
| case L: |
| ch = rd_L ((ftnint *) ptr, p->p1, len); |
| break; |
| case A: |
| ch = rd_A (ptr, len); |
| break; |
| case AW: |
| ch = rd_AW (ptr, p->p1, len); |
| break; |
| case E: |
| case EE: |
| case D: |
| case G: |
| case GE: |
| case F: |
| ch = rd_F ((ufloat *) ptr, p->p1, p->p2.i[0], len); |
| break; |
| |
| /* Z and ZM assume 8-bit bytes. */ |
| |
| case ZM: |
| case Z: |
| ch = rd_Z ((Uint *) ptr, p->p1, len); |
| break; |
| } |
| if (ch == 0) |
| return (ch); |
| else if (ch == EOF) |
| return (EOF); |
| if (f__cf) |
| clearerr (f__cf); |
| return (errno); |
| } |
| |
| int |
| rd_ned (struct syl * p) |
| { |
| switch (p->op) |
| { |
| default: |
| fprintf (stderr, "rd_ned, unexpected code: %d\n", p->op); |
| sig_die (f__fmtbuf, 1); |
| case APOS: |
| return (rd_POS (p->p2.s)); |
| case H: |
| return (rd_H (p->p1, p->p2.s)); |
| case SLASH: |
| return ((*f__donewrec) ()); |
| case TR: |
| case X: |
| f__cursor += p->p1; |
| return (1); |
| case T: |
| f__cursor = p->p1 - f__recpos - 1; |
| return (1); |
| case TL: |
| f__cursor -= p->p1; |
| if (f__cursor < -f__recpos) /* TL1000, 1X */ |
| f__cursor = -f__recpos; |
| return (1); |
| } |
| } |