static char *SccsId = "@(#)main.c 4.11 (TU-Delft) 04/22/93";
/**********************************************************

Name/Version      : tecc/4.11

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

Author            : A.J. van Genderen
Creation date     : 15-Mar-1988
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) 1988. All rights reserved.
**********************************************************/
#include <stdio.h>
#include <signal.h>
#include <dmincl.h>
#include "define.h"
#include "type.h"
#ifdef ESE
#include "eseOption.h"
#include "tversion.h"
#endif

#ifndef ESE
char *argv0 = "tecc";
char *use_msg = "\nUsage: %s [-sn] [-m maskdatafile] [-p process] file\n\n";
#else
char *argv0 = "techcom";
char *use_msg = "\nUsage: %s [options] file\n\n";
#endif

DM_PROJECT *dmproject = NULL;

int silent;
int docompress;

struct contact cons[MAXCON];
struct transistor tors[MAXTOR];
struct capacitance caps[MAXCAP];
struct resistance ress[MAXRES];
struct vdimension vdms[MAXVDIM];
struct shape shps[MAXSHAPE];

int con_cnt = 0;
int tor_cnt = 0;
int cap_cnt = 0;
int res_cnt = 0;
int vdim_cnt = 0;
int shape_cnt = 0;

DM_PROCDATA *procdata;

int *maskTransf;
int *maskBackTransf;

int conducCnt;
int *conducTransf;
int *conducBackTransf;

int sSlotCnt;
int eSlotCnt;
int oeSlotCnt;

int *sLayerWeight;
int *eLayerWeight;
int *oeLayerWeight;

int nbrLays;

int maxNbrKeys;

struct elemRef **keytab;
int nbrKeySlots;

struct layerRef *keylist;

extern FILE *yyin;

#ifndef ESE
char process[132];
char maskdata[512];
#else
char * process = NULL;
char * maskdata = NULL;
#endif

#ifdef ESE
OptionSpec optionSpecs[] = {
    { "usage", NO, eseHelp, (void *) optionSpecs,
            "-usage:     techcom [options] file\nOptions (may be abbreviated) are:"},
    { "%etext", NO, eseText, (void *) NULL,
            "    -%etext:              print the '(int) & etext' number" },
    { "%help", NO, eseHelpAll, (void *) optionSpecs,
            "    -%help:               print this list" },
    { "release", NO, esePrintString, (void *) TOOLVERSION,
            "    -release:             print the release number of this tool"},
    { "help", NO, eseHelp, (void *) optionSpecs,
            "    -help:                print this list" },
    { "silent", NO, eseTurnOn, (void *) & silent,
            "    -silent:              silent mode" },
    { "process", YES, eseAssignArgument, (void *) & process,
            "    -process  process:    specifies process to be used instead of default" },
    { "nocompress", NO, eseTurnOff, (void *) & docompress,
            "    -nocompress:          do not compress element definition file" },
    { "%maskdata", YES, eseAssignArgument, (void *) & maskdata,
            "    -%maskdata  maskfile: Use the maskdata found in 'maskfile'" },
/*
    { "verbose", NO, eseTurnOff, (void *) & silent,
            "    -verbose:             print run-time information" },
*/
    { (char *) 0, (char) 0, (IFP) 0, (void *) 0, (char *) 0 },
};
#endif


