static char *SccsId = "@(#)read.c 4.13 (TU-Delft) 06/22/93";
/**********************************************************

Name/Version      : simeye/4.13

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author(s)         : A.J. van Genderen
Creation date     : 29-May-1990
Modified by       : 
Modification date : 


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1990 , All rights reserved
**********************************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dmincl.h>

#include "define.h"
#include "type.h"
#include "extern.h"

extern struct signal *storedSig;

extern DM_PROJECT *projKey;

extern char *modNameOf ();

#define MAXSLSNAME  10

static struct signal **Array_signals = NULL;

char **SV = NULL;
int *svi = 0;
int SV_cnt = 0;
int SV_size = 0;

void delSigList ();

int readLogic (name, intermediate)
char *name;
int intermediate;
/*                    intermediate = 0  : no intermediate read
/*                                 = 2  : start intermediate read
/*                                 = 1  : intermediate read
/*                                 = -1 : end intermediate read
*/
{
    char newname[40];
    char help[132];
    int i;
    long time;
    char c;
    static char *filename;
    static FILE *fp = NULL;
    static DM_CELL *simout_key = NULL;
    static DM_STREAM *dsp_res = NULL;
    static RES_FILE *ResF;
    static long fp_mem_pos;
    RES_FILE *read_paths ();
    STRING_REF * str_ref;
    RES_PATH * rs;
    struct signal *sig;
    static struct signal *last_sig_read;
    static struct signal *Old_end_signal;
    struct sig_value *sval;
    int value;
    static double Timeconvert;
    struct stat sbuf;
    STRING_REF * names_from_path ();


    if (intermediate == 0 || intermediate == 2) {

	last_sig_read = NULL;

	sprintf (newname, "%s", name);
	i = 0;
	while (newname[i] != ' ' && newname[i] != '\0') i++;
	newname[i] = '\0';

	if (use_io_views) {
	    if (!dsp_res) {
		if (!simout_key
		    && dmGetMetaDesignData (EXISTCELL, projKey, 
					    modNameOf (newname), SIMOUT) == 1) {
		    simout_key = dmCheckOut (projKey, newname, WORKING, 
					     DONTCARE, SIMOUT, READONLY);
		}
		if (!simout_key 
		    || (!dsp_res && dmStat (simout_key, "res", &sbuf) != 0)) {
		    if (!intermediate) {
			sprintf (help, 
			   "Cannot open 'res' stream for cell %s", newname);
			windowMessage (help, -1);
			if (simout_key) {
			    dmCheckIn (simout_key, COMPLETE);
			    simout_key = NULL;
			}
		    }
		    return (0);
		}
		dsp_res = dmOpenStream (simout_key, "res", "r");
		fp = dsp_res -> dmfp;
	    }

	    /* Added these lines for filename initialization (PvdW). */
	    NEW (filename, strlen (newname) + 5, char);
	    sprintf (filename, "%s.res", newname);
	}
	else {
	    i = 0;
	    while (newname[i] != '\0' && i < MAXSLSNAME) i++;
	    newname[i] = '\0';

	    NEW (filename, strlen (newname) + 5, char);
	    sprintf (filename, "%s.res", newname);

	    if (!fp && (fp = fopen (filename, "r")) == NULL) {
		if (!intermediate) {
		    sprintf (help, "Cannot open %s", filename);
		    windowMessage (help, -1);
		}
		return (0);
	    }
	}

	if ((ResF = read_paths (fp, filename)) == NULL) {
	    if (intermediate == 0 || intermediate == -1) {
		sprintf (help, "Empty file %s", filename);
		windowMessage (help, -1);
		if (use_io_views) {
		    dmCloseStream (dsp_res, COMPLETE);
		    dsp_res = NULL;
		    dmCheckIn (simout_key, COMPLETE);
		    simout_key = NULL;
		}
		else
		    fclose (fp);
		fp = NULL;
	    }
	    else
		rewind (fp);
	    return (0);
	}

	if (Append) {
	    Old_end_signal = End_signal;
	}
	else {
	    delSigList (Begin_signal);

	    Nr_signals = 0;

	    Begin_signal = NULL;
	    End_signal = NULL;

	    resetStringValues ();
	}

	rs = ResF -> signals;
	while (rs) {
	    str_ref = names_from_path (0, rs -> path);
	    while (str_ref) {
		Nr_signals++;
		NEW (sig, 1, struct signal);
		sig -> name = str_ref -> str;
		sig -> next = NULL;
		sig -> orig_next = NULL;
		sig -> prev = NULL;
		sig -> layover = NULL;
		sig -> begin_value = NULL;
		sig -> end_value = NULL;
		sig -> begin_value_L = NULL;
		sig -> end_value_L = NULL;
		sig -> begin_value_U = NULL;
		sig -> end_value_U = NULL;
		sig -> expr = NULL;
		sig -> no_edit = 0;
		sig -> endless = 0;
		sig -> stringValue = 0;
		if (End_signal) {
		    End_signal -> next = sig;
		    End_signal -> orig_next = sig;
		    sig -> prev = End_signal;
		    End_signal = sig;
		}
		else {
		    Begin_signal = End_signal = sig;
		}
		str_ref = str_ref -> next;
	    }
	    rs = rs -> next;
	}

	if (Append) {

	    /* maintain old value of Timescaling for Timescaling */

	    Timeconvert = ResF -> scaling / Timescaling;
	}
	else {
	    Timescaling = ResF -> scaling;
	}
	Voltscaling = 2.5;

	fseek (fp, 0, 0);
	while (getc (fp) != '\n');    /* search begin of signal values */

	fp_mem_pos = ftell (fp);
    }
    else {
	fseek (fp, fp_mem_pos, 0);
    }

    /* read signal values */

    while (fscanf (fp, "%ld", &time) == 1) {
	
	if (Append) {

	    if (time * Timeconvert * 10 > MAXLONG) {
		windowMessage (
		  "New x values too large (as compared to old x values)", -1);
		delSigList (Old_end_signal -> orig_next);
		Old_end_signal -> orig_next = NULL;
		Old_end_signal -> next = NULL;
		if (intermediate == 0 || intermediate == -1) {
		    if (use_io_views) {
			dmCloseStream (dsp_res, COMPLETE);
			dsp_res = NULL;
			dmCheckIn (simout_key, COMPLETE);
			simout_key = NULL;
		    }
		    else
			fclose (fp);
		    fp = NULL;
		}
		return (0);
	    }

	    time = time * Timeconvert;

	    sig = Old_end_signal -> orig_next;
	}
	else {
	    sig = Begin_signal;
	}

	if (intermediate != 0 && last_sig_read) {
	    while (sig != last_sig_read) {
		fscanf (fp, "%*c");
		sig = sig -> orig_next;
	    }
	    last_sig_read = NULL;
	}

	while (sig) {

	    if (fscanf (fp, "%c", &c) != 1)
                break;

	    if (c == 'h') {
		value = 2;
	    }
	    else if (c == 'l') {
		value = 0;
	    }
	    else if (c == 'x') {
		value = 1;
	    }
	    else if (c == 'f') {
		value = -1;        /* free state, no draw */
	    }
	    else if (c == '(') {
		i = 0;
		while ((c = getc (fp)) != ')' && c != '\n' && c != EOF)
		    help[i++] = c;
		help[i] = '\0';
		value = addStringValue (help);
		sig -> stringValue = 1;
	    }
	    else {
		fprintf (stderr, "He ? c = %c\n", c);
	    }

	    if (!sig -> end_value || sig -> end_value -> value != value) {
		NEW (sval, 1, struct sig_value);
		sval -> time = time;
		sval -> value = value;
		sval -> next = NULL;
		sval -> prev = NULL;

		if (sig -> end_value) {
		    sig -> end_value -> next = sval;
		    sval -> prev = sig -> end_value;
		    sig -> end_value = sval;
		}
		else {
		    sig -> begin_value = sig -> end_value = sval;
		}
	    }

	    sig = sig -> orig_next;
	}

	last_sig_read = sig;
	fp_mem_pos = ftell (fp);
    }

    /* make all new signals end at the time that is Endtime 
       for the current input file */

    if (Append) {
	sig = Old_end_signal -> orig_next;
    }
    else {
	sig = Begin_signal;
    }
    while (sig) {
	if (sig -> end_value && sig -> end_value -> time < time) {
	    NEW (sval, 1, struct sig_value);
	    sval -> time = time;
	    sval -> value = sig -> end_value -> value;
	    sval -> next = NULL;
	    sig -> end_value -> next = sval;
	    sval -> prev = sig -> end_value;
	    sig -> end_value = sval;
	}
	sig = sig -> orig_next;
    }

    if (Append)
	Endtime = Max (Endtime, time);
    else {
	Begintime = 0;
	Endtime = time;
    }

    Global_umin = 0;
    Global_umax = 2;

    if (intermediate == 0 || intermediate == -1) {
	if (use_io_views) {
	    dmCloseStream (dsp_res, COMPLETE);
	    dsp_res = NULL;
	    dmCheckIn (simout_key, COMPLETE);
	    simout_key = NULL;
	}
	else
	    fclose (fp);
	fp = NULL;
    }
    return (1);
}


