526 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			526 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "f2c.h"
 | |
| #include "fio.h"
 | |
| #include "fmt.h"
 | |
| #include "lio.h"
 | |
| #include "ctype.h"
 | |
| #include "fp.h"
 | |
| 
 | |
| extern char *fmtbuf;
 | |
| extern char *malloc(), *realloc();
 | |
| int (*lioproc)(), (*l_getc)(), (*l_ungetc)();
 | |
| int l_eof;
 | |
| 
 | |
| #define isblnk(x) (ltab[x+1]&B)
 | |
| #define issep(x) (ltab[x+1]&SX)
 | |
| #define isapos(x) (ltab[x+1]&AX)
 | |
| #define isexp(x) (ltab[x+1]&EX)
 | |
| #define issign(x) (ltab[x+1]&SG)
 | |
| #define iswhit(x) (ltab[x+1]&WH)
 | |
| #define SX 1
 | |
| #define B 2
 | |
| #define AX 4
 | |
| #define EX 8
 | |
| #define SG 16
 | |
| #define WH 32
 | |
| char 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
 | |
| };
 | |
| 
 | |
| t_getc()
 | |
| {	int ch;
 | |
| 	if(curunit->uend) return(EOF);
 | |
| 	if((ch=getc(cf))!=EOF) return(ch);
 | |
| 	if(feof(cf))
 | |
| 		l_eof = curunit->uend = 1;
 | |
| 	return(EOF);
 | |
| }
 | |
| integer e_rsle()
 | |
| {
 | |
| 	int ch;
 | |
| 	if(curunit->uend) return(0);
 | |
| 	while((ch=t_getc())!='\n' && ch!=EOF);
 | |
| 	return(0);
 | |
| }
 | |
| 
 | |
| flag lquit;
 | |
| int lcount,ltype;
 | |
| char *lchar;
 | |
| double lx,ly;
 | |
| #define ERR(x) if(n=(x)) return(n)
 | |
| #define GETC(x) (x=(*l_getc)())
 | |
| #define Ungetc(x,y) (*l_ungetc)(x,y)
 | |
| 
 | |
| l_read(number,ptr,len,type) ftnint *number,type; char *ptr; ftnlen len;
 | |
