plt - Software for 2D Plots 2.5

File: <base>/plt-2.5a/classic/libc/data.c (8,709 bytes)
/*	data.c			Paul Albrecht			Mar 1983

	Subroutines to handle and return data which is in a
	file in column form.  Archaic code.

	Last Edit	11/11/88
*/


#include	"opts.h"


#define		ALL		(-1)

#ifndef		MAXFIL
#define		MAXFIL		5
#endif

#ifndef		MAXCOL
#define		MAXCOL		16
#endif

#ifndef		MAXLEN
#define		MAXLEN		512
#endif

#define		DIGIT(CHR)		 (((CHR) >= '0' && (CHR) <= '9') \
							|| (CHR) == '#' || (CHR) == '%')
#define		WHITE(CHR)		 ((CHR) == ' '  || (CHR) == '\t')
#define		END(CHR)		 ((CHR) == '\n' || (CHR) == EOF)


static	FILE	*outStream = stdout;

typedef	enum	{
		typeASCII, typeShort, typeFloat, typeDouble
		} DataType;

typedef	union	{
		double	*d;
		float	*f;
		short	*s;
		char	*c;
		}	Pointer;

typedef	struct	 {
	FILE		*fp;	/* file pointer */
	char		*name;	/* name of the file */
	char		eof;	/* YES if eof reached, NO otherwise */
	char		raw;	/* 0 = ascii data, otherwize size of binary num */
	DataType	type;	/* type of data we are reading */
	short		ac;		/* ALL if all columns needed, NO otherwise */
	long		tc;		/* columns in first row of file */
	short		lc;		/* 1 + largest column number required from file */
	short		nc;		/* number of columns to take from the file */
	short		nb;		/* number of bytes per row for raw data file */
	short	col[MAXCOL];/* columns requested from specified file */
	long		rf;		/* first row wanted from the file */
	long		rt;		/* last row */
	long		rs;		/* row step, take every nth row */
	long	row;		/* current row */
	long	beginData;	/* byte at which data begins */
	}	DFILE;

static	DFILE	df[MAXFIL];

static	DataType	outDataType = typeFloat;

static short
	forceASCII = NO,		/* Output is ascii regardless of destination? */
	nf = 0,					/* number of files being read */
	tty, initialized = NO;	/* used by data_aput() below */


static	char	*sfield  = " ",
		*sformat = "%g%s",
		*str[MAXLEN/sizeof(float)],
		line[MAXLEN];
static int data_row(), get_strings();

data_close()
{
	while (nf > 0)
		fclose(df[nf--].fp);
	initialized = NO;
}



data_files(list)
char *list[];
{
    static char *allist[] = { "%", 0 };
    register DFILE *f;
    register n, grand_tot = 0;
    char c, *args;

    if (*(++list) == 0)
	list = allist;

    for (nf = n = 0; n < MAXFIL; n++) {
	f = &df[n];
	f->fp = stdin;
	f->name = "standard-input";
	f->eof = f->raw = f->ac = f->nc = f->lc = 0;
	f->beginData = f->row = 0;
	f->rf = f->rt = f->rs = -1;
    }

    while (*list) {
	if (nf == MAXFIL)
	    estop("Can't have more than %d files", MAXFIL);
	f = &df[nf];

	if (**list == ':') {
	    args = *(list++) + 1;
	    switch (*args) {
	      case 's': f->raw = sizeof(short); break;
	      case 'f': f->raw = sizeof(float); break;
	      case 'd':	f->raw = sizeof(double); break;
	    }
	    if (f->raw != 0) {
		args++;
		GetNum(&args, &f->tc);
	    }
	    GetNum(&args,&f->rf);
	    GetNum(&args,&f->rt);
	    GetNum(&args,&f->rs);
	}
	else {
	    if (!DIGIT(**list)) {
		f->fp = fofile(*list, "r");
		f->name = *list++;
	    }
	    while (*list && DIGIT(**list)) {
		c = **list++;
		if (c != '#' && c !=  '%') {
		    n = 1 + (f->col[f->nc] = atoi(list[-1]));
		    if (f->lc < n)
			f->lc = n;
		}
		else	f->col[f->nc] = f->ac = ALL;
		
		if (++f->nc > MAXCOL)
		    estop("Can't take more than %d columns from one file", MAXCOL);
	    }
	    nf++;
	    
	    if (f->nc == 0)
		f->col[f->nc++] = f->ac = ALL;
	    
	    if (f->raw == 0) {
		c = getc(f->fp);
		if (c == sizeof(short) || c == sizeof(float) || c == sizeof(double)) {
		    f->beginData = 2;
		    f->raw = c;
		    f->tc  = getc(f->fp);
		}
		else {		/* text input */
		    long pos;

		    ungetc(c, f->fp);
		    pos = ftell(f->fp);	/* record file position *** */
		    if ((f->tc=get_strings(f)) > sizeof(str)/2)
			estop("Too many columns in %s", f->name);
		    fseek(f->fp, pos, SEEK_SET);/* restore file position *** */
		}
		if (f->tc < f->lc)
		    estop("Too few columns in %s", f->name);
	    }
	    
	    if ((f->nb=f->raw*f->tc) > sizeof(line))
		estop("Too many columns in %s", f->name);
	    if (f->ac == ALL)
		f->lc = f->tc;
	    if (f->lc == 0)
		estop("No columns from %s", f->name);
	    if (f->rf == -1)
		f->rf = 0;
	    if (f->rt == -1)
		f->rt = 07777777777;
	    if (f->rs == -1)
		f->rs = 1;
	    
	    if (f->fp != stdin && f->rf > f->row && f->raw != 0) {
		if (fseek(f->fp, f->beginData+f->raw*(long)f->nb*(f->rf-1), 0) == -1)
		    fseek(f->fp, f->beginData, 0);
		else
		    f->row = f->rf;
	    }
	    while (f->rf > f->row) {
		data_row(f);
		if (f->eof)
		    estop("Only %ld rows in %s", f->row-1, f->name);
	    }
	    for (n=0; n < f->nc; n++)
		grand_tot += (f->col[n] == ALL) ? f->tc : 1;
	}
    }
    return (grand_tot);
}


