#include "config.h" #include #include "f2c.h" #include "fio.h" /* Compile with -DF8X_NML_ELIDE_QUOTES to permit eliding quotation */ /* marks in namelist input a la the Fortran 8X Draft published in */ /* the May 1989 issue of Fortran Forum. */ extern char *f__fmtbuf; extern int f__fmtlen; #ifdef Allow_TYQUAD static longint f__llx; #endif #undef abs #undef min #undef max #include #include "fmt.h" #include "lio.h" #include "fp.h" int (*f__lioproc) (ftnint *, char *, ftnlen, ftnint), (*l_getc) (void), (*l_ungetc) (int, FILE *); int l_eof; #define isblnk(x) (f__ltab[x+1]&B) #define issep(x) (f__ltab[x+1]&SX) #define isapos(x) (f__ltab[x+1]&AX) #define isexp(x) (f__ltab[x+1]&EX) #define issign(x) (f__ltab[x+1]&SG) #define iswhit(x) (f__ltab[x+1]&WH) #define SX 1 #define B 2 #define AX 4 #define EX 8 #define SG 16 #define WH 32 char f__ltab[128 + 1] = { /* offset one for EOF */ 0, 0, 0, AX, 0, 0, 0, 0, 0, 0, WH | B, SX | WH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, SX | B | WH, 0, AX, 0, 0, 0, 0, AX, 0, 0, 0, SG, SX, SG, 0, SX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EX, EX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, AX, 0, 0, 0, EX, EX, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #ifdef ungetc static int un_getc (int x, FILE * f__cf) { return ungetc (x, f__cf); } #else #define un_getc ungetc extern int ungetc (int, FILE *); /* for systems with a buggy stdio.h */ #endif int t_getc (void) { int ch; if (f__curunit->uend) return (EOF); if ((ch = getc (f__cf)) != EOF) return (ch); if (feof (f__cf)) f__curunit->uend = l_eof = 1; return (EOF); } integer e_rsle (void) { int ch; f__init = 1; if (f__curunit->uend) return (0); while ((ch = t_getc ()) != '\n') if (ch == EOF) { if (feof (f__cf)) f__curunit->uend = l_eof = 1; return EOF; } return (0); } flag f__lquit; int f__lcount, f__ltype, nml_read; char *f__lchar; double f__lx, f__ly; #define ERR(x) if((n=(x))) {f__init &= ~2; return(n);} #define GETC(x) (x=(*l_getc)()) #define Ungetc(x,y) (*l_ungetc)(x,y) static int l_R (int poststar, int reqint) { char s[FMAX + EXPMAXDIGS + 4]; register int ch; register char *sp, *spe, *sp1; long e, exp; int havenum, havestar, se; if (!poststar) { if (f__lcount > 0) return (0); f__lcount = 1; } #ifdef Allow_TYQUAD f__llx = 0; #endif f__ltype = 0; exp = 0; havestar = 0; retry: sp1 = sp = s; spe = sp + FMAX; havenum = 0; switch (GETC (ch)) { case '-': *sp++ = ch; sp1++; spe++; case '+': GETC (ch); } while (ch == '0') { ++havenum; GETC (ch); } while (isdigit (ch)) { if (sp < spe) *sp++ = ch; else ++exp; GETC (ch); } if (ch == '*' && !poststar) { if (sp == sp1 || exp || *s == '-') { errfl (f__elist->cierr, 112, "bad repetition count"); } poststar = havestar = 1; *sp = 0; f__lcount = atoi (s); goto retry; } if (ch == '.') { #ifndef ALLOW_FLOAT_IN_INTEGER_LIST_INPUT if (reqint) errfl (f__elist->cierr, 115, "invalid integer"); #endif GETC (ch); if (sp == sp1) while (ch == '0') { ++havenum; --exp; GETC (ch); } while (isdigit (ch)) { if (sp < spe) { *sp++ = ch; --exp; } GETC (ch); } } havenum += sp - sp1; se = 0; if (issign (ch)) goto signonly; if (havenum && isexp (ch)) { #ifndef ALLOW_FLOAT_IN_INTEGER_LIST_INPUT if (reqint) errfl (f__elist->cierr, 115, "invalid integer"); #endif GETC (ch); if (issign (ch)) { signonly: if (ch == '-') se = 1; GETC (ch); } if (!isdigit (ch)) { bad: errfl (f__elist->cierr, 112, "exponent field"); } e = ch - '0'; while (isdigit (GETC (ch))) { e = 10 * e + ch - '0'; if (e > EXPMAX) goto bad; } if (se) exp -= e; else exp += e; } (void) Ungetc (ch, f__cf); if (sp > sp1) { ++havenum; while (*--sp == '0') ++exp; if (exp) sprintf (sp + 1, "e%ld", exp); else sp[1] = 0; f__lx = atof (s); #ifdef Allow_TYQUAD if (reqint & 2 && (se = sp - sp1 + exp) > 14 && se < 20) { /* Assuming 64-bit longint and 32-bit long. */ if (exp < 0) sp += exp; if (sp1 <= sp) { f__llx = *sp1 - '0'; while (++sp1 <= sp) f__llx = 10 * f__llx + (*sp1 - '0'); } while (--exp >= 0) f__llx *= 10; if (*s == '-') f__llx = -f__llx; } #endif } else f__lx = 0.; if (havenum) f__ltype = TYLONG; else switch (ch) { case ',': case '/': break; default: if (havestar && (ch == ' ' || ch == '\t' || ch == '\n')) break; if (nml_read > 1) { f__lquit = 2; return 0; } errfl (f__elist->cierr, 112, "invalid number"); } return 0; } static int rd_count (register int ch) { if (ch < '0' || ch > '9') return 1; f__lcount = ch - '0'; while (GETC (ch) >= '0' && ch <= '9') f__lcount = 10 * f__lcount + ch - '0'; Ungetc (ch, f__cf); return f__lcount <= 0; } static int l_C (void) { int ch, nml_save; double lz; if (f__lcount > 0) return (0); f__ltype = 0; GETC (ch); if (ch != '(') { if (nml_read > 1 && (ch < '0' || ch > '9')) { Ungetc (ch, f__cf); f__lquit = 2; return 0; } if (rd_count (ch)) { if (!f__cf || !feof (f__cf)) errfl (f__elist->cierr, 112, "complex format"); else err (f__elist->cierr, (EOF), "lread"); } if (GETC (ch) != '*') { if (!f__cf || !feof (f__cf)) errfl (f__elist->cierr, 112, "no star"); else err (f__elist->cierr, (EOF), "lread"); } if (GETC (ch) != '(') { Ungetc (ch, f__cf); return (0); } } else f__lcount = 1; while (iswhit (GETC (ch))); Ungetc (ch, f__cf); nml_save = nml_read; nml_read = 0; if ((ch = l_R (1, 0))) return ch; if (!f__ltype) errfl (f__elist->cierr, 112, "no real part"); lz = f__lx; while (iswhit (GETC (ch))); if (ch != ',') { (void) Ungetc (ch, f__cf); errfl (f__elist->cierr, 112, "no comma"); } while (iswhit (GETC (ch))); (void) Ungetc (ch, f__cf); if ((ch = l_R (1, 0))) return ch; if (!f__ltype) errfl (f__elist->cierr, 112, "no imaginary part"); while (iswhit (GETC (ch))); if (ch != ')') errfl (f__elist->cierr, 112, "no )"); f__ly = f__lx; f__lx = lz; #ifdef Allow_TYQUAD f__llx = 0; #endif nml_read = nml_save; return (0); } static char nmLbuf[256], *nmL_next; static int (*nmL_getc_save) (void); static int (*nmL_ungetc_save) (int, FILE *); static int nmL_getc (void) { int rv; if ((rv = *nmL_next++)) return rv; l_getc = nmL_getc_save; l_ungetc = nmL_ungetc_save; return (*l_getc) (); } static int nmL_ungetc (int x, FILE * f) { f = f; /* banish non-use warning */ return *--nmL_next = x; } static int Lfinish (int ch, int dot, int *rvp) { char *s, *se; static char what[] = "namelist input"; s = nmLbuf + 2; se = nmLbuf + sizeof (nmLbuf) - 1; *s++ = ch; while (!issep (GETC (ch)) && ch != EOF) { if (s >= se) { nmLbuf_ovfl: return *rvp = err__fl (f__elist->cierr, 131, what); } *s++ = ch; if (ch != '=') continue; if (dot) return *rvp = err__fl (f__elist->cierr, 112, what); got_eq: *s = 0; nmL_getc_save = l_getc; l_getc = nmL_getc; nmL_ungetc_save = l_ungetc; l_ungetc = nmL_ungetc; nmLbuf[1] = *(nmL_next = nmLbuf) = ','; *rvp = f__lcount = 0; return 1; } if (dot) goto done; for (;;) { if (s >= se) goto nmLbuf_ovfl; *s++ = ch; if (!isblnk (ch)) break; if (GETC (ch) == EOF) goto done; } if (ch == '=') goto got_eq; done: Ungetc (ch, f__cf); return 0; } static int l_L (void) { int ch, rv, sawdot; if (f__lcount > 0) return (0); f__lcount = 1; f__ltype = 0; GETC (ch); if (isdigit (ch)) { rd_count (ch); if (GETC (ch) != '*') { if (!f__cf || !feof (f__cf)) errfl (f__elist->cierr, 112, "no star"); else err (f__elist->cierr, (EOF), "lread"); } GETC (ch); } sawdot = 0; if (ch == '.') { sawdot = 1; GETC (ch); } switch (ch) { case 't': case 'T': if (nml_read && Lfinish (ch, sawdot, &rv)) return rv; f__lx = 1; break; case 'f': case 'F': if (nml_read && Lfinish (ch, sawdot, &rv)) return rv; f__lx = 0; break; default: if (isblnk (ch) || issep (ch) || ch == EOF) { (void) Ungetc (ch, f__cf); return (0); } if (nml_read > 1) { Ungetc (ch, f__cf); f__lquit = 2; return 0; } errfl (f__elist->cierr, 112, "logical"); } f__ltype = TYLONG; while (!issep (GETC (ch)) && ch != EOF); (void) Ungetc (ch, f__cf); return (0); } #define BUFSIZE 128 static int l_CHAR (void) { int ch, size, i; static char rafail[] = "realloc failure"; char quote, *p; if (f__lcount > 0) return (0); f__ltype = 0; if (f__lchar != NULL) free (f__lchar); size = BUFSIZE; p = f__lchar = (char *) malloc ((unsigned int) size); if (f__lchar == NULL) errfl (f__elist->cierr, 113, "no space"); GETC (ch); if (isdigit (ch)) { /* allow Fortran 8x-style unquoted string... */ /* either find a repetition count or the string */ f__lcount = ch - '0'; *p++ = ch; for (i = 1;;) { switch (GETC (ch)) { case '*': if (f__lcount == 0) { f__lcount = 1; #ifndef F8X_NML_ELIDE_QUOTES if (nml_read) goto no_quote; #endif goto noquote; } p = f__lchar; goto have_lcount; case ',': case ' ': case '\t': case '\n': case '/': Ungetc (ch, f__cf); /* no break */ case EOF: f__lcount = 1; f__ltype = TYCHAR; return *p = 0; } if (!isdigit (ch)) { f__lcount = 1; #ifndef F8X_NML_ELIDE_QUOTES if (nml_read) { no_quote: errfl (f__elist->cierr, 112, "undelimited character string"); } #endif goto noquote; } *p++ = ch; f__lcount = 10 * f__lcount + ch - '0'; if (++i == size) { f__lchar = (char *) realloc (f__lchar, (unsigned int) (size += BUFSIZE)); if (f__lchar == NULL) errfl (f__elist->cierr, 113, rafail); p = f__lchar + i; } } } else (void) Ungetc (ch, f__cf); have_lcount: if (GETC (ch) == '\'' || ch == '"') quote = ch; else if (isblnk (ch) || (issep (ch) && ch != '\n') || ch == EOF) { Ungetc (ch, f__cf); return 0; } #ifndef F8X_NML_ELIDE_QUOTES else if (nml_read > 1) { Ungetc (ch, f__cf); f__lquit = 2; return 0; } #endif else { /* Fortran 8x-style unquoted string */ *p++ = ch; for (i = 1;;) { switch (GETC (ch)) { case ',': case ' ': case '\t': case '\n': case '/': Ungetc (ch, f__cf); /* no break */ case EOF: f__ltype = TYCHAR; return *p = 0; } noquote: *p++ = ch; if (++i == size) { f__lchar = (char *) realloc (f__lchar, (unsigned int) (size += BUFSIZE)); if (f__lchar == NULL) errfl (f__elist->cierr, 113, rafail); p = f__lchar + i; } } } f__ltype = TYCHAR; for (i = 0;;) { while (GETC (ch) != quote && ch != '\n' && ch != EOF && ++i < size) *p++ = ch; if (i == size) { newone: f__lchar = (char *) realloc (f__lchar, (unsigned int) (size += BUFSIZE)); if (f__lchar == NULL) errfl (f__elist->cierr, 113, rafail); p = f__lchar + i - 1; *p++ = ch; } else if (ch == EOF) return (EOF); else if (ch == '\n') { if (*(p - 1) != '\\') continue; i--; p--; if (++i < size) *p++ = ch; else goto newone; } else if (GETC (ch) == quote) { if (++i < size) *p++ = ch; else goto newone; } else { (void) Ungetc (ch, f__cf); *p = 0; return (0); } } } int c_le (cilist * a) { if (f__init != 1) f_init (); f__init = 3; f__fmtbuf = "list io"; f__curunit = &f__units[a->ciunit]; f__fmtlen = 7; if (a->ciunit >= MXUNIT || a->ciunit < 0) err (a->cierr, 101, "stler"); f__scale = f__recpos = 0; f__elist = a; if (f__curunit->ufd == NULL && fk_open (SEQ, FMT, a->ciunit)) err (a->cierr, 102, "lio"); f__cf = f__curunit->ufd; if (!f__curunit->ufmt) err (a->cierr, 103, "lio"); return (0); } int l_read (ftnint * number, char *ptr, ftnlen len, ftnint type) { #define Ptr ((flex *)ptr) int i, n, ch; doublereal *yy; real *xx; for (i = 0; i < *number; i++) { if (f__lquit) return (0); if (l_eof) err (f__elist->ciend, EOF, "list in"); if (f__lcount == 0) { f__ltype = 0; for (;;) { GETC (ch); switch (ch) { case EOF: err (f__elist->ciend, (EOF), "list in"); case ' ': case '\t': case '\n': continue; case '/': f__lquit = 1; goto loopend; case ',': f__lcount = 1; goto loopend; default: (void) Ungetc (ch, f__cf); goto rddata; } } } rddata: switch ((int) type) { case TYINT1: case TYSHORT: case TYLONG: #ifndef ALLOW_FLOAT_IN_INTEGER_LIST_INPUT ERR (l_R (0, 1)); break; #endif case TYREAL: case TYDREAL: ERR (l_R (0, 0)); break; #ifdef TYQUAD case TYQUAD: n = l_R (0, 2); if (n) return n; break; #endif case TYCOMPLEX: case TYDCOMPLEX: ERR (l_C ()); break; case TYLOGICAL1: case TYLOGICAL2: case TYLOGICAL: ERR (l_L ()); break; case TYCHAR: ERR (l_CHAR ()); break; } while (GETC (ch) == ' ' || ch == '\t'); if (ch != ',' || f__lcount > 1) Ungetc (ch, f__cf); loopend: if (f__lquit) return (0); if (f__cf && ferror (f__cf)) { clearerr (f__cf); errfl (f__elist->cierr, errno, "list in"); } if (f__ltype == 0) goto bump; switch ((int) type) { case TYINT1: case TYLOGICAL1: Ptr->flchar = (char) f__lx; break; case TYLOGICAL2: case TYSHORT: Ptr->flshort = (short) f__lx; break; case TYLOGICAL: case TYLONG: Ptr->flint = (ftnint) f__lx; break; #ifdef Allow_TYQUAD case TYQUAD: if (!(Ptr->fllongint = f__llx)) Ptr->fllongint = f__lx; break; #endif case TYREAL: Ptr->flreal = f__lx; break; case TYDREAL: Ptr->fldouble = f__lx; break; case TYCOMPLEX: xx = (real *) ptr; *xx++ = f__lx; *xx = f__ly; break; case TYDCOMPLEX: yy = (doublereal *) ptr; *yy++ = f__lx; *yy = f__ly; break; case TYCHAR: b_char (f__lchar, ptr, len); break; } bump: if (f__lcount > 0) f__lcount--; ptr += len; if (nml_read) nml_read++; } return (0); #undef Ptr } integer s_rsle (cilist * a) { int n; f__reading = 1; f__external = 1; f__formatted = 1; if ((n = c_le (a))) return (n); f__lioproc = l_read; f__lquit = 0; f__lcount = 0; l_eof = 0; if (f__curunit->uwrt && f__nowreading (f__curunit)) err (a->cierr, errno, "read start"); if (f__curunit->uend) err (f__elist->ciend, (EOF), "read start"); l_getc = t_getc; l_ungetc = un_getc; f__doend = xrd_SL; return (0); }