int readWaves (name, intermediate)   /* read .plt format or spice output file */
char *name;
int intermediate;
{
    char newname[40];
    char help[56];
    int i;
    long time;
    char b;
    char c;
    static char *filename;
    static FILE *fp = NULL;
    static DM_CELL *simout_key = NULL;
    static DM_STREAM *dsp_plt = NULL;
    static long fp_mem_pos;
    struct signal *sig;
    struct sig_value *sval;
    char buf[264];
    int nr;
    int h;
    static int Old_nr_signals;
    static struct signal *Old_end_signal;
    double newTimescaling;
    double newVoltscaling;
    double newGlobal_umin;
    double newGlobal_umax;
    static double Timeconvert;
    static double Voltconvert;
    struct stat sbuf;

    if (intermediate == 0 || intermediate == 2) {

	sprintf (newname, "%s", name);
	i = 0;
	while (newname[i] != ' ' && newname[i] != '\0') i++;
	newname[i] = '\0';

        if (use_io_views) {
            if (!dsp_plt) {
                if (!simout_key
                    && dmGetMetaDesignData (EXISTCELL, projKey,
                                            modNameOf (newname), SIMOUT) == 1) {
                    simout_key = dmCheckOut (projKey, newname, WORKING,
                                             DONTCARE, SIMOUT, READONLY);
                }
                if (!simout_key
                    || (!dsp_plt && dmStat (simout_key, "plt", &sbuf) != 0)) {
                    if (!intermediate) {
                        sprintf (help,
                           "Cannot open 'plt' stream for cell %s", newname);
                        windowMessage (help, -1);
                        if (simout_key) {
                            dmCheckIn (simout_key, COMPLETE);
                            simout_key = NULL;
                        }
                    }
                    return (0);
                }
                dsp_plt = dmOpenStream (simout_key, "plt", "r");
                fp = dsp_plt -> dmfp;
            }

	    /* Added these lines for filename initialization (PvdW). */
	    NEW (filename, strlen (newname) + 5, char);
	    sprintf (filename, "%s.plt", newname);
        }
        else {
	    i = 0;
	    while (newname[i] != '\0' && i < MAXSLSNAME) i++;
	    newname[i] = '\0';

	    NEW (filename, strlen (newname) + 5, char);
	    sprintf (filename, "%s.plt", newname);

	    if (!fp && (fp = fopen (filename, "r")) == NULL) {
		if (!intermediate) {
		    sprintf (help, "Cannot open %s", filename);
		    windowMessage (help, -1);
		}
		return (0);
	    }
	}

	if (fscanf (fp, "%d", &nr) <= 0) {
	    if (intermediate == 0 || intermediate == -1) {
		sprintf (help, "Empty file %s", filename);
		windowMessage (help, -1);
                if (use_io_views) {
                    dmCloseStream (dsp_plt, COMPLETE);
                    dsp_plt = NULL;
                    dmCheckIn (simout_key, COMPLETE);
                    simout_key = NULL;
                }
                else
		    fclose (fp);
		fp = NULL;
	    }
	    else
		rewind (fp);
	    return (0);
	}

	if (Append) {
	    Old_nr_signals = Nr_signals;
	    Old_end_signal = End_signal;
	    Nr_signals = Nr_signals + nr;
	}
	else {
	    delSigList (Begin_signal);

	    Old_nr_signals = 0;
	    Nr_signals = nr;

	    Begin_signal = NULL;
	    End_signal = NULL;

	    resetStringValues ();
	}

	for (i = Old_nr_signals; i < Nr_signals; i++) {

	    fscanf (fp, "%s", buf);

	    NEW (sig, 1, struct signal);
	    NEW (sig -> name, strlen (buf) + 1, char);
	    sprintf (sig -> name, "%s", buf);
	    sig -> orig_next = NULL;
	    sig -> next = NULL;
	    sig -> prev = NULL;
	    sig -> layover = NULL;
	    sig -> begin_value = NULL;
	    sig -> end_value = NULL;
	    sig -> begin_value_L = NULL;
	    sig -> end_value_L = NULL;
	    sig -> begin_value_U = NULL;
	    sig -> end_value_U = NULL;
	    sig -> expr = NULL;
	    sig -> no_edit = 0;
	    sig -> endless = 0;
	    sig -> stringValue = 0;
	    if (End_signal) {
		End_signal -> orig_next = sig;
		End_signal -> next = sig;
		sig -> prev = End_signal;
		End_signal = sig;
	    }
	    else {
		Begin_signal = End_signal = sig;
	    }
	}

	/* make a direct accessible datastructure for the signals */

	NEW (Array_signals, Nr_signals, struct signal *);
	sig = Begin_signal;
	for (i = 0; i < Nr_signals; i++) {
	    Array_signals[i] = sig;
	    sig = sig -> orig_next;
	}

	/* */

	h = 0;

	h += fscanf (fp, "%lf", &newTimescaling);
	h += fscanf (fp, "%lf", &newVoltscaling);

	h += fscanf (fp, "%d", &newGlobal_umin);
	h += fscanf (fp, "%d", &newGlobal_umax);

	if (h != 4) {
	    if (Append) {
		delSigList (Old_end_signal -> orig_next);
		Old_end_signal -> orig_next = NULL;
		Old_end_signal -> next = NULL;
	    }
	    else {
		delSigList (Begin_signal);
		Begin_signal = NULL;
	    }
	    if (intermediate == 0 || intermediate == -1) {
		windowMessage ("Incomplete input file", -1);
	        if (use_io_views) {
		    dmCloseStream (dsp_plt, COMPLETE);
		    dsp_plt = NULL;
		    dmCheckIn (simout_key, COMPLETE);
		    simout_key = NULL;
		}
		else
		    fclose (fp);
		fp = NULL;
	    }
	    else
		rewind (fp);
	    return (0);
	}

	if (Append) {
	    Timeconvert = newTimescaling / Timescaling;
	    Voltconvert = newVoltscaling / Voltscaling;

	    if (newGlobal_umin < Global_umin)
		Global_umin = newGlobal_umin;
	    if (newGlobal_umax > Global_umax)
		Global_umax = newGlobal_umax;

	    if (Voltconvert > 1e4) {
		windowMessage (
		  "New y scale factor / old y scale factor > 1e4", -1);
		delSigList (Old_end_signal -> orig_next);
		Old_end_signal -> orig_next = NULL;
		Old_end_signal -> next = NULL;
	        if (use_io_views) {
		    dmCloseStream (dsp_plt, COMPLETE);
		    dsp_plt = NULL;
		    dmCheckIn (simout_key, COMPLETE);
		    simout_key = NULL;
		}
		else
		    fclose (fp);
		fp = NULL;
		return (0);
	    }
	}
	else {
	    Timescaling = newTimescaling;
	    Voltscaling = newVoltscaling;

	    Global_umin = newGlobal_umin;
	    Global_umax = newGlobal_umax;
	}

	if (Global_umax <= Global_umin)
	    Global_umax = Global_umin + 1.0 / Voltscaling;

	fp_mem_pos = ftell (fp);
    }
    else {
	fseek (fp, fp_mem_pos, 0);
    }

    while (fscanf (fp, "%ld", &time) == 1) {

	if (Append) {
	    if (time * Timeconvert * 10 > MAXLONG) {
		windowMessage (
		  "New x values too large (as compared to old x values)", -1);
		delSigList (Old_end_signal -> orig_next);
		Old_end_signal -> orig_next = NULL;
		Old_end_signal -> next = NULL;
		if (intermediate == 0 || intermediate == -1) {
                    if (use_io_views) {
                        dmCloseStream (dsp_plt, COMPLETE);
                        dsp_plt = NULL;
                        dmCheckIn (simout_key, COMPLETE);
                        simout_key = NULL;
                    }
                    else
			fclose (fp);
		    fp = NULL;
		}
		return (0);
	    }

	    time = time * Timeconvert;
	}

        while ((c = fgetc (fp)) != '\n' && c != EOF) {

            if (fscanf (fp, "%d", &i) != 1)
                break;

            i--;

	    if (Append)
		i = i + Old_nr_signals;

	    NEW (sval, 1, struct sig_value);
	    sval -> time = time;
	    sval -> next = NULL;
	    sval -> prev = NULL;

            if (fscanf (fp, "%c", &b) != 1)
                break;
            if (fscanf (fp, "%d", &sval -> value) != 1)
                break;

            if (Append)
		sval -> value = sval -> value * Voltconvert;

            if (b == 'l') {
		if (sval -> value < Global_umin) {
		    Global_umin = sval -> value;
		}
		if (Array_signals[i] -> end_value_L) {
		    Array_signals[i] -> end_value_L -> next = sval;
		    sval -> prev = Array_signals[i] -> end_value_L;
		    Array_signals[i] -> end_value_L = sval;
		}
		else {
		    Array_signals[i] -> begin_value_L = 
		    Array_signals[i] -> end_value_L = sval;
		}
            }
            else if (b == 'u') {
		if (sval -> value > Global_umax) {
		    Global_umax = sval -> value;
		}
		if (Array_signals[i] -> end_value_U) {
		    Array_signals[i] -> end_value_U -> next = sval;
		    sval -> prev = Array_signals[i] -> end_value_U;
		    Array_signals[i] -> end_value_U = sval;
		}
		else {
		    Array_signals[i] -> begin_value_U = 
		    Array_signals[i] -> end_value_U = sval;
		}
            }
        }

	if (c == '\n')
	    fp_mem_pos = ftell (fp);  
	    /* remember only positions just before time value */
    }

    if (Append)
	Endtime = Max (Endtime, time);
    else {
	Begintime = 0;
	Endtime = time;
    }

    if (intermediate == 0 || intermediate == -1) {
        if (use_io_views) {
            dmCloseStream (dsp_plt, COMPLETE);
            dsp_plt = NULL;
            dmCheckIn (simout_key, COMPLETE);
            simout_key = NULL;
        }
        else
	    fclose (fp);
	fp = NULL;
    }
    return (1);
}

