static char *SccsId = "@(#)main.c 4.8 (TU-Delft) 02/10/92";
/**********************************************************

Name/Version      : putdevmod/4.8

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

Author(s)         : A.J. van Genderen
Creation date     : 6-Sep-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 <signal.h>
#include <stdio.h>
#include <dmincl.h>
#ifdef ESE
#include "eseOption.h"
#include "tversion.h"
#endif

char *argv0 = "putdevmod";
char *use_msg = "\nUsage: %s [-e] file\n\n";

DM_PROJECT *dmproject = NULL;
char *infile;
int lineno;
int spicemod;

#ifdef ESE
OptionSpec optionSpecs[] = {
    { "usage", NO, eseHelp, (void *) optionSpecs,
            "usage:        putdevmod [options] file\nOptions (may be abbreviated) are:"},
    { "help", NO, eseHelp, (void *) optionSpecs,
            "    -help:         print this list" },
    { "release", NO, esePrintString, (void *) TOOLVERSION,
            "    -release:      print the release number of this tool"},
    { "%etext", NO, eseText, (void *) NULL,
            "    -%etext:       print the '(int) & etext' number" },
    { "%help", NO, eseHelpAll, (void *) optionSpecs,
            "    -%help:        print this list" },
    { (char *) 0, (char) 0, (IFP) 0, (void *) 0, (char *) 0 },
};
#endif

int optMkEquiv = 0;


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

#ifndef ESE
    while (--argc > 0) {
        if ((*++argv)[0] == '-' ) {
	    for (s = *argv + 1; *s != '\0'; s++) {
	        switch (*s) {
		    case 'e':
			optMkEquiv = 1;
			break;
		    default: 
		        fprintf (stderr, 
				 "%s: illegal option: %c\n", argv0, *s);
		        exit (1);
	        }
	    }
	}
	else {
            if (infile == NULL) {
		infile = *argv;
	    }
	    else {
		fprintf (stderr, use_msg, argv0);
		exit (1);
	    }
	}
    }
    if (infile == NULL) {
	fprintf (stderr, use_msg, argv0);
	exit (1);
    }
#else
    if (eseOptionHandler (argc, argv, optionSpecs, 1, &infile) > 0 ||
            infile == NULL) {
	fprintf (stderr, use_msg, argv0);
	exit (1);
    }
#endif

    dmInit (argv0);
    dmproject = dmOpenProject (DEFAULT_PROJECT, DEFAULT_MODE);

    initIntrup ();

    parseDesc ();

    if (dmproject) dmCloseProject (dmproject, COMPLETE);
    dmQuit ();

    return (0);
}

parseDesc ()
{
    char devname[80];
    char terminals[40][80];   /* maximum 40 terminals of size 79 */
    int term_cnt;
    char c;
    FILE *fpin;
    char keyword[81];
    char buf[81];
    int i;

    DM_STREAM *dsp_term;
    DM_STREAM *dsp_devmod;
    DM_STREAM *dsp;

    DM_CELL *dmkey;

    if ((fpin = fopen (infile, "r")) == NULL) {
        fatalErr ("Cannot open", infile);
    }

    lineno = 1;

    if (getword (fpin, keyword, 0, 0) > 0 && strcmp (keyword, "device") == 0) {
	if (getword (fpin, devname, 1, 0) <= 0) {
	    sprintf (buf, "%d", lineno);
	    fatalErr ("syntax error at line", buf);
	}
    }
    else {
	sprintf (buf, "%d", lineno);
	fatalErr ("syntax error at line", buf);
    }

    spicemod = 0;

    while (getword (fpin, keyword, 0, 1) > 0) {

	if (strcmp (keyword, "begin") == 0) {

	    if (getword (fpin, keyword, 1, 0) > 0) {
		if (strcmp (keyword, "spicemod") == 0) {
		    spicemod = 1;
		}
		else {
		    fatalErr ("unknown simulation model:", keyword);
		}
	    }
	    else {
		sprintf (buf, "%d", lineno);
		fatalErr ("syntax error at line", buf);
	    }
	}
        else if (strcmp (keyword, "terminals") == 0 && spicemod) {

	    term_cnt = 0;
            while (getword (fpin, terminals[term_cnt], 1, 0) > 0) {
                term_cnt++;
	    }
        }
	else if (strcmp (keyword, "end") == 0 && spicemod) {
	    spicemod = 0;
	}
	else if (!spicemod) {
	    sprintf (buf, "%d", lineno);
	    fatalErr ("syntax error at line", buf);
	}
    }

    dmkey = dmCheckOut (dmproject, devname, WORKING, 
				DONTCARE, CIRCUIT, UPDATE);

    /* write terminals */

    dsp_term = dmOpenStream (dmkey, "term", "w");

    i = 0;
    while (i < term_cnt) {
        sprintf (cterm.term_name, "%s", terminals[i]);
        cterm.term_dim = 0;
        dmPutDesignData (dsp_term, CIR_TERM);
        i++;
    }

    dmCloseStream (dsp_term, COMPLETE);


    /* copy full contents of inputfile to devmod */

    dsp_devmod = dmOpenStream (dmkey, "devmod", "w");

    rewind (fpin);

    while ((c = getc (fpin)) != EOF)
        putc (c, dsp_devmod -> dmfp);

    dmCloseStream (dsp_devmod, COMPLETE);


    /* clear mc and net streams */

    dsp = dmOpenStream (dmkey, "mc", "w");
    dmCloseStream (dsp, COMPLETE);

    dsp = dmOpenStream (dmkey, "net", "w");
    dmCloseStream (dsp, COMPLETE);

    dmCheckIn (dmkey, COMPLETE);

    if (optMkEquiv) {

	/* first, check out the layout cell to make it known to the database */

	dmkey = dmCheckOut (dmproject, devname, WORKING, 
				    DONTCARE, LAYOUT, READONLY);
        dmCheckIn (dmkey, COMPLETE);

	dmPutMetaDesignData (CELLEQUIVALENCE, dmproject, 
			     devname, LAYOUT,
			     devname, CIRCUIT);
    }
}

