static char *SccsId = "@(#)main_pp.c 3.3 (TU-Delft) 06/25/90";
/**********************************************************

Name/Version      : nspice/3.3

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

Author(s)         : A.J. van Genderen
Creation date     : 8-June-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 "define.h"
#include "type.h"
#include "extern.h"

char *argv0 = "nspice_pp";
char *Usg_msg = "\nUsage: %s cell commandfile\n\n";

struct signal *Begin_signal = NULL;
struct signal *End_signal = NULL;
int Nr_signals;

long Endtime;
double Timescaling;
double outaccur;

struct node_ref *Begin_print = NULL;
struct node_ref *End_print = NULL;

char * cellname;
char * commandfile;

extern int simlevel;

main (argc, argv)
int argc;
char **argv;
{
    char *s;

    cellname = NULL;
    commandfile = NULL;

    while (--argc > 0) {
        if ( (*++argv)[0] == '-' ) {
	    for (s = *argv + 1; *s != '\0'; s++) {
	        switch (*s) {

		    default: 
		        fprintf (stderr, 
				 "%s: illegal option: %c\n", argv0, *s);
			fprintf (stderr, Usg_msg, argv0); 
		        exit (1);
	        }
	    }
	}
	else if (cellname == NULL) {
	    cellname = *argv;
	}
	else if (commandfile == NULL) {
	    commandfile = *argv;
	}
	else {
	    fprintf (stderr, Usg_msg, argv0); 
	    exit (1);
	}
    }

    if (commandfile == NULL) {
	fprintf (stderr, Usg_msg, argv0); 
	exit (1);
    }

    readCom (commandfile);

    readCir (cellname);

    writeSpiceCom ();

    return (0);
}

writeSpiceCom ()
{
    int prevvalue;
    struct signal *sig;
    struct sig_value *sval;
    struct node_ref *pr;
    double t;
    double prevt;
    double trise = -1.0;
    double tfall = -1.0;
    double tstep = -1.0;
    double tstart = -1.0;
    double vhigh = 5.0;    /* default */
    double vlow = 0.0;     /* default */
    double ttran;
    int linenr = 1;
    int error = 0;
    int uic = 0;
    char c;
    int i;
    char buf[128];
    char keyw[128];
    char name[128];
    char help[128];
    int fs_warning = 0;
    int value;
    int match;
    struct node_ref *tab;
    FILE *fp;
    int readDouble ();

    fp = fopen (commandfile, "r");

    if (fp) {

	c = getc (fp);
        match = 0;
	while (!match && c != EOF) {         /* c is first character on line */
            if (c == '*' && (c = getc (fp)) == '%')
                match = 1;
	    while (c != '\n' && c != EOF)
		c = getc (fp);
	    linenr++;
	    if (c != EOF)
		c = getc (fp);
	}

        match = 0;
	while (!match && c != EOF) {         /* c is first character on line */
            if (c == '*' && (c = getc (fp)) == '%') {
                match = 1;
                while ((c = getc (fp)) != '\n' && c != EOF);
            }
            else {
	        while (c == ' ' || c == '\t')
	            c = getc (fp);
	        while (c != '\n' && c != EOF) {
		    ungetc (c, fp);
		    fscanf (fp, "%s", keyw);
		    if (strcmp (keyw, "trise") == 0) {
		        if (readDouble (fp, &trise) != 1) 
			    error = 1;
		    }
		    else if (strcmp (keyw, "tfall") == 0) {
		        if (readDouble (fp, &tfall) != 1) 
			    error = 1;
		    }
		    else if (strcmp (keyw, "tstep") == 0) {
		        if (readDouble (fp, &tstep) != 1) 
			    error = 1;
		    }
		    else if (strcmp (keyw, "tstart") == 0) {
		        if (readDouble (fp, &tstart) != 1) 
			    error = 1;
		    }
		    else if (strcmp (keyw, "vhigh") == 0) {
		        if (readDouble (fp, &vhigh) != 1) 
			    error = 1;
		    }
		    else if (strcmp (keyw, "vlow") == 0) {
		        if (readDouble (fp, &vlow) != 1) 
			    error = 1;
		    }
		    else if (strcmp (keyw, "uic") == 0) {
		        uic = 1;
		    }
		    else {
		        error = 1;
		    }
		    if (error) {
		        sprintf (buf, 
		        "%s, line %d: error in reading spice info", 
		        commandfile, linenr); 
		        message (buf);
		        exit (1);
		    }
		    while ((c = getc (fp)) == ' ' || c == '\t');
                }
	    }
	    if (c != EOF)
		c = getc (fp);
	    linenr++;
	}
    }

    if (tstep <= 0 && simlevel == 3) {
	message ("must specify tstep in %s", commandfile);
	exit (1);
    }

    sig = Begin_signal;
    while (sig) {

	if (sig -> nodenr == 0) {
	    sig = sig -> next;
	    continue;
	}

	fprintf (stdout, "v%s ", sig -> name);
	fprintf (stdout, "%d 0 ", sig -> nodenr);

	fprintf (stdout, "pwl (");

        prevt = 0.0;
	sval = sig -> begin_value;
	while (sval) {

            if (sval -> value < 0) {
		value = 1;

		if (!fs_warning) {
		    sprintf (help, "%le", vlow + vhigh / 2);

		    message 
		    ("Using free state -> %s Volts", help);
		    fs_warning = 1;
		}
	    }
	    else {
		value = sval -> value;
	    }

	    if (sval != sig -> begin_value) {

                ttran = -1.0;
		if (sval -> value == 0 && tfall > 0)
		    ttran = tfall;
		else if (sval -> value == 2 && trise > 0)
		    ttran = trise;

		if (ttran <= 0.0) {
		    ttran = tstep;
		    /* ttran = sval -> time * Timescaling * 0.00002; */
		}

		t = (sval -> time) * Timescaling - ttran / 2;
                if (t <= prevt * 1.000000001) {
                    sprintf (help, "signal \"%s\" at t=%le: %s %s",
                    sig -> name,
                    sval -> time * Timescaling, 
                    "next transition not after stabilization of previous one;",
                    "reduce trise and/or tfall !");
                    message (help);
                    exit (1);
                }
		fprintf (stdout, "\n+     %le %le", t,
			 vlow + prevvalue * vhigh / 2);

	        t = (sval -> time) * Timescaling + ttran / 2,
	        fprintf (stdout, " %le %le", t,
			 vlow + value * vhigh / 2);
	    }
	    else {
                t = (sval -> time) * Timescaling,
		fprintf (stdout, "%le %le", t, vlow + value * vhigh / 2);
	    }

            prevvalue = value;
            prevt = t;
	    sval = sval -> next;
	}

	fprintf (stdout, ")\n");

	sig = sig -> next;
    }

    if (Begin_print && simlevel == 3) {

	fprintf (stdout, ".print tran");

        i = 1;
	pr = Begin_print;
	while (pr) {

	    if (pr -> nodenr == 0) {
		pr = pr -> next;
		continue;
	    }

	    if (i != 1 && (i - 1) % 8 == 0)
		fprintf (stdout, "\n.print tran");

	    fprintf (stdout, " v(%d)", pr -> nodenr);

	    pr = pr -> next;
	    i++;
	}

	fprintf (stdout, "\n");
    }

    if (fp && match) {

        match = 0;
	while (!match && c != EOF) {  

	    if (c == '"') {
		if (fscanf (fp, "%s", name) != 1) {
		    sprintf (buf, 
		    "%s, line %d: error in reading spice info", 
		    commandfile, linenr); 
		    message (buf);
		    exit (1);
		}
		for (i = 0; name[i] != '\0' && name[i] != '"'; i++);
		if (name[i] == '"') {
		    name[i] = '\0';
		}
		else {
		    sprintf (buf, 
		    "%s, line %d: error in reading spice info", 
		    commandfile, linenr); 
		    message (buf);
		    exit (1);
		}

                tab = Begin_table;
		while (tab && strcmp (tab -> name, name) != 0) {
		    tab = tab -> next;
		}

                if (tab)
		    fprintf (stdout, "%d", tab -> nodenr);
		else {
		    sprintf (buf, 
		    "file %s, line %d: no node with name %s", 
		    commandfile, linenr, name); 
		    message (buf);
		    exit (1);
		}

		fprintf (stdout, "%s", &name[i+1]);

	        c = getc (fp);
	    }
	    else if (c == '\n') {
                linenr++;
		putc (c, stdout);
                if ((c = getc (fp)) == '*') {
                    if ((c = getc (fp)) == '%')
                        match = 1;
                    else {
		        putc ('*', stdout);
                    }
                }
            }
	    else {
		putc (c, stdout);

	        c = getc (fp);
	    }
	}

	if (!match) {
	    message ("file %s: missing *%%", commandfile);
	    exit (1);
	}

	fclose (fp);
    }


    if (simlevel == 3) {
	fprintf (stdout, ".tran %le %le", tstep, Endtime * Timescaling);
	if (tstart > 0) {
	    fprintf (stdout, " %le", tstart);
	}
	if (uic) {
	    fprintf (stdout, " uic");
	}
	fprintf (stdout, "\n");
    }

    fprintf (stdout, ".end\n");
}

int readDouble (fp, var)
FILE *fp;
double *var;
{
    char c;

    if (fscanf (fp, "%le", var) != 1)
	return (0);
    
    c = getc (fp);
    switch (c) {
	case 'T':
	    *var = *var * 1e12;
	    break;
	case 'G':
	    *var = *var * 1e9;
	    break;
	case 'M':
	    *var = *var * 1e6;
	    break;
	case 'k':
	    *var = *var * 1e3;
	    break;
	case 'm':
	    *var = *var * 1e-3;
	    break;
	case 'u':
	    *var = *var * 1e-6;
	    break;
	case 'n':
	    *var = *var * 1e-9;
	    break;
	case 'p':
	    *var = *var * 1e-12;
	    break;
	case 'f':
	    *var = *var * 1e-15;
	    break;
	default:
	    if (c != EOF)
		ungetc (c, fp);
    }

    return (1);
}

message (s, a1, a2, a3, a4, a5)
char *s;
char *a1, *a2, *a3, *a4, *a5;
{
    fprintf (stderr, "%s: ", argv0);
    fprintf (stderr, s, a1, a2, a3, a4, a5);
    fprintf (stderr, "\n");
}