int readSpice (name, intermediate)
char *name;
int intermediate;
{
    char str1[512];
    char str2[512];

    char newname[40];
    char help[56];
    int i;
    long time;
    char *filename;
    FILE *fp;
    struct signal *sig;
    struct sig_value *sval;
    char buf[264];
    double t;
    double v;
    double mint;
    double maxt;
    double minv;
    double maxv;
    int match, end;
    char c;
    long foffset;
    long ftell ();
    double convdec ();
    struct signal *Old_end_signal;
    int Old_nr_signals;
    double newTimescaling;
    double newVoltscaling;
    double newGlobal_umin;
    double newGlobal_umax;
    int plot_tran;
    int found;
    int spice3;


    sprintf (newname, "%s", name);
    i = 0;
    while (newname[i] != ' ' && newname[i] != '\0') i++;
    newname[i] = '\0';

    NEW (filename, strlen (newname) + 5, char);
    sprintf (filename, "%s.ana", newname);

    if ((fp = fopen (filename, "r")) == NULL) {
	if (!intermediate) {
	    sprintf (help, "Cannot open %s", filename);
	    windowMessage (help, -1);
	}
	return (0);
    }

    spice3 = -1;

    found = 0;
    while (1) {
        sprintf (str1, "");

        match = 0;
        while (!match && fscanf (fp, "%s", str2) == 1) {

            if (spice3 == -1) {
		if (strcmp (str2, "Circuit:") == 0) {
		    spice3 = 1;     /* it is a spice3 ouput file */
		}
		else
		    spice3 = 0;     /* it is a spice2 ouput file */
	    }

            if (spice3 == 0 && 
		((strcmp (str1, "TRANSIENT") == 0
                 && strcmp (str2, "ANALYSIS") == 0)
                 || (strcmp (str1, "transient") == 0
                     && strcmp (str2, "analysis") == 0))) {
                match = 1;
            }

            if (spice3 == 1 
		&& (strcmp (str1, "transient") == 0
		    || strcmp (str1, "Transient") == 0)
		&& strcmp (str2, "Index") == 0) {
                match = 1;
	    }

            if (spice3 == 1 && (strcmp (str2, "transient") == 0
				|| strcmp (str2, "Transient") == 0)) {
		while (getc (fp) != '\n');
		if (getc (fp) == '-') {
		    while (getc (fp) != '\n');
		}
	    }

            strcpy (str1, str2);
        }

        if (spice3 == 0) { 
	    if (match
		&& (fscanf (fp, "%s", str1) == 1
		    && (!(strcmp (str1, "TEMPERATURE") == 0
			  || strcmp (str1, "temperature") == 0)))) {
		continue;    /* it is an error message or something */
	    }

	    plot_tran = 0;
	    match = 0;
	    while (!match && fscanf (fp, "%s", str1) == 1) {

		if (strcmp (str1, "LEGEND:") == 0
		    || strcmp (str1, "legend:") == 0) {
		    plot_tran = 1;
		    break;
		}

		if (strcmp (str1, "TIME") == 0
		    || strcmp (str1, "time") == 0) {
		    match = 1;
		}
	    }

	    if (plot_tran)
		continue;
	}

        if (!match)
            break;

	if (spice3 == 1) {
	    fscanf (fp, "%*s");    /* skip string 'time' */
	}

        if (Append || found) {
	    Old_end_signal = End_signal;
	    Old_nr_signals = Nr_signals;
        }
        else {
	    delSigList (Begin_signal);

	    Begin_signal = NULL;
	    End_signal = NULL;
	    Old_nr_signals = Nr_signals = 0;

	    resetStringValues ();
        }

        while ((c = getc (fp)) == ' ' || c == '\t');

        while (c != '\n') {
            ungetc (c, fp);

            fscanf (fp, "%s", buf);

	    NEW (sig, 1, struct signal);
	    NEW (sig -> name, strlen (buf) + 1, char);
	    sprintf (sig -> name, "%s", buf);
	    sig -> orig_next = NULL;
	    sig -> next = NULL;
	    sig -> prev = NULL;
	    sig -> layover = NULL;
	    sig -> begin_value = NULL;
	    sig -> end_value = NULL;
	    sig -> begin_value_L = NULL;
	    sig -> end_value_L = NULL;
	    sig -> begin_value_U = NULL;
	    sig -> end_value_U = NULL;
	    sig -> expr = NULL;
	    sig -> no_edit = 0;
	    sig -> endless = 0;
	    sig -> stringValue = 0;
	    if (End_signal) {
	        End_signal -> orig_next = sig;
	        End_signal -> next = sig;
	        sig -> prev = End_signal;
	        End_signal = sig;
	    }
	    else {
	        Begin_signal = End_signal = sig;
	    }
    
	    Nr_signals++;
	    while ((c = getc (fp)) == ' ' || c == '\t');
        }
    
	if (spice3 == 1) {
	    while (getc (fp) != '\n');  /* skip '-------  ... ' */
	}

        foffset = ftell (fp);
    
	mint = 1e99;
        maxt = 0;
        minv = 1e99;   /* MAXREAL */
        maxv = -1e99;  /* MINREAL */
    
	if (spice3 == 1) {
	    /* the first item on the line is an index, 
	       the second item is the time */
	    fscanf (fp, "%*d");
	}

        end = 0;
        while (!end && fscanf (fp, "%le", &t) > 0) {

	    if (t > maxt) 
	        maxt = t;
	    if (t < mint) 
	        mint = t;
    
	    for (i = Old_nr_signals; i < Nr_signals; i++) {
    
                if (fscanf (fp, "%le", &v) < 0) {
		    sprintf (help, "Error in reading transient analysis of %s", 
			           filename);
		    windowMessage (help, -1);
		    fclose (fp);
		    return (0);
	        }
    
	        if (v > maxv)
		    maxv = v;

	        if (v < minv)
		    minv = v;
	    }

	    if (spice3 == 0) {
		while ((c = getc (fp)) != '\n');
		while ((c = getc (fp)) == ' ' || c == '\t');
		if (c < '0' || c > '9') end = 1;
		ungetc (c, fp);
	    }

	    if (spice3 == 1) {
		while ((c = getc (fp)) == ' ' || c == '\t' 
		       || c == '\n' || c == '');

		if (c == 'I' && getc (fp) == 'n' && getc (fp) == 'd'
		    && getc (fp) == 'e' && getc (fp) == 'x') {
		    if (c != EOF) while ((c = getc (fp)) != '\n');
	            if (c != EOF) while ((c = getc (fp)) != '\n');  
						   /* skip '-------  ... ' */
                    if (c != EOF) c = getc (fp);
		}

		if (c >= '0' && c <= '9') {
		    ungetc (c, fp);

		    /* the first item on the line is an index, 
		       the second item is the time */

		    fscanf (fp, "%*d");
		}
		else {
		    end = 1;
		}
	    }
        }

        if (maxt <= 0) {
	    sprintf (help, "end of simulation time <= 0 in %s", filename);
	    windowMessage (help, -1);
	    fclose (fp);
	    return (0);
        }

        newTimescaling = convdec (maxt / (MAXLONG / 100));
        newVoltscaling = convdec (
			   Max (Abs (minv), Abs (maxv)) / (MAXINT / 100));
    
        if (Append || found) {
    
	    if (newVoltscaling / Voltscaling > 1e4) {
                windowMessage (
	          "New y scale factor / old y scale factor > 1e4", -1);
	        delSigList (Old_end_signal -> orig_next);
	        Old_end_signal -> orig_next = NULL;
	        Old_end_signal -> next = NULL;
		fclose (fp);
	        return (0);
	    }

	    newGlobal_umin = minv / Voltscaling;
	    newGlobal_umax = maxv / Voltscaling;

	    if (newGlobal_umin < Global_umin)
	        Global_umin = newGlobal_umin;
	    if (newGlobal_umax > Global_umax)
	        Global_umax = newGlobal_umax;
        }
        else {
	    Timescaling = newTimescaling;
	    Voltscaling = newVoltscaling;

	    Global_umin = minv / Voltscaling;
	    Global_umax = maxv / Voltscaling;
        }

        fseek (fp, foffset, 0);

	if (spice3 == 1) {
	    /* the first item on the line is an index, 
	       the second item is the time */
	    fscanf (fp, "%*d");
	}

        end = 0;
        while (!end && fscanf (fp, "%le", &t) > 0) {
    
	    if (t / Timescaling * 10 > MAXLONG) {
	        windowMessage (
	          "New x values too large (as compared to old x values)", -1);
	        delSigList (Old_end_signal -> orig_next);
	        Old_end_signal -> orig_next = NULL;
	        Old_end_signal -> next = NULL;
		fclose (fp);
	        return (0);
	    }

	    time = (long) (t / Timescaling);
    
	    if (Append || found) {
	        sig = Old_end_signal -> orig_next;
	    }
	    else {
	        sig = Begin_signal;
	    }
	    for (i = Old_nr_signals; i < Nr_signals; i++) {
    
                if (fscanf (fp, "%le", &v) < 0) {
		    sprintf (help, "Error in reading transient analysis of %s", 
			           filename);
		    windowMessage (help, -1);
		    fclose (fp);
		    return (0);
	        }
    
                if (sig -> end_value_U && sig -> end_value_U -> prev
		&& sig -> end_value_U -> value == (int)(v / Voltscaling)
	        && sig -> end_value_U -> prev -> value 
                                                  == (int)(v / Voltscaling)) {

                    /* save memory space (and execution time) by
                       not storing intermediate values that are 
                       equal to a previous and next value.
                    */

                    sig -> end_value_U -> time = time;

                }
                else {

		    NEW (sval, 1, struct sig_value);
		    sval -> time = time;
		    sval -> next = NULL;
		    sval -> prev = NULL;
		    sval -> value = (int)(v / Voltscaling);
    
		    /* store only in the upper value waveform */
    
		    if (sig -> end_value_U) {
		        sig -> end_value_U -> next = sval;
		        sval -> prev = sig -> end_value_U;
		        sig -> end_value_U = sval;
		    }
		    else {
		        sig -> begin_value_U = 
		        sig -> end_value_U = sval;
	            }
                }
    
	        sig = sig -> orig_next;
	    }
    
	    if (spice3 == 0) {
		while ((c = getc (fp)) != '\n');
		while ((c = getc (fp)) == ' ' || c == '\t');
		if (c < '0' || c > '9') end = 1;
		ungetc (c, fp);
	    }

	    if (spice3 == 1) {
		while ((c = getc (fp)) == ' ' || c == '\t' 
		       || c == '\n' || c == '');

		if (c == 'I' && getc (fp) == 'n' && getc (fp) == 'd'
		    && getc (fp) == 'e' && getc (fp) == 'x') {
		    if (c != EOF) while ((c = getc (fp)) != '\n');
	            if (c != EOF) while ((c = getc (fp)) != '\n');  
						   /* skip '-------  ... ' */
                    if (c != EOF) c = getc (fp);
		}

		if (c >= '0' && c <= '9') {
		    ungetc (c, fp);

		    /* the first item on the line is an index, 
		       the second item is the time */

		    fscanf (fp, "%*d");
		}
		else {
		    end = 1;
		}
	    }
        }

        if (Append || found) {
	    Begintime = Min (Begintime, (long) (mint / Timescaling));
	    Endtime = Max (Endtime, time);
	}
        else {
	    Begintime = (long) (mint / Timescaling);
	    Endtime = time;
	}

        found = 1;
    }

    if (!found) {
        sprintf (help, 
                 "Cannot find transient analysis table in %s", filename);
        windowMessage (help, -1);
	fclose (fp);
        return (0);
    }

    fclose (fp);
    return (1);
}