data_read(outData)
register double	*outData;
{
register DFILE *f;
register c;
register Pointer inData;
int	i, j, k;

	inData.c = line;

	for (i=0; i < nf; i++) {
		if (!data_row(f = &df[i]))
			return (NO);

		for (j=0; j < f->nc; j++) {
			if ((c=f->col[j]) == ALL) {
				for (k=0; k < f->tc ; k++) {
					switch (f->raw) {
						case 0:
							*outData++ = atof(str[k]);
							break;
						case sizeof(short):
							*outData++ = inData.s[k];
							break;
						case sizeof(float):
							*outData++ = inData.f[k];
							break;
						case sizeof(double):
							*outData++ = inData.d[k];
							break;
					}
				}
			}
			else {
				switch (f->raw) {
					case 0:
						*outData++ = atof(str[c]);
						break;
					case sizeof(short):
						*outData++ = inData.s[c];
						break;
					case sizeof(float):
						*outData++ = inData.f[c];
						break;
					case sizeof(double):
						*outData++ = inData.d[c];
						break;
				}
			}
		}

		for (j=1; j < f->rs; j++)
			data_row(f);
	}
	return (YES);
}



static int data_row(f)
register DFILE *f;
{
register n, c = 0;

	if (f->row++ > f->rt)
		return (NO);

	if (!f->raw) {
		c = get_strings(f);
		if (f->eof)
			return (NO);
		if (c < f->lc) {
			eprintf("Too few columns in file %s row %ld\n", f->name, f->row);
			f->eof = YES;
			return (NO);
		}
		else	return (YES);
	}

	for (n=0; n < f->nb && c != EOF; line[n++]=c=getc(f->fp));

	if (n == f->nb)
		return (YES);

	if (n != 1)
		eprintf("Row %ld incomplete in %s\n", f->row, f->name);

	f->eof = YES;
	return (NO);
}


static	get_strings(f)
register DFILE	*f;
{
register FILE	*fptr = f->fp;
register c;
register char	*lptr = line;
int	 n = 0;

	if ((c=getc(fptr)) == EOF) {
		f->eof = YES;
		return (0);
	}
	while (!END(c)) {
		while (WHITE(c))
			c = getc(fptr);

		if (!END(c)) {
			str[n++] = lptr;
			do {	*lptr++ = c;
				c = getc(fptr);
			}	while (!WHITE(c) && !END(c));
			*lptr++ = ' ';
		}
	}
	if (lptr >= line+MAXLEN)
		estop("Row %ld too long in %s", f->row, f->name);

	return (n);
}


data_put(ncol, dlist)
int	ncol;
double	dlist;
{
	data_aput(ncol, &dlist);
}


data_aput(ncol, drow)
int		ncol;
double	*drow;
{
register Pointer	outData;
union {	double dbl; float flt; short sh;} out;
register n;

	if (!initialized) {
		tty = isatty(fileno(outStream)) || forceASCII;
		if (!tty) {
			char	itemSize;
			switch (outDataType) {
				case typeShort:		itemSize = sizeof(short);	break;
				case typeFloat:		itemSize = sizeof(float);	break;
				case typeDouble:	itemSize = sizeof(double);	break;
			}
			putc(itemSize, outStream);
			putc((char)ncol, outStream);
		}
		else
			outDataType = typeASCII;
		initialized = YES;
	}

	
	switch (outDataType) {
		case typeASCII:
			for (n=0; n < ncol; n++) {
				if (EOF == fprintf(outStream,sformat,drow[n],(n+1 == ncol) ? "" : sfield))
					estop("Error writing ASCII data");
			}
			break;
		case typeShort:
			outData.c = line;
			for (n=0; n < ncol; n++)
				*(outData.s)++ = drow[n];
			if (fwrite(line,ncol*sizeof(*outData.s),1,outStream) == 0)
				estop("Error writing binary short");
			break;
		case typeFloat:
			outData.c = line;
			for (n=0; n < ncol; n++)
				*(outData.f)++ = drow[n];
			if (fwrite(line,ncol*sizeof(*outData.f),1,outStream) == 0)
				estop("Error writing binary float");
			break;
		case typeDouble:
			if (fwrite(&drow,ncol*sizeof(*drow),1,outStream) == 0)
				estop("Error writing binary double");
			break;
	}

	if (tty)
		putchar('\n');
}


data_sep(string)
char	*string;
{
	sfield = string;
}


data_ascii(mode)
{
	forceASCII = mode;
}


data_out(stream)
FILE	*stream;
{
	outStream = stream;
}


data_fmt(format)
char	*format;
{
static	char	fmt[30];

	if (format == NULL) {	/* yuck */
		outDataType = typeDouble;
		sformat = "%.15g%s";
	}
	else {
		sprintf(fmt, "%%%s%%s", format);
		sformat = fmt;
	}
}


GetNum(numsp, longint)
char	**numsp;
long	*longint;
{
long	n;
char	*nums;

	nums = *numsp;
	n = 0;

	while (*nums >= '0' && *nums <= '9')
		n = 10*n + (int)(*nums++ - '0');

	if (*numsp != nums)
		*longint = n;
	*numsp = nums + 1;
}