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