void delSigList (sig) 
struct signal *sig;
{
    struct signal *oldsig;
    void delSig ();

    while (sig) {
	oldsig = sig;
	sig = sig -> orig_next;

	delSig (oldsig);
    }
}

void delSig (sig)
struct signal *sig;
{
    void delSigval ();
    void delSigexpr ();

    delSigval (sig -> begin_value);
    delSigval (sig -> begin_value_L);
    delSigval (sig -> begin_value_U);
    delSigexpr (sig -> expr);
    DELETE (sig -> name);
    DELETE (sig);

    if (storedSig == sig)
	storedSig = NULL;
}

void delSigval (sigv)
struct sig_value *sigv;
{
    struct sig_value *oldsigv;

    while (sigv) {
	oldsigv = sigv;
	sigv = sigv -> next;

	DELETE (oldsigv);
    }
}

void delSigexpr (sigel)
struct signalelement *sigel;
{
    struct signalelement *oldsigel;

    while (sigel) {
	if (sigel -> child)
	    delSigexpr (sigel -> child);
	oldsigel = sigel;
	sigel = sigel -> sibling;

	DELETE (oldsigel);
    }
}

int addStringValue (str)
char *str;
{
    int i;
    int low, high, mid;
    int v;

    low = -1, high = SV_cnt;  /* open boundaries */
    while (low + 1 < high) {
	mid = (low + high) / 2;
	v = strcmp (SV[svi[mid]], str);
	if (v > 0) {
	    high = mid;
	}
	else if (v < 0) {
	    low = mid;
	}
	else {
	    return (svi[mid]);
	}
    }

    if (SV_cnt == SV_size) {
	if (SV_size == 0) {
	    SV_size = 200;
            NEW (SV, SV_size, char *);
	    NEW (svi, SV_size, int);
	}
	else {
            ENLARGE (SV, SV_size * 2, char *);
	    ENLARGE (svi, SV_size * 2, int);
	    SV_size = SV_size * 2;
	}
    }

    /* insert in list while maintaining alphabetical order */

    for (i = SV_cnt; i > low + 1; i--) {
	svi[i] = svi[i - 1];
    }

    NEW (SV[SV_cnt], strlen (str) + 1, char);
    strcpy (SV[SV_cnt], str);
    svi[low + 1] = SV_cnt++;

    return (svi[low + 1]);
}

resetStringValues ()
{
    int i;

    for (i = 0; i < SV_cnt; i++) {
	DELETE (SV[i]);
    }

    SV_cnt = 0;
}