| {
 | |
| #define Ptr ((flex *)ptr)
 | |
| 	int i,n,ch;
 | |
| 	doublereal *yy;
 | |
| 	real *xx;
 | |
| 	for(i=0;i<*number;i++)
 | |
| 	{
 | |
| 		if(lquit) return(0);
 | |
| 		if(l_eof)
 | |
| 			err(elist->ciend, EOF, "list in")
 | |
| 		if(lcount == 0) {
 | |
| 			ltype = 0;
 | |
| 			for(;;)  {
 | |
| 				GETC(ch);
 | |
| 				switch(ch) {
 | |
| 				case EOF:
 | |
| 					goto loopend;
 | |
| 				case ' ':
 | |
| 				case '\t':
 | |
| 				case '\n':
 | |
| 					continue;
 | |
| 				case '/':
 | |
| 					lquit = 1;
 | |
| 					goto loopend;
 | |
| 				case ',':
 | |
| 					lcount = 1;
 | |
| 					goto loopend;
 | |
| 				default:
 | |
| 					(void) Ungetc(ch, cf);
 | |
| 					goto rddata;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	rddata:
 | |
| 		switch((int)type)
 | |
| 		{
 | |
| 		case TYSHORT:
 | |
| 		case TYLONG:
 | |
| 		case TYREAL:
 | |
| 		case TYDREAL:
 | |
| 			ERR(l_R(0));
 | |
| 			break;
 | |
| 		case TYCOMPLEX:
 | |
| 		case TYDCOMPLEX:
 | |
| 			ERR(l_C());
 | |
| 			break;
 | |
| 		case TYLOGICAL:
 | |
| 			ERR(l_L());
 | |
| 			break;
 | |
| 		case TYCHAR:
 | |
| 			ERR(l_CHAR());
 | |
| 			break;
 | |
| 		}
 | |
| 	while (GETC(ch) == ' ' || ch == '\t');
 | |
| 	if (ch != ',')
 | |
| 		Ungetc(ch,cf);
 | |
| 	loopend:
 | |
| 		if(lquit) return(0);
 | |
| 		if(cf) {
 | |
| 			if (feof(cf))
 | |
| 				err(elist->ciend,(EOF),"list in")
 | |
| 			else if(ferror(cf)) {
 | |
| 				clearerr(cf);
 | |
| 				err(elist->cierr,errno,"list in")
 | |
| 				}
 | |
| 			}
 | |
| 		if(ltype==0) goto bump;
 | |
| 		switch((int)type)
 | |
| 		{
 | |
| 		case TYSHORT:
 | |
| 			Ptr->flshort=lx;
 | |
| 			break;
 | |
| 		case TYLOGICAL:
 | |
| 		case TYLONG:
 | |
| 			Ptr->flint=lx;
 | |
| 			break;
 | |
| 		case TYREAL:
 | |
| 			Ptr->flreal=lx;
 | |
| 			break;
 | |
| 		case TYDREAL:
 | |
| 			Ptr->fldouble=lx;
 | |
| 			break;
 | |
| 		case TYCOMPLEX:
 | |
| 			xx=(real *)ptr;
 | |
| 			*xx++ = lx;
 | |
| 			*xx = ly;
 | |
| 			break;
 | |
| 		case TYDCOMPLEX:
 | |
| 			yy=(doublereal *)ptr;
 | |
| 			*yy++ = lx;
 | |
| 			*yy = ly;
 | |
| 			break;
 | |
| 		case TYCHAR:
 | |
| 			b_char(lchar,ptr,len);
 | |
| 			break;
 | |
| 		}
 | |
| 	bump:
 | |
| 		if(lcount>0) lcount--;
 | |
| 		ptr += len;
 | |
| 	}
 | |
| 	return(0);
 | |
| #undef Ptr
 | |
| }
 | |
| l_R(poststar)
 | |
|  int poststar;
 | |
| {
 | |
| 	char s[FMAX+EXPMAXDIGS+4];
 | |
| 	register int ch;
 | |
| 	register char *sp, *spe, *sp1;
 | |
| 	long e, exp;
 | |
| 	double atof();
 | |
| 	int havenum, se;
 | |
| 
 | |
| 	if (!poststar) {
 | |
| 		if (lcount > 0)
 | |
| 			return(0);
 | |
| 		lcount = 1;
 | |
| 		}
 | |
| 	ltype = 0;
 | |
| 	exp = 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 == '-') {
 | |
| 			err(elist->cierr,112,"bad repetition count")
 | |
| 			}
 | |
| 		poststar = 1;
 | |
| 		*sp = 0;
 | |
| 		lcount = atoi(s);
 | |
| 		goto retry;
 | |
| 		}
 | |
| 	if (ch == '.') {
 | |
| 		GETC(ch);
 | |
| 		if (sp == sp1)
 | |
| 			while(ch == '0') {
 | |
| 				++havenum;
 | |
| 				--exp;
 | |
| 				GETC(ch);
 | |
| 				}
 | |
| 		while(isdigit(ch)) {
 | |
| 			if (sp < spe)
 | |
| 				{ *sp++ = ch; --exp; }
 | |
| 			GETC(ch);
 | |
| 			}
 | |
| 		}
 | |
| 	se = 0;
 | |
| 	if (issign(ch))
 | |
| 		goto signonly;
 | |
| 	if (isexp(ch)) {
 | |
| 		GETC(ch);
 | |
| 		if (issign(ch)) {
 | |
| signonly:
 | |
| 			if (ch == '-') se = 1;
 | |
| 			GETC(ch);
 | |
| 			}
 | |
| 		if (!isdigit(ch)) {
 | |
| bad:
 | |
| 			err(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, cf);
 | |
| 	if (sp > sp1) {
 | |
| 		++havenum;
 | |
| 		while(*--sp == '0')
 | |
| 			++exp;
 | |
| 		if (exp)
 | |
| 			sprintf(sp+1, "e%ld", exp);
 | |
| 		else
 | |
| 			sp[1] = 0;
 | |
| 		lx = atof(s);
 | |
| 		}
 | |
| 	else
 | |
| 		lx = 0.;
 | |
| 	if (havenum)
 | |
| 		ltype = TYLONG;
 | |
| 	else
 | |
| 		switch(ch) {
 | |
| 			case ',':
 | |
| 			case '/':
 | |
| 				break;
 | |
| 			default:
 | |
| 				err(elist->cierr,112,"invalid number")
 | |
| 			}
 | |
| 	return 0;
 | |
| 	}
 | |
| 
 | |
|  static int
 | |
| rd_count(ch)
 | |
|  register int ch;
 | |
| {
 | |
| 	if (ch < '0' || ch > '9')
 | |
| 		return 1;
 | |
| 	lcount = ch - '0';
 | |
| 	while(GETC(ch) >= '0' && ch <= '9')
 | |
| 		lcount = 10*lcount + ch - '0';
 | |
| 	Ungetc(ch,cf);
 | |
| 	return 0;
 | |
| 	}
 | |
| 
 | |
| l_C()
 | |
| {	int ch;
 | |
| 	double lz;
 | |
| 	if(lcount>0) return(0);
 | |
| 	ltype=0;
 | |
| 	GETC(ch);
 | |
| 	if(ch!='(')
 | |
| 	{
 | |
| 		if (rd_count(ch))
 | |
| 			if(!cf || !feof(cf))
 | |
| 				err(elist->cierr,112,"complex format")
 | |
| 			else
 | |
| 				err(elist->cierr,(EOF),"lread");
 | |
| 		if(GETC(ch)!='*')
 | |
| 		{
 | |
| 			if(!cf || !feof(cf))
 | |
| 				err(elist->cierr,112,"no star")
 | |
| 			else
 | |
| 				err(elist->cierr,(EOF),"lread");
 | |
| 		}
 | |
| 		if(GETC(ch)!='(')
 | |
| 		{	(void) Ungetc(ch,cf);
 | |
| 			return(0);
 | |
| 		}
 | |
| 	}
 | |
| 	else
 | |
| 		lcount = 1;
 | |
| 	while(iswhit(GETC(ch)));
 | |
| 	(void) Ungetc(ch,cf);
 | |
| 	if (ch = l_R(1))
 | |
| 		return ch;
 | |
| 	if (!ltype)
 | |
| 		err(elist->cierr,112,"no real part");
 | |
| 	lz = lx;
 | |
| 	while(iswhit(GETC(ch)));
 | |
| 	if(ch!=',')
 | |
| 	{	(void) Ungetc(ch,cf);
 | |
| 		err(elist->cierr,112,"no comma");
 | |
| 	}
 | |
| 	while(iswhit(GETC(ch)));
 | |
| 	(void) Ungetc(ch,cf);
 | |
| 	if (ch = l_R(1))
 | |
| 		return ch;
 | |
| 	if (!ltype)
 | |
| 		err(elist->cierr,112,"no imaginary part");
 | |
| 	while(iswhit(GETC(ch)));
 | |
| 	if(ch!=')') err(elist->cierr,112,"no )");
 | |
| 	ly = lx;
 | |
| 	lx = lz;
 | |
| 	return(0);
 | |
| }
 | |
| l_L()
 | |
| {
 | |
| 	int ch;
 | |
| 	if(lcount>0) return(0);
 | |
| 	ltype=0;
 | |
| 	GETC(ch);
 | |
| 	if(isdigit(ch))
 | |
| 	{
 | |
| 		rd_count(ch);
 | |
| 		if(GETC(ch)!='*')
 | |
| 			if(!cf || !feof(cf))
 | |
| 				err(elist->cierr,112,"no star")
 | |
| 			else
 | |
| 				err(elist->cierr,(EOF),"lread");
 | |
| 		GETC(ch);
 | |
| 	}
 | |
| 	if(ch == '.') GETC(ch);
 | |
| 	switch(ch)
 | |
| 	{
 | |
| 	case 't':
 | |
| 	case 'T':
 | |
| 		lx=1;
 | |
| 		break;
 | |
| 	case 'f':
 | |
| 	case 'F':
 | |
| 		lx=0;
 | |
| 		break;
 | |
| 	default:
 | |
| 		if(isblnk(ch) || issep(ch) || ch==EOF)
 | |
| 		{	(void) Ungetc(ch,cf);
 | |
| 			return(0);
 | |
| 		}
 | |
| 		else	err(elist->cierr,112,"logical");
 | |
| 	}
 | |
| 	ltype=TYLONG;
 | |
| 	lcount = 1;
 | |
| 	while(!issep(GETC(ch)) && ch!=EOF);
 | |
| 	(void) Ungetc(ch, cf);
 | |
| 	return(0);
 | |
| }
 | |
| #define BUFSIZE	128
 | |
| l_CHAR()
 | |
| {	int ch,size,i;
 | |
| 	char quote,*p;
 | |
| 	if(lcount>0) return(0);
 | |
| 	ltype=0;
 | |
| 	if(lchar!=NULL) free(lchar);
 | |
| 	size=BUFSIZE;
 | |
| 	p=lchar=malloc((unsigned int)size);
 | |
| 	if(lchar==NULL) err(elist->cierr,113,"no space");
 | |
| 
 | |
| 	GETC(ch);
 | |
| 	if(isdigit(ch)) {
 | |
| 		/* allow Fortran 8x-style unquoted string...	*/
 | |
| 		/* either find a repetition count or the string	*/
 | |
| 		lcount = ch - '0';
 | |
| 		*p++ = ch;
 | |
| 		for(i = 1;;) {
 | |
| 			switch(GETC(ch)) {
 | |
| 				case '*':
 | |
| 					if (lcount == 0) {
 | |
| 						lcount = 1;
 | |
| 						goto noquote;
 | |
| 						}
 | |
| 					p = lchar;
 | |
| 					goto have_lcount;
 | |
| 				case ',':
 | |
| 				case ' ':
 | |
| 				case '\t':
 | |
| 				case '\n':
 | |
| 				case '/':
 | |
| 					Ungetc(ch,cf);
 | |
| 					/* no break */
 | |
| 				case EOF:
 | |
| 					lcount = 1;
 | |
| 					ltype = TYCHAR;
 | |
| 					return *p = 0;
 | |
| 				}
 | |
| 			if (!isdigit(ch)) {
 | |
| 				lcount = 1;
 | |
| 				goto noquote;
 | |
| 				}
 | |
| 			*p++ = ch;
 | |
| 			lcount = 10*lcount + ch - '0';
 | |
| 			if (++i == size) {
 | |
| 				lchar = realloc(lchar,
 | |
| 					(unsigned int)(size += BUFSIZE));
 | |
| 				p = lchar + i;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	else	(void) Ungetc(ch,cf);
 | |
|  have_lcount:
 | |
| 	if(GETC(ch)=='\'' || ch=='"') quote=ch;
 | |
| 	else if(isblnk(ch) || (issep(ch) && ch != '\n') || ch==EOF)
 | |
| 	{	(void) Ungetc(ch,cf);
 | |
| 		return(0);
 | |
| 	}
 | |
| 	else {
 | |
| 		/* Fortran 8x-style unquoted string */
 | |
| 		*p++ = ch;
 | |
| 		for(i = 1;;) {
 | |
| 			switch(GETC(ch)) {
 | |
| 				case ',':
 | |
| 				case ' ':
 | |
| 				case '\t':
 | |
| 				case '\n':
 | |
| 				case '/':
 | |
| 					Ungetc(ch,cf);
 | |
| 					/* no break */
 | |
| 				case EOF:
 | |
| 					ltype = TYCHAR;
 | |
| 					return *p = 0;
 | |
| 				}
 | |
|  noquote:
 | |
| 			*p++ = ch;
 | |
| 			if (++i == size) {
 | |
| 				lchar = realloc(lchar,
 | |
| 					(unsigned int)(size += BUFSIZE));
 | |
| 				p = lchar + i;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	ltype=TYCHAR;
 | |
| 	for(i=0;;)
 | |
| 	{	while(GETC(ch)!=quote && ch!='\n'
 | |
| 			&& ch!=EOF && ++i<size) *p++ = ch;
 | |
| 		if(i==size)
 | |
| 		{
 | |
| 		newone:
 | |
| 			lchar= realloc(lchar, (unsigned int)(size += BUFSIZE));
 | |
| 			p=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,cf);
 | |
| 			*p = 0;
 | |
| 			return(0);
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| integer s_rsle(a) cilist *a;
 | |
| {
 | |
| 	int n;
 | |
| 	extern int ungetc();
 | |
| 
 | |
| 	if(!init) f_init();
 | |
| 	if(n=c_le(a)) return(n);
 | |
| 	reading=1;
 | |
| 	external=1;
 | |
| 	formatted=1;
 | |
| 	lioproc = l_read;
 | |
| 	lquit = 0;
 | |
| 	lcount = 0;
 | |
| 	l_eof = 0;
 | |
| 	if(curunit->uwrt && nowreading(curunit))
 | |
| 		err(a->cierr,errno,"read start");
 | |
| 	l_getc = t_getc;
 | |
| 	l_ungetc = ungetc;
 | |
| 	return(0);
 | |
| }
 | |
| c_le(a) cilist *a;
 | |
| {
 | |
| 	fmtbuf="list io";
 | |
| 	if(a->ciunit>=MXUNIT || a->ciunit<0)
 | |
| 		err(a->cierr,101,"stler");
 | |
| 	scale=recpos=0;
 | |
| 	elist=a;
 | |
| 	curunit = &units[a->ciunit];
 | |
| 	if(curunit->ufd==NULL && fk_open(SEQ,FMT,a->ciunit))
 | |
| 		err(a->cierr,102,"lio");
 | |
| 	cf=curunit->ufd;
 | |
| 	if(!curunit->ufmt) err(a->cierr,103,"lio")
 | |
| 	return(0);
 | |
| }
 |