DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T r

⟦6bf1f1e80⟧ TextFile

    Length: 4816 (0x12d0)
    Types: TextFile
    Names: »readtab.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/graph/readtab.c« 

TextFile

/*
 * 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 );
}