home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1986 Alan Kent
- *
- * Permission is granted to freely distribute part or
- * all of this code as long as it is not for profit
- * and this message is retained in the code.
- *
- * No resposibility is taken for any damage or incorect
- * results this program generates.
- *
- */
-
-
- #include <stdio.h>
- #include <ctype.h>
- #include <math.h>
- #include "graph.h"
-
-
- #define BUF_SIZE 512
-
-
- extern double log10 ();
- extern double pow ();
- extern table_st *new_table ();
-
-
- table_st *
- read_table ( filename , num_cols , num_rows )
- char *filename;
- int num_cols , num_rows;
- {
- char *skip_blanks ();
- char *scan_value ();
-
- char buf[ BUF_SIZE ];
- char *p;
- FILE *fp;
- int rows , cols , i;
- table_st *table , *tp;
- double val;
-
-
- /* first, open the file */
-
- if ( ( fp = fopen ( filename , "r" ) ) == NULL )
- abort ( "failed to open file '%s'" , filename );
-
- if ( num_cols < 0 || num_rows < 0 ) {
-
- /* pass one of file: count rows and cols */
-
- rows = 0;
- cols = 0;
- do {
- if ( fgets ( buf , BUF_SIZE , fp ) == NULL ) {
- /* empty data file */
- fclose ( fp );
- return ( NULL );
- }
- } while ( *skip_blanks ( buf ) == '\0' );
- p = skip_blanks ( buf );
- while ( *p != '\0' ) {
- cols++;
- p = scan_value ( p , &val );
- if ( p == NULL )
- abort ( "Data file '%s' contains non-numeric data" , filename );
- p = skip_blanks ( p );
- }
- rows++;
- while ( fgets ( buf , BUF_SIZE , fp ) != NULL ) {
- if ( *skip_blanks ( buf ) != '\0' )
- rows++;
- }
-
- /* allocate and read new table */
-
- rewind ( fp );
- }
- else {
- rows = num_rows;
- cols = num_cols;
- }
-
- /*
- printf ( "Data file '%s' contains %d columns and %d rows of data\n" ,
- filename , cols , rows );
- */
-
- table = new_table ( cols , rows );
- i = 0;
- while ( fgets ( buf , BUF_SIZE , fp ) != NULL && i < rows ) {
- if ( *skip_blanks ( buf ) != '\0' ) {
- tp = table;
- p = skip_blanks ( buf );
- while ( *p != '\0' ) {
- if ( tp == NULL )
- break;
- p = scan_value ( p , &val );
- if ( p == NULL )
- abort ( "illegal data on data file '%s'" , filename );
- p = skip_blanks ( p );
- tp->data[i] = val;
- tp = tp->next;
- }
- i++;
- if ( tp != NULL )
- abort ( "line too short in data file '%s'" , filename );
- }
- }
-
- /* if table size got from parameters, it is possible that the table */
- /* allocated has more rows than was specified (cols are reported as */
- /* an error). This is alright, but the table should be shrunk in size. */
- /* note that as malloc() does not care about our table size, it does not */
- /* matter if the size field is larger than the actual table. */
-
- for ( tp = table; tp != NULL; tp = tp->next )
- tp->size = i;
-
- fclose ( fp );
- return ( table );
- }
-
-
-
- char *
- scan_value ( in_str , pval )
- char *in_str;
- double *pval;
- {
- register char *str;
- int sign;
- int num_digits;
- register int exponent;
- int exp2;
- double val;
-
-
- str = in_str; /* register variable for SPEED */
-
- /* get leading +/- sign */
-
- sign = 1;
- if ( *str == '+' )
- str++;
- else if ( *str == '-' ) {
- str++;
- sign = -1;
- }
-
- /* get digit string */
-
- num_digits = 0;
- val = 0.0;
- exponent = 0;
- while ( isdigit ( *str ) ) {
- val = val * 10.0 + ( *str - '0' );
- str++;
- num_digits++;
- }
- if ( *str == '.' ) {
- str++;
- while ( isdigit ( *str ) ) {
- val = val * 10.0 + ( *str - '0' );
- exponent--;
- str++;
- num_digits++;
- }
- }
-
- if ( num_digits == 0 )
- return ( NULL );
-
- if ( sign < 0 )
- val = -val;
-
- if ( *str == 'e' || *str == 'E' ) {
- str++;
- sign = 1;
- if ( *str == '+' )
- str++;
- else if ( *str == '-' ) {
- str++;
- sign = -1;
- }
- if ( ! isdigit ( *str ) )
- return ( NULL );
- exp2 = 0;
- while ( isdigit ( *str ) ) {
- exp2 = exp2 * 10 + ( *str - '0' );
- str++;
- }
- if ( sign < 0 )
- exp2 = -exp2;
- exponent += exp2;
- }
-
- /* now, merge the value and the exponent */
- /* anyone know a PORTABLE and fast way of doing this accurately? */
- /* Using the log functions can introduce errors */
-
- if ( exponent < -12 || exponent > 12 ) {
- /* For speed, use pow for large exponents */
- val *= pow ( 10.0 , (double)exponent );
- }
- else {
- while ( exponent < 0 ) {
- val *= 0.1;
- exponent++;
- }
- while ( exponent > 0 ) {
- val *= 10.0;
- exponent--;
- }
- }
-
- *pval = val;
-
- #ifdef USING_ATOF
- /* this requires scanning the string twice and does not detect */
- /* errors at all */
- str = in_str;
- *pval = atof ( str );
- while ( *str != '\0' && ! isspace ( *str ) )
- str++;
- #endif
-
- return ( str );
- }
-
-
-
- static char *
- skip_blanks ( str )
- char *str;
- {
- while ( isspace ( *str ) )
- str++;
- if ( *str == '#' )
- while ( *str != '\0' )
- str++;
- return ( str );
- }
-
-