plt - Software for 2D Plots 2.5
(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;
}