1: /* 2: char id_lread[] = "@(#)lread.c 1.7"; 3: * 4: * list directed read 5: */ 6: 7: #include "fio.h" 8: #include "lio.h" 9: 10: #define SP 1 11: #define B 2 12: #define AP 4 13: #define EX 8 14: #define D 16 15: #define EIN 32 16: #define isblnk(x) (ltab[x+1]&B) 17: #define issep(x) (ltab[x+1]&SP) 18: #define isapos(x) (ltab[x+1]&AP) 19: #define isexp(x) (ltab[x+1]&EX) 20: #define isdigit(x) (ltab[x+1]&D) 21: #define endlinp(x) (ltab[x+1]&EIN) 22: 23: #define GETC(x) (x=(*getn)()) 24: 25: char lrd[] = "list read"; 26: char *lchar; 27: double lx,ly; 28: int ltype; 29: int l_read(),t_getc(),ungetc(); 30: 31: char ltab[128+1] = 32: { EIN, /* offset one for EOF */ 33: /* 0- 15 */ 0,0,AP,0,0,0,0,0,0,B,SP|B|EIN,0,0,0,0,0, /* ^B,TAB,NEWLINE */ 34: /* 16- 31 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 35: /* 32- 47 */ SP|B,0,AP,0,0,0,0,AP,0,0,0,0,SP,0,0,EIN, /* space,",',comma,/ */ 36: /* 48- 63 */ D,D,D,D,D,D,D,D,D,D,0,0,0,0,0,0, /* digits 0-9 */ 37: /* 64- 79 */ 0,0,0,0,EX,EX,0,0,0,0,0,0,0,0,0,0, /* D,E */ 38: /* 80- 95 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 39: /* 96-111 */ 0,0,0,0,EX,EX,0,0,0,0,0,0,0,0,0,0, /* d,e */ 40: /* 112-127 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 41: }; 42: 43: s_rsle(a) cilist *a; /* start read sequential list external */ 44: { 45: int n; 46: reading = YES; 47: if(n=c_le(a,READ)) return(n); 48: l_first = YES; 49: lquit = NO; 50: lioproc = l_read; 51: getn = t_getc; 52: ungetn = ungetc; 53: leof = curunit->uend; 54: lcount = 0; 55: ltype = NULL; 56: if(curunit->uwrt && ! nowreading(curunit)) err(errflag, errno, lrd) 57: return(OK); 58: } 59: 60: t_getc() 61: { int ch; 62: if(curunit->uend) return(EOF); 63: if((ch=getc(cf))!=EOF) return(ch); 64: if(feof(cf)) 65: { curunit->uend = YES; 66: leof = EOF; 67: } 68: else clearerr(cf); 69: return(EOF); 70: } 71: 72: e_rsle() 73: { 74: int ch; 75: if(curunit->uend) return(OK); 76: while(GETC(ch) != '\n' && ch != EOF); 77: return(OK); 78: } 79: 80: l_read(number,ptr,len,type) ftnint *number,type; flex *ptr; ftnlen len; 81: { int i,n,ch; 82: double *yy; 83: float *xx; 84: for(i=0;i<*number;i++) 85: { 86: if(leof) err(endflag, EOF, lrd) 87: if(l_first) 88: { l_first = NO; 89: while(isblnk(GETC(ch))); /* skip blanks */ 90: (*ungetn)(ch,cf); 91: } 92: else if(lcount==0) /* repeat count == 0 ? */ 93: { ERR(t_sep()); /* look for non-blank, allow 1 comma */ 94: if(lquit) return(OK); /* slash found */ 95: } 96: switch((int)type) 97: { 98: case TYSHORT: 99: case TYLONG: 100: case TYREAL: 101: case TYDREAL: 102: ERR(l_R(1)); 103: break; 104: case TYCOMPLEX: 105: case TYDCOMPLEX: 106: ERR(l_C()); 107: break; 108: case TYLOGICAL: 109: ERR(l_L()); 110: break; 111: case TYCHAR: 112: ERR(l_CHAR()); 113: break; 114: } 115: if(lquit) return(OK); 116: if(leof) err(endflag,EOF,lrd) 117: else if(external && ferror(cf)) err(errflag,errno,lrd) 118: if(ltype) switch((int)type) 119: { 120: case TYSHORT: 121: ptr->flshort=lx; 122: break; 123: case TYLOGICAL: 124: case TYLONG: 125: ptr->flint=lx; 126: break; 127: case TYREAL: 128: ptr->flreal=lx; 129: break; 130: case TYDREAL: 131: ptr->fldouble=lx; 132: break; 133: case TYCOMPLEX: 134: xx=(float *)ptr; 135: *xx++ = ly; 136: *xx = lx; 137: break; 138: case TYDCOMPLEX: 139: yy=(double *)ptr; 140: *yy++ = ly; 141: *yy = lx; 142: break; 143: case TYCHAR: 144: b_char(lchar,(char *)ptr,len); 145: break; 146: } 147: if(lcount>0) lcount--; 148: ptr = (flex *)((char *)ptr + len); 149: } 150: return(OK); 151: } 152: 153: lr_comm() 154: { int ch; 155: if(lcount) return(lcount); 156: ltype=NULL; 157: while(isblnk(GETC(ch))); 158: (*ungetn)(ch,cf); 159: if(ch==',') 160: { lcount=1; 161: return(lcount); 162: } 163: if(ch=='/') 164: { lquit = YES; 165: return(lquit); 166: } 167: else 168: return(OK); 169: } 170: 171: get_repet() 172: { char ch; 173: double lc; 174: if(isdigit(GETC(ch))) 175: { (*ungetn)(ch,cf); 176: rd_int(&lc); 177: lcount = (int)lc; 178: if(GETC(ch)!='*') 179: if(leof) return(EOF); 180: else return(F_ERREPT); 181: } 182: else 183: { lcount = 1; 184: (*ungetn)(ch,cf); 185: } 186: return(OK); 187: } 188: 189: l_R(flg) int flg; 190: { double a,b,c,d; 191: int da,db,dc,dd; 192: int i,ch,sign=0; 193: a=b=c=d=0; 194: da=db=dc=dd=0; 195: if(flg && lr_comm()) return(OK); 196: da=rd_int(&a); /* repeat count ? */ 197: if(GETC(ch)=='*') 198: { 199: if (a <= 0.) return(F_ERNREP); 200: lcount=(int)a; 201: if (nullfld()) return(OK); /* could be R* */ 202: db=rd_int(&b); /* whole part of number */ 203: } 204: else 205: { (*ungetn)(ch,cf); 206: db=da; 207: b=a; 208: lcount=1; 209: } 210: if(GETC(ch)=='.' && isdigit(GETC(ch))) 211: { (*ungetn)(ch,cf); 212: dc=rd_int(&c); /* fractional part of number */ 213: } 214: else 215: { (*ungetn)(ch,cf); 216: dc=0; 217: c=0.; 218: } 219: if(isexp(GETC(ch))) 220: dd=rd_int(&d); /* exponent */ 221: else if (ch == '+' || ch == '-') 222: { (*ungetn)(ch,cf); 223: dd=rd_int(&d); 224: } 225: else 226: { (*ungetn)(ch,cf); 227: dd=0; 228: } 229: if(db<0 || b<0) 230: { sign=1; 231: b = -b; 232: } 233: for(i=0;i<dc;i++) c/=10.; 234: b=b+c; 235: if (dd > 0) 236: { for(i=0;i<d;i++) b *= 10.; 237: for(i=0;i< -d;i++) b /= 10.; 238: } 239: lx=sign?-b:b; 240: ltype=TYLONG; 241: return(OK); 242: } 243: 244: rd_int(x) double *x; 245: { int ch,sign=0,i=0; 246: double y=0.0; 247: if(GETC(ch)=='-') sign = -1; 248: else if(ch=='+') sign=0; 249: else (*ungetn)(ch,cf); 250: while(isdigit(GETC(ch))) 251: { i++; 252: y=10*y + ch-'0'; 253: } 254: (*ungetn)(ch,cf); 255: if(sign) y = -y; 256: *x = y; 257: return(y==0.0?sign:i); /* 0:[+]&&y==0, -1:-&&y==0, >0:#digits&&y!=0 */ 258: } 259: 260: l_C() 261: { int ch,n; 262: if(lr_comm()) return(OK); 263: if(n=get_repet()) return(n); /* get repeat count */ 264: if (nullfld()) return(OK); /* could be R* */ 265: if(GETC(ch)!='(') err(errflag,F_ERLIO,"no (") 266: while(isblnk(GETC(ch))); 267: (*ungetn)(ch,cf); 268: l_R(0); /* get real part */ 269: ly = lx; 270: if(t_sep()) return(EOF); 271: l_R(0); /* get imag part */ 272: while(isblnk(GETC(ch))); 273: if(ch!=')') err(errflag,F_ERLIO,"no )") 274: ltype = TYCOMPLEX; 275: return(OK); 276: } 277: 278: l_L() 279: { 280: int ch,n; 281: if(lr_comm()) return(OK); 282: if(n=get_repet()) return(n); /* get repeat count */ 283: if (nullfld()) return(OK); /* could be R* */ 284: if(GETC(ch)=='.') GETC(ch); 285: switch(ch) 286: { 287: case 't': 288: case 'T': 289: lx=1; 290: break; 291: case 'f': 292: case 'F': 293: lx=0; 294: break; 295: default: 296: if(isblnk(ch) || issep(ch)) 297: { (*ungetn)(ch,cf); 298: lx=0; 299: return(OK); 300: } 301: else if(ch==EOF) return(EOF); 302: else err(errflag,F_ERLIO,"logical not T or F"); 303: } 304: ltype=TYLOGICAL; 305: while(!issep(GETC(ch)) && !isblnk(ch) && !endlinp(ch)); 306: (*ungetn)(ch,cf); 307: return(OK); 308: } 309: 310: #define BUFSIZE 128 311: l_CHAR() 312: { int ch,size,i,n; 313: char quote,*p; 314: if(lr_comm()) return(OK); 315: if(n=get_repet()) return(n); /* get repeat count */ 316: if (nullfld()) return(OK); /* could be R* */ 317: if(isapos(GETC(ch))) quote=ch; 318: else if(isblnk(ch) || issep(ch) || ch==EOF || ch=='\n') 319: { if(ch==EOF) return(EOF); 320: (*ungetn)(ch,cf); 321: return(OK); 322: } 323: else 324: { quote = '\0'; /* to allow single word non-quoted */ 325: (*ungetn)(ch,cf); 326: } 327: ltype=TYCHAR; 328: if(lchar!=NULL) free(lchar); 329: size=BUFSIZE-1; 330: p=lchar=(char *)malloc(BUFSIZE); 331: if(lchar==NULL) err(errflag,F_ERSPACE,lrd) 332: for(i=0;;) 333: { while( ( (quote && GETC(ch)!=quote) || 334: (!quote && !issep(GETC(ch)) && !isblnk(ch) && !endlinp(ch)) ) 335: && ch!='\n' && ch!=EOF && ++i<size ) 336: *p++ = ch; 337: if(i==size) 338: { 339: newone: 340: size += BUFSIZE; 341: lchar=(char *)realloc(lchar, size+1); 342: if(lchar==NULL) err(errflag,F_ERSPACE,lrd) 343: p=lchar+i-1; 344: *p++ = ch; 345: } 346: else if(ch==EOF) return(EOF); 347: else if(ch=='\n') 348: { if(*(p-1) == '\\') *(p-1) = ch; 349: else if(!quote) 350: { *p = '\0'; 351: (*ungetn)(ch,cf); 352: return(OK); 353: } 354: } 355: else if(quote && GETC(ch)==quote) 356: { if(++i<size) *p++ = ch; 357: else goto newone; 358: } 359: else 360: { (*ungetn)(ch,cf); 361: *p = '\0'; 362: return(OK); 363: } 364: } 365: } 366: 367: t_sep() 368: { 369: int ch; 370: while(isblnk(GETC(ch))); 371: if(leof) return(EOF); 372: if(ch=='/') 373: { lquit = YES; 374: (*ungetn)(ch,cf); 375: return(OK); 376: } 377: if(issep(ch)) while(isblnk(GETC(ch))); 378: if(leof) return(EOF); 379: (*ungetn)(ch,cf); 380: return(OK); 381: } 382: 383: nullfld() /* look for null field following a repeat count */ 384: { 385: int ch; 386: 387: while(isblnk(GETC(ch))); 388: (*ungetn)(ch,cf); 389: if (issep(ch) || endlinp(ch)) 390: return(YES); 391: return(NO); 392: }