main (argc, argv)
int argc;
char *argv[];
{
    char *s;
    int i;
    int l;
    char *techfile = NULL;
    char *outfile;
    char str[80];
    int id;
    int proc_id;
    char proclist[80];
    FILE *fp_proclist;
    int hidden = 0;

    silent = 0;
    docompress = 1;
#ifndef ESE
    process[0] = '\0';
    maskdata[0] = '\0';

    while (--argc > 0) {
        if ((*++argv)[0] == '-' ) {
	    for (s = *argv + 1; *s != '\0'; s++) {
	        switch (*s) {
		    case 'm':
			if (sscanf (*++argv, "%s", maskdata) != 1) {
			    fprintf (stderr, use_msg, argv0);
			    exit (1);
			};
			argc--;
			*(s+1) = '\0';
			break;
		    case 'p':
			if (sscanf (*++argv, "%s", process) != 1) {
			    fprintf (stderr, use_msg, argv0);
			    exit (1);
			};
			argc--;
			*(s+1) = '\0';
			break;
		    case 's':
			silent = 1;
			break;
		    case '%':
			hidden = 1;
			break;
		    case 'n':
			/*
			if (hidden)
			*/
			    docompress = 0;
			/*
			else {
			    fprintf (stderr, 
				     "%s: illegal option: %c\n", argv0, *s);
			    exit (1);
			}
			*/
			break;
		    default:
		        fprintf (stderr, 
				 "%s: illegal option: %c\n", argv0, *s);
		        exit (1);
	        }
	    }
	}
	else {
            if (techfile == NULL) {
		techfile = *argv;
	    }
	    else {
		fprintf (stderr, use_msg, argv0);
		exit (1);
	    }
	}
    }

#else
    if (eseOptionHandler (argc, argv, optionSpecs, 1, &techfile) != 0) {
	fprintf (stderr, use_msg, argv0);
	exit (1);
    }
#endif
    if (techfile == NULL) {
	fprintf (stderr, use_msg, argv0);
	exit (1);
    }
    else {
	l = strlen (techfile);
	if (l < 2 || techfile[l-1] != 's' || techfile [l-2] != '.') {
	    fprintf (stderr, "%s: illegal name for inputfile\n", argv0);
	    exit (1);
	}
    }

    dmInit (argv0);

    if (process && process[0]) {

	sprintf (proclist, "%s/lib/process/processlist", icdpath);
	if ((fp_proclist = fopen (proclist, "r")) == NULL) {
	    fprintf (stderr, "%s: cannot open %s\n", argv0, proclist);
	    exit (1);
	}

        proc_id = -1;
        while (proc_id < 0 && fscanf (fp_proclist, "%s", str) > 0) {

	    if (str[0] != '#') {
		id = -1;
		id = atoi (str);
		fscanf (fp_proclist, "%s", str);
		if (strcmp (str, process) == 0) {
		    proc_id = id;
		}
	    }

	    while (getc (fp_proclist) != '\n');
	}

	fclose (fp_proclist);

	if ((procdata = (DM_PROCDATA *)_dmDoGetProcess (proc_id)) == NULL)
	    exit (1);
    }
    else if (maskdata && maskdata[0]) {
	if ((procdata = (DM_PROCDATA *)_dmDoGetProcessFile (maskdata)) == NULL)
	    exit (1);
    }
    else {

	dmproject = dmOpenProject (DEFAULT_PROJECT, PROJ_READ);

	initIntrup ();

	procdata = (DM_PROCDATA *)dmGetMetaDesignData (PROCESS, dmproject);
    }

    ALLOC (maskTransf, procdata -> nomasks, int);
    for (i = 0; i < procdata -> nomasks; i++) {
	maskTransf[i] = i;
    }
    ALLOC (maskBackTransf, procdata -> nomasks, int);
    for (i = 0; i < procdata -> nomasks; i++) {
	maskBackTransf[i] = i;
    }

    OPENR (yyin, techfile);

    yyparse ();

    CLOSE (yyin);

    if (maxNbrKeys > 0)
	selectKeys ();

    changeMasks ();

    /* addDef (); */

    checkConnections ();

    mkCapBitmasks ();

    ALLOC (keytab, nbrKeySlots, struct elemRef *);

    mkKeys ();

    rmRedCond ();

    rmRedElem ();

    findConducTransf ();

    outfile = techfile;
    outfile[ strlen (techfile)  - 1 ] = 't';

    prTabs (outfile);

    if (! process || ! process[0]) {
	if (dmproject) dmCloseProject (dmproject, COMPLETE);
    }

    dmQuit ();

    return (0);
}

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
    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
        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, QUIT);
    dmQuit ();
    exit (1);
}