int getword (fp, buf, onSameLine, onNewLine)
FILE *fp;
char *buf;
int onSameLine;
int onNewLine;
{
    char c;

    if (onNewLine) {
        while ((c = getc (fp)) != '\n' && c != EOF);
	if (c == '\n')
	    lineno++;
    }

    if (c != EOF)
	c = getc (fp);

    while (c != EOF) {
	while (c == ' ' || c == '\t')
	    c = getc (fp);
	if (c == '\n') {
	    if (onSameLine) {
	        ungetc (c, fp);
		return (0);
	    }
	    else {
	        c = getc (fp);
	        lineno++;
	    }
	}
	else if (spicemod && c == '*') {
	    c = getc (fp);                 /* skip comment */
	}
	else {
	    ungetc (c, fp);
	    fscanf (fp, "%s", buf);
	    return (1);
	}
    }

    return (-1);
}

fatalErr (s1, s2) 
char *s1, *s2;
{
    fprintf (stderr, "%s: ", argv0);

    if (s1 && *s1 != '\0') {
	fprintf (stderr, "%s", s1);
    }

    if (s2 && *s2 != '\0') {
	fprintf (stderr, " %s", s2);
    }

    fprintf (stderr, "\n");

    die ();
}

initIntrup ()
{
    int int_hdl ();

    if (signal (SIGINT, SIG_IGN) != SIG_IGN)   
        signal (SIGINT, int_hdl);
        /* only when value was not SIG_IGN, a jump must be done to int_hdl */
    if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
        signal (SIGQUIT, int_hdl);
        /* only when value was not SIG_IGN, a jump must be done to int_hdl */
    signal (SIGTERM, int_hdl);
    signal (SIGILL, int_hdl);
    signal (SIGFPE, int_hdl);
#ifdef SIGBUS /* [ps] */
    signal (SIGBUS, int_hdl);
#endif
    signal (SIGSEGV, int_hdl);
}

int_hdl (sig)   /* interrupt handler */
int sig;
{
    switch (sig) {
        case SIGILL :
            fprintf (stderr, "Illegal instruction\n");
            break;
        case SIGFPE :
            fprintf (stderr, "Floating point exception\n");
            break;
#ifdef SIGBUS /* [ps] */
        case SIGBUS :
            fprintf (stderr, "Bus error\n");
            break;
#endif
        case SIGSEGV :
            fprintf (stderr, "Segmentation violation\n");
            break;
        default :
            break;
    }

    die ();
}

dmError (s)
char *s;
{
    dmPerror (s);
    die ();
}

die () 
{
    if (dmproject) dmCloseProject (dmproject, COMPLETE);
    dmQuit ();
    exit (1);
}
