366 lines
7.9 KiB
C
366 lines
7.9 KiB
C
/* $Header$ */
|
||
/*
|
||
* read.c: Dataset read code
|
||
*
|
||
* Routines:
|
||
* int ReadData();
|
||
*
|
||
* $Log$
|
||
* Revision 1.1 2004-01-25 09:00:49 pnenzi
|
||
*
|
||
* Added xgraph plotting program.
|
||
*
|
||
* Revision 1.2 1999/12/03 23:17:45 heideman
|
||
* apply xgraph_no_animation.patch
|
||
*
|
||
* Revision 1.1.1.1 1999/12/03 23:15:53 heideman
|
||
* xgraph-12.0
|
||
*
|
||
*/
|
||
#ifndef lint
|
||
static char rcsid[] = "$Id$";
|
||
#endif
|
||
|
||
#include "copyright.h"
|
||
#include <stdio.h>
|
||
#include <math.h>
|
||
#include <pwd.h>
|
||
#include <ctype.h>
|
||
#include "xgraph.h"
|
||
#include "xtb.h"
|
||
#include "hard_devices.h"
|
||
#include "params.h"
|
||
/*
|
||
* New dataset reading code
|
||
*/
|
||
|
||
static int setNumber = 0;
|
||
static PointList **curSpot = (PointList **) 0;
|
||
static PointList *curList = (PointList *) 0;
|
||
static int newGroup = 0;
|
||
static int redundant_set = 0;
|
||
|
||
#ifdef DO_DER
|
||
extern void Der1();
|
||
#endif
|
||
|
||
static int
|
||
rdSet(fn)
|
||
char *fn; /* Reading from file `fn' */
|
||
|
||
/*
|
||
* Set up new dataset. Will return zero if there are too many data sets.
|
||
*/
|
||
{
|
||
char setname[100];
|
||
|
||
if (!redundant_set) {
|
||
if (setNumber < MAXSETS) {
|
||
(void) sprintf(setname, "Set %d", setNumber);
|
||
if ((strcmp(PlotData[setNumber].setName, setname) == 0) && fn) {
|
||
PlotData[setNumber].setName = fn;
|
||
}
|
||
curSpot = &(PlotData[setNumber].list);
|
||
PlotData[setNumber].list = (PointList *) 0;
|
||
newGroup = 1;
|
||
setNumber++;
|
||
redundant_set = 1;
|
||
return 1;
|
||
}
|
||
else {
|
||
return 0;
|
||
}
|
||
}
|
||
else {
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
static void
|
||
rdSetName(name)
|
||
char *name; /* New set name */
|
||
|
||
/*
|
||
* Sets the name of a data set. Automatically makes a copy.
|
||
*/
|
||
{
|
||
PlotData[setNumber - 1].setName = STRDUP(name);
|
||
}
|
||
|
||
static void
|
||
rdGroup()
|
||
/*
|
||
* Set up for reading new group of points within a dataset.
|
||
*/
|
||
{
|
||
newGroup = 1;
|
||
}
|
||
|
||
static void
|
||
rdPoint(xval, yval)
|
||
double xval,
|
||
yval; /* New point */
|
||
|
||
/*
|
||
* Adds a new point to the current group of the current
|
||
* data set.
|
||
*/
|
||
{
|
||
if (newGroup) {
|
||
*curSpot = (PointList *) Malloc(sizeof(PointList));
|
||
curList = *curSpot;
|
||
curSpot = &(curList->next);
|
||
curList->numPoints = 0;
|
||
curList->allocSize = INITSIZE;
|
||
curList->xvec = (double *) Malloc((unsigned)
|
||
(INITSIZE * sizeof(double)));
|
||
curList->yvec = (double *) Malloc((unsigned)
|
||
(INITSIZE * sizeof(double)));
|
||
curList->next = (PointList *) 0;
|
||
newGroup = 0;
|
||
}
|
||
if (curList->numPoints >= curList->allocSize) {
|
||
curList->allocSize *= 2;
|
||
curList->xvec = (double *) Realloc((char *) curList->xvec,
|
||
(unsigned) (curList->allocSize *
|
||
sizeof(double)));
|
||
curList->yvec = (double *) Realloc((char *) curList->yvec,
|
||
(unsigned) (curList->allocSize *
|
||
sizeof(double)));
|
||
}
|
||
|
||
curList->xvec[curList->numPoints] = xval;
|
||
curList->yvec[curList->numPoints] = yval;
|
||
|
||
(curList->numPoints)++;
|
||
redundant_set = 0;
|
||
}
|
||
|
||
static int
|
||
rdFindMax()
|
||
/*
|
||
* Returns the maximum number of items in any one group of any
|
||
* data set.
|
||
*/
|
||
{
|
||
int i;
|
||
PointList *list;
|
||
int max = -1;
|
||
|
||
for (i = 0; i < setNumber; i++) {
|
||
for (list = PlotData[i].list; list; list = list->next) {
|
||
if (list->numPoints > max)
|
||
max = list->numPoints;
|
||
}
|
||
}
|
||
return max;
|
||
}
|
||
|
||
|
||
typedef enum line_type {
|
||
EMPTY, COMMENT, SETNAME, DRAWPNT, MOVEPNT, SETPARAM, ERROR
|
||
} LineType;
|
||
|
||
typedef struct point_defn {
|
||
double xval,
|
||
yval;
|
||
} Point;
|
||
|
||
typedef struct parmval_defn {
|
||
char *name,
|
||
*value;
|
||
} ParmVals;
|
||
|
||
typedef struct line_info {
|
||
LineType type;
|
||
union val_defn {
|
||
char *str; /* SETNAME, ERROR */
|
||
Point pnt; /* DRAWPNT, MOVEPNT */
|
||
ParmVals parm; /* SETPARAM */
|
||
} val;
|
||
} LineInfo;
|
||
|
||
static LineType
|
||
parse_line(line, result)
|
||
char *line; /* Line to parse */
|
||
LineInfo *result; /* Returned result */
|
||
|
||
/*
|
||
* Parses `line' into one of the types given in the definition
|
||
* of LineInfo. The appropriate values are filled into `result'.
|
||
* Below are the current formats for each type:
|
||
* EMPTY: All white space
|
||
* COMMENT: Starts with "#"
|
||
* SETNAME: A name enclosed in double quotes
|
||
* DRAWPNT: Two numbers optionally preceded by keyword "draw"
|
||
* MOVEPNT: Two numbers preceded by keyword "move"
|
||
* SETPARAM: Two non-null strings separated by ":"
|
||
* ERROR: Not any of the above (an error message is returned)
|
||
* Note that often the values are pointers into the line itself
|
||
* and should be copied if they are to be used over a long period.
|
||
*/
|
||
{
|
||
char *first;
|
||
|
||
/* Find first non-space character */
|
||
while (*line && isspace(*line))
|
||
line++;
|
||
if (*line) {
|
||
if (*line == '#') {
|
||
/* comment */
|
||
result->type = COMMENT;
|
||
}
|
||
else if (*line == '"') {
|
||
/* setname */
|
||
result->type = SETNAME;
|
||
line++;
|
||
result->val.str = line;
|
||
while (*line && (*line != '\n') && (*line != '"'))
|
||
line++;
|
||
if (*line)
|
||
*line = '\0';
|
||
}
|
||
else {
|
||
first = line;
|
||
while (*line && !isspace(*line))
|
||
line++;
|
||
if (*line) {
|
||
*line = '\0';
|
||
if (stricmp(first, "move") == 0) {
|
||
/* MOVEPNT */
|
||
if (sscanf(line + 1, "%lf %lf",
|
||
&result->val.pnt.xval,
|
||
&result->val.pnt.yval) == 2) {
|
||
result->type = MOVEPNT;
|
||
}
|
||
else {
|
||
result->type = ERROR;
|
||
result->val.str = "Cannot read move coordinates";
|
||
}
|
||
}
|
||
else if (stricmp(first, "draw") == 0) {
|
||
/* DRAWPNT */
|
||
if (sscanf(line + 1, "%lf %lf",
|
||
&result->val.pnt.xval,
|
||
&result->val.pnt.yval) == 2) {
|
||
result->type = DRAWPNT;
|
||
}
|
||
else {
|
||
result->type = ERROR;
|
||
result->val.str = "Cannot read draw coordinates";
|
||
}
|
||
}
|
||
else if (first[strlen(first) - 1] == ':') {
|
||
/* SETPARAM */
|
||
first[strlen(first) - 1] = '\0';
|
||
result->val.parm.name = first;
|
||
line++;
|
||
while (*line && isspace(*line))
|
||
line++;
|
||
/* may be a \n at end of it */
|
||
if (line[strlen(line) - 1] == '\n') {
|
||
line[strlen(line) - 1] = '\0';
|
||
}
|
||
result->val.parm.value = line;
|
||
result->type = SETPARAM;
|
||
}
|
||
else if (sscanf(first, "%lf", &result->val.pnt.xval) == 1) {
|
||
/* DRAWPNT */
|
||
if (sscanf(line + 1, "%lf", &result->val.pnt.yval) == 1) {
|
||
result->type = DRAWPNT;
|
||
}
|
||
else {
|
||
result->type = ERROR;
|
||
result->val.str = "Cannot read second coordinate";
|
||
}
|
||
}
|
||
else {
|
||
/* ERROR */
|
||
result->type = ERROR;
|
||
result->val.str = "Unknown line type";
|
||
}
|
||
}
|
||
else {
|
||
/* ERROR */
|
||
result->type = ERROR;
|
||
result->val.str = "Premature end of line";
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
/* empty */
|
||
result->type = EMPTY;
|
||
}
|
||
return result->type;
|
||
}
|
||
|
||
|
||
int
|
||
ReadData(stream, filename)
|
||
FILE *stream;
|
||
char *filename;
|
||
|
||
/*
|
||
* Reads in the data sets from the supplied stream. If the format
|
||
* is correct, it returns the current maximum number of points across
|
||
* all data sets. If there is an error, it returns -1.
|
||
*/
|
||
{
|
||
char buffer[MAXBUFSIZE];
|
||
LineInfo info;
|
||
int line_count = 0;
|
||
int errors = 0;
|
||
|
||
if (!rdSet(filename)) {
|
||
(void) fprintf(stderr, "Error in file `%s' at line %d:\n %s\n",
|
||
filename, line_count,
|
||
"Too many data sets - extra data ignored");
|
||
return -1;
|
||
}
|
||
while (fgets(buffer, MAXBUFSIZE, stream)) {
|
||
line_count++;
|
||
switch (parse_line(buffer, &info)) {
|
||
case EMPTY:
|
||
if (!rdSet(filename)) {
|
||
(void) fprintf(stderr, "Error in file `%s' at line %d:\n %s\n",
|
||
filename, line_count,
|
||
"Too many data sets - extra data ignored");
|
||
return -1;
|
||
}
|
||
break;
|
||
case COMMENT:
|
||
/* nothing */
|
||
break;
|
||
case SETNAME:
|
||
rdSetName(info.val.str);
|
||
break;
|
||
case DRAWPNT:
|
||
rdPoint(info.val.pnt.xval, info.val.pnt.yval);
|
||
break;
|
||
case MOVEPNT:
|
||
rdGroup();
|
||
rdPoint(info.val.pnt.xval, info.val.pnt.yval);
|
||
break;
|
||
case SETPARAM:
|
||
param_reset(info.val.parm.name, info.val.parm.value);
|
||
break;
|
||
default:
|
||
if (filename) {
|
||
(void) fprintf(stderr, "Error in file `%s' at line %d:\n %s\n",
|
||
filename, line_count, info.val.str);
|
||
errors++;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
#ifdef DO_DER
|
||
Der1();
|
||
#endif
|
||
if (errors)
|
||
return -1;
|
||
else
|
||
return rdFindMax();
|
||
}
|
||
|
||
|