static char *SccsId = "@(#)main.c 3.25 (TU-Delft) 03/26/91";
/**********************************************************

Name/Version      : dbcat/3.25

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

Author(s)         : S. de Graaf
Creation date     : 24-Oct-1986
Modified by       : S. de Graaf, Paul Stravers [ps]
Modification date : 02-Jul-1987
Modification date : 22-Apr-1988
Modification date : 19-May-1988
Modification date : 22-Nov-1988
Modification date : 19-Jun-1990
Modification date : 22-Mar-1993 [ps]


        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) 1987-1988, All rights reserved
**********************************************************/
#include "stdio.h"
#include "malloc.h"
#include "signal.h"
#include "dmincl.h"
#ifdef ESE
#include "eseOption.h"
#include "tversion.h"
#endif

#ifdef MSDOS
#define SCAN fscanf(fp->dmfp,
#else
#define SCAN dmScanf(fp,
#endif
#ifdef PACK
#define _dmDoget _dmUnpack
#endif

#define PE fprintf(stderr,
#define Lay(no) process->mask_name[no]

DM_PROJECT *project;
DM_CELL    *key;
DM_STREAM  *fp;
DM_PROCDATA *process;
char    *cell;
char ** viewlist = NULL;
char    *view = "layout";
char     strbuf[40];
char    *n_mode = 0;
int      v_mode;
char *s_mode = 0;
int  a_mode = 0;
int  c_mode = 0;
int  l_mode = 1;
int  f_mode = 0;

#ifndef ESE
char *argv0 = "dbcat";		/* program name */
char *use_msg =			/* command line */
"\nUsage: %s [-av] [-c|-f] [-s dbstream] [-n name] [cell ...]\n\n";
#else
char *argv0 = "catcell";		/* program name */
char *use_msg =			/* command line */
"\nUsage: %s [options] [cell ...]\n\n";
#endif

#ifdef ESE
OptionSpec optionSpecs[] = {
    { "usage", NO, eseHelp, (void *) optionSpecs,
            "-usage:     catcell [options] [cell ...]\nOptions (may be abbreviated) are:"},
    { "%etext", NO, eseText, (void *) NULL,
            "    -%etext:         print the '(int) & etext' number" },
    { "release", NO, esePrintString, (void *) TOOLVERSION,
            "    -release:        print the release number of this tool"},
    { "%help", NO, eseHelpAll, (void *) optionSpecs,
            "    -%help:          print this list" },
    { "help", NO, eseHelp, (void *) optionSpecs,
            "    -help:           print this list" },
    { "verbose", NO, eseTurnOn, (void *) & v_mode,
            "    -verbose:        print run-time information" },
    { "all", NO, eseTurnOn, (void *) & a_mode,
            "    -all:            list stream data of all cells of specified viewtype" },
    { "%circuit", NO, eseTurnOn, (void *) & c_mode,
            "    -%circuit:       list only data in circuit view"  },
    { "%layout", NO, eseTurnOn, (void *) & l_mode,
            "    -%layout:        list only data in layout view (default)"  },
    { "view", YES, eseListArguments, (void *) & viewlist,
            "    -view viewtype:  list only data of cells of (only one) viewtype" },
    { "stream", YES, eseAssignArgument, (void *) & s_mode,
            "    -stream astream: list only data of streams named 'astream'" },
    { "name", YES, eseAssignArgument, (void *) & n_mode,
            "    -name aname:     list only data items named 'aname'" },
    { (char *) 0, (char) 0, (IFP) 0, (void *) 0, (char *) 0 },
};
#endif

main (argc, argv)
int   argc;
char *argv[];
{
    int  sig_handler ();
    register int i, j, iarg;
    register char **ml;
    int  usage = 0;
#ifndef ESE
    for (iarg = 1; iarg < argc && argv[iarg][0] == '-'; ++iarg) {
	j = iarg;
	for (i = 1; argv[j][i] != '\0'; ++i) {
	    switch (argv[j][i]) {
		case 'a': 
		    ++a_mode;
		    PE "%s: -a: list all cells\n", argv0);
		    break;

		case 'v': 
		    ++v_mode;
		    PE "%s: -v: verbose mode\n", argv0);
		    break;

		case 'c': 
		    ++c_mode;
		    f_mode = 0;
		    PE "%s: -c: list only circuit data\n", argv0);
		    break;

		case 'f': 
		    ++f_mode;
		    c_mode = 0;
		    PE "%s: -f: list only floorplan data\n", argv0);
		    break;

		case 's': 
		    s_mode = argv[++iarg];
		    PE "%s: -s: read only dbstream: %s\n",
			argv0, s_mode);
		    break;

		case 'n': 
		    n_mode = argv[++iarg];
		    PE "%s: -n: list only name: %s\n",
			argv0, n_mode);
		    break;

		default: 
		    ++usage;
		    PE "%s: -%c: unknown option\n",
			argv0, argv[j][i]);
	    }
	}
    }

    if (a_mode) --iarg;

    if (argc <= iarg) {
	PE "%s: no cell name given\n", argv0);
	++usage;
    }
#else
    ml = (char **) calloc (argc, sizeof (char *));
    usage = eseOptionHandler (argc, argv, optionSpecs, argc, ml);

    if ((!ml[0] && !a_mode) || (ml[0] && a_mode)) {
	PE "You must specify either -all or cell ...\n");
	usage++;
    }

    if (!viewlist) {
	PE "You must specify at least one viewtype with the '-view' option.\n");
	usage++;
    }
    else if (viewlist[0]  && viewlist[1]) {
	PE "-view: specify atmost one view");
        usage++;
    }
    else if (viewlist[0][0] == 'l') {
	l_mode = 1;
        c_mode = 0;
    }
    else if (viewlist[0][0] == 'c') {
        c_mode = 1;
        l_mode = 0;
    }
    else {
	PE "-view: '%s' does not exist", viewlist[0]);
        usage++;
    }
#endif

    if (usage) {
	PE use_msg, argv0);
	exit (1);
    }

#ifndef MSDOS
    signal (SIGHUP , SIG_IGN); /* ignore hangup signal */
    signal (SIGQUIT, SIG_IGN);
    signal (SIGTERM, sig_handler);
#endif

    if (signal (SIGINT, SIG_IGN) != SIG_IGN)
	signal (SIGINT, sig_handler);

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

    if (!c_mode)
	process = (DM_PROCDATA *) dmGetMetaDesignData (PROCESS, project);

    if (c_mode) view = "circuit";
    else if (f_mode) view = "floorplan";
    else view = "layout";

    if (a_mode) {
	if (c_mode)
	    ml = (char **) dmGetMetaDesignData (CELLLIST, project, CIRCUIT);
	else if (f_mode)
	    ml = (char **) dmGetMetaDesignData (CELLLIST, project, FLOORPLAN);
	else
	    ml = (char **) dmGetMetaDesignData (CELLLIST, project, LAYOUT);
    }
#ifndef ESE
    else
	ml = &argv[iarg];
#endif

    while (cell = *ml++) {
	if (c_mode)
	    key = dmCheckOut (project, cell, WORKING, DONTCARE, CIRCUIT, READONLY);
	else if (f_mode)
	    key = dmCheckOut (project, cell, WORKING, DONTCARE, FLOORPLAN, READONLY);
	else
	    key = dmCheckOut (project, cell, WORKING, DONTCARE, LAYOUT, READONLY);

	if (s_mode) {
	    if (c_mode) {
		if (strcmp (s_mode, "info") == 0)
		    readc_info ("info");
		else if (strcmp (s_mode, "mc") == 0)
		    readc_mc ("mc");
		else if (strcmp (s_mode, "term") == 0)
		    readc_term ("term");
		else if (strcmp (s_mode, "net") == 0)
		    readc_net ("net");
		else
		    error (2, s_mode);
	    }
	    else if (f_mode) {
		if (strcmp (s_mode, "mc") == 0)
		    readf_mc ("mc");
		else if (strcmp (s_mode, "info") == 0)
		    readf_info ("info");
		else if (strcmp (s_mode, "term") == 0)
		    readf_term ("term");
		else if (strcmp (s_mode, "chan") == 0)
		    readf_chan ("chan");
		else
		    error (2, s_mode);
	    }
	    else {
	    if (strcmp (s_mode, "info") == 0)
		read_info ("info");
	    else if (strcmp (s_mode, "info3") == 0)
		read_info3 ("info3");
	    else if (strcmp (s_mode, "info2") == 0)
		read_info2 ("info2");
	    else if (strcmp (s_mode, "mc") == 0)
		read_mc ("mc");
	    else if (strcmp (s_mode, "box") == 0)
		read_box ("box");
	    else if (strcmp (s_mode, "term") == 0)
		read_term ("term");
	    else if (strcmp (s_mode, "nor") == 0)
		read_nor ("nor");
	    else if ((i = strend (s_mode, "bxx")) >= 0) {
		if (i == 0) {
		    for (i = 0; i < process -> nomasks; ++i) {
			sprintf (strbuf, "%s_bxx", Lay (i));
			read_bxx (strbuf);
			if (process -> mask_type[i] == DM_INTCON_MASK) {
			    sprintf (strbuf, "t_%s_bxx", Lay (i));
			    read_bxx (strbuf);
			}
		    }
		}
		else
		    read_bxx (s_mode);
	    }
	    else if ((i = strend (s_mode, "nxx")) >= 0) {
		if (i == 0) {
		    for (i = 0; i < process -> nomasks; ++i) {
			sprintf (strbuf, "%s_nxx", Lay (i));
			read_nxx (strbuf);
		    }
		}
		else
		    read_nxx (s_mode);
	    }
	    else if ((i = strend (s_mode, "gln")) >= 0) {
		if (i == 0) {
		    for (i = 0; i < process -> nomasks; ++i) {
			sprintf (strbuf, "%s_gln", Lay (i));
			read_gln (strbuf);
		    }
		}
		else
		    read_gln (s_mode);
	    }
	    else if ((i = strend (s_mode, "pgt")) >= 0) {
		if (i == 0) {
		    for (i = 0; i < process -> nomasks; ++i) {
			if (process -> pgt_no[i] <= 0) continue;
			sprintf (strbuf, "%s_pgt", Lay (i));
			read_pgt (strbuf);
		    }
		}
		else
		    read_pgt (s_mode);
	    }
	    else if ((i = strend (s_mode, "pgt_neg")) >= 0) {
		if (i == 0) {
		    for (i = 0; i < process -> nomasks; ++i) {
			if (process -> pgt_no[i] <= 0) continue;
			sprintf (strbuf, "%s_pgt_neg", Lay (i));
			read_pgt (strbuf);
		    }
		}
		else
		    read_pgt (s_mode);
	    }
	    else if ((i = strend (s_mode, "vln")) >= 0) {
		if (i == 0) {
		    for (i = 0; i < process -> nomasks; ++i) {
			sprintf (strbuf, "%s_vln", Lay (i));
			read_vln (strbuf);
			if (process -> mask_type[i] == DM_INTCON_MASK) {
			    sprintf (strbuf, "t_%s_vln", Lay (i));
			    read_vln (strbuf);
			}
		    }
		}
		else
		    read_vln (s_mode);
	    }
	    else if (strcmp (s_mode, "teq") == 0)
		read_teq ("teq");
	    else if (strcmp (s_mode, "tid") == 0)
		read_tid ("tid");
	    else if (strcmp (s_mode, "spec") == 0)
		read_spec ("spec");
	    else if (strcmp (s_mode, "flashes") == 0)
		read_flashes ("flashes");
	    else
		error (2, s_mode);
	    }
	}
	else {
	    if (c_mode) {
		readc_mc ("mc");
		readc_term ("term");
		readc_net ("net");
	    }
	    else if (f_mode) {
		readf_mc ("mc");
		readf_info ("info");
		readf_term ("term");
		readf_chan ("chan");
	    }
	    else {
		read_info ("info");
		read_info3 ("info3");
		read_info2 ("info2");
		read_mc ("mc");
		read_box ("box");
		read_term ("term");
		read_nor ("nor");
	    }
	}
	dmCheckIn (key, COMPLETE);
    }

    dmQuit ();
    exit (0);
}

int
strend (s1, s2)
char *s1, *s2;
{
    int i;
    if ((i = strlen (s1) - strlen (s2)) >= 0)
	if (strcmp (s1 + i, s2) == 0) return (i);
    return (-1);
}

/* modified to read ALL info records, not just the first three... [ps] */
read_info (file)
char *file;
{
    int result;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode)
	printf ("cell/call/elmt  bxl,bxr,byb,byt:\n");
    while ((result = dmGetDesignData (fp, GEO_INFO)) > 0)
    {
       printf ("%5ld %5ld %5ld %5ld\n",
	       ginfo.bxl, ginfo.bxr, ginfo.byb, ginfo.byt);
    }
    dmCloseStream (fp, QUIT);
    if (result < 0 )
    {
       fprintf(stderr,"I experience some trouble reading the info stream\n");
       return;
    }
}

read_info2 (file)
char *file;
{
    int ft = 0;
    register int i, j;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    for (j = i = 0; i < process -> nomasks; ++i) {
	if (dmGetDesignData (fp, GEO_INFO2) == 0) {
	    if (i) printf ("%s: premature eof\n", argv0);
	    break;
	}
	++j;
	if (ft) { ft = 0;
	    printf ("#boxes: #groups:  (lay:)\n");
	}
	printf ("%7ld %8ld", ginfo2.nr_boxes, ginfo2.nr_groups);
	if (v_mode)
	    printf ("  (%s)\n", Lay (i));
	else
	    printf ("\n");
    }
    for (i = 0; i < process -> nomasks; ++i) {
	if (process -> mask_type[i] != DM_INTCON_MASK) continue;
	if (dmGetDesignData (fp, GEO_INFO2) == 0) {
	    if (j) printf ("%s: premature eof\n", argv0);
	    break;
	}
	printf ("%7ld %8ld", ginfo2.nr_boxes, ginfo2.nr_groups);
	if (v_mode)
	    printf ("  (t_%s)\n", Lay (i));
	else
	    printf ("\n");
    }
    dmCloseStream (fp, QUIT);
}

read_info3 (file)
char *file;
{
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (dmGetDesignData (fp, GEO_INFO3) > 0) {
	if (v_mode)
	    printf ("bxl,bxr,byb,byt:  samples:\n");
	printf ("%5ld %5ld %5ld %5ld  %2ld\n",
	    ginfo3.bxl, ginfo3.bxr, ginfo3.byb, ginfo3.byt,
	    ginfo3.nr_samples);
    }
    dmCloseStream (fp, QUIT);
}

read_mc (file)
char *file;
{
    int ft = 0;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while (dmGetDesignData (fp, GEO_MC) > 0) {
	if (n_mode) {
	    if (strcmp (n_mode, gmc.cell_name)) continue;
	}
	if (ft) { ft = 0;
printf ("cell: inst: tx: ty: mt[0,1,3,4]: bxl,bxr,byb,byt: [dx,nx: dy,ny:]\n");
	}
    printf ("%-10s %-10s %5ld %5ld  %2ld %2ld %2ld %2ld %5ld %5ld %5ld %5ld",
	    gmc.cell_name, gmc.inst_name,
	    gmc.mtx[2], gmc.mtx[5],
	    gmc.mtx[0], gmc.mtx[1], gmc.mtx[3], gmc.mtx[4],
	    gmc.bxl, gmc.bxr, gmc.byb, gmc.byt);
	if (gmc.nx || gmc.ny)
	    printf ("  %ld %ld  %ld %ld", gmc.dx, gmc.nx, gmc.dy, gmc.ny);
	printf ("%s\n", (gmc.imported ? " (IMP)" : ""));
    }
    dmCloseStream (fp, QUIT);
}

read_box (file)
char *file;
{
    int ft = 0;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while (dmGetDesignData (fp, GEO_BOX) > 0) {
	if (ft) { ft = 0;
	    printf ("lay: xl,xr,yb,yt: [bxl,bxr,byb,byt: dx,nx: dy,ny:]\n");
	}
	printf ("%-3s %5ld %5ld %5ld %5ld",
	    Lay (gbox.layer_no), gbox.xl, gbox.xr, gbox.yb, gbox.yt);
	if (gbox.nx || gbox.ny) {
	    printf ("  %5ld %5ld %5ld %5ld  %ld %ld  %ld %ld",
		gbox.bxl, gbox.bxr, gbox.byb, gbox.byt,
		gbox.dx, gbox.nx, gbox.dy, gbox.ny);
	}
	printf ("\n");
    }
    dmCloseStream (fp, QUIT);
}

read_term (file)
char *file;
{
    int ft = 0;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while (dmGetDesignData (fp, GEO_TERM) > 0) {
	if (ft) { ft = 0;
    printf ("term: lay: xl,xr,yb,yt: [bxl,bxr,byb,byt: dx,nx: dy,ny:]\n");
	}
	printf ("%-10s %-3s %5ld %5ld %5ld %5ld",
	    gterm.term_name, Lay (gterm.layer_no),
	    gterm.xl, gterm.xr, gterm.yb, gterm.yt);
	if (gterm.nx || gterm.ny) {
	    printf ("  %5ld %5ld %5ld %5ld  %ld %ld  %ld %ld",
		gterm.bxl, gterm.bxr, gterm.byb, gterm.byt,
		gterm.dx, gterm.nx, gterm.dy, gterm.ny);
	}
	printf ("\n");
    }
    dmCloseStream (fp, QUIT);
}

read_nor (file)
char *file;
{
    int ft = 0;
    register int i;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while (dmGetDesignData (fp, GEO_NOR_INI) > 0) {
	if (ft) { ft = 0;
	    printf ("lay: elmt: no_xy: bxl,bxr,byb,byt:\n");
	    printf ("[r_bxl,bxr,byb,byt: dx,nx: dy,ny:]\n");
	    printf ("x: y:\n");
	}
	printf ("%-3s %ld %4ld %5ld %5ld %5ld %5ld\n",
	    Lay (gnor_ini.layer_no), gnor_ini.elmt, gnor_ini.no_xy,
	    gnor_ini.bxl, gnor_ini.bxr, gnor_ini.byb, gnor_ini.byt);

	if (gnor_ini.nx || gnor_ini.ny) {
	    printf ("%11s%5ld %5ld %5ld %5ld  %.3f %ld  %.3f %ld\n", "",
		gnor_ini.r_bxl, gnor_ini.r_bxr, gnor_ini.r_byb, gnor_ini.r_byt,
		gnor_ini.dx, gnor_ini.nx, gnor_ini.dy, gnor_ini.ny);
	}

	for (i = 0; i < gnor_ini.no_xy; ++i) {
	    dmGetDesignData (fp, GEO_NOR_XY);
	    printf ("%10.3f %10.3f\n", gnor_xy.x, gnor_xy.y);
	}
    }
    dmCloseStream (fp, QUIT);
}

read_bxx (file)
char *file;
{
    int ft = 0;
    int term = 0;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) { ++ft;
	if (file[0] == 't' && file[1] == '_') ++term;
    }
    while (dmGetDesignData (fp, GEO_BOXLAY) > 0) {
	if (ft) { ft = 0;
	printf ("  xl:   xr:   yb:   yt:  %s:\n", (term ? "term#" : " ct"));
	}
	printf ("%5ld %5ld %5ld %5ld %5ld\n",
	    gboxlay.xl, gboxlay.xr, gboxlay.yb, gboxlay.yt,
	    gboxlay.chk_type);
    }
    dmCloseStream (fp, QUIT);
}

read_gln (file)
char *file;
{
    int ft = 0;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while (dmGetDesignData (fp, GEO_GLN) > 0) {
	if (ft) { ft = 0;
	    printf ("  xl:   xr:   yl:   yr:\n");
	}
	printf ("%5d %5d %5d %5d\n",
	    ggln.xl, ggln.xr, ggln.yl, ggln.yr);
    }
    dmCloseStream (fp, QUIT);
}

read_nxx (file)
char *file;
{
    int ft = 0;
    register int i;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while (dmGetDesignData (fp, GEO_NXX_INI) > 0) {
	if (ft) { ft = 0;
	    printf ("elmt: no_xy: [xc: yc: r1: r2: a1: a2:]\n");
	    printf ("x: y:\n");
	}
	printf ("%ld %4ld", gnxx_ini.elmt, gnxx_ini.no_xy);
	if (gnxx_ini.elmt == CIRCLE_NOR) {
	    printf (" %.3f %.3f %.3f %.3f %.3f %.3f\n",
		gnxx_ini.xc, gnxx_ini.yc,
		gnxx_ini.r1, gnxx_ini.r2,
		gnxx_ini.a1, gnxx_ini.a2);
	}
	else {
	    printf ("\n");
	}
	for (i = 0; i < gnxx_ini.no_xy; ++i) {
	    dmGetDesignData (fp, GEO_NXX_XY);
	    printf ("%10.3f %10.3f\n", gnxx_xy.x, gnxx_xy.y);
	}
    }
    dmCloseStream (fp, QUIT);
}

read_pgt (file)
char *file;
{
    int i, ft = 0;
    long X, Y, W, V, U;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while ((i = _dmDoget (fp -> dmfp, "DDDDD", &X, &Y, &W, &V, &U)) == 5) {
	if (ft) { ft = 0;
	    printf ("      X:       Y:       W:       V:    U:\n");
	}
	printf ("%8ld %8ld %8ld %8ld %5ld\n", X, Y, W, V, U);
    }
    if (i != EOF) error (3, file);
    dmCloseStream (fp, QUIT);
}

read_vln (file)
char *file;
{
    int ft = 0;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while (dmGetDesignData (fp, GEO_VLNLAY) > 0) {
	if (ft) { ft = 0;
	    printf ("   x:   yb:   yt:  occ: con:  ct:  grp:\n");
	}
	printf ("%5ld %5ld %5ld     %c    %c   %2ld %5ld\n",
	    gvlnlay.x, gvlnlay.yb, gvlnlay.yt,
	    gvlnlay.occ_type, gvlnlay.con_type,
	    gvlnlay.chk_type, gvlnlay.grp_number);
    }
    dmCloseStream (fp, QUIT);
}

read_teq (file)
char *file;
{
    int ft = 0;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while (dmGetDesignData (fp, GEO_TEQ) > 0) {
	if (ft) { ft = 0;
	    printf ("term#:  grp:\n");
	}
	printf ("%4ld    %ld\n", gteq.term_number, gteq.grp_number);
    }
    dmCloseStream (fp, QUIT);
}

read_tid (file)
char *file;
{
    int ft = 0;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    while (dmGetDesignData (fp, GEO_TID) > 0) {
	if (gtid.term_offset == -1) {
	    if (v_mode) { ++ft;
		printf ("cell: inst_name: nx: ny:\n");
	    }
	    printf ("%-10s %-10s %2ld %2ld\n",
		gtid.cell_name, gtid.inst_name,
		gtid.m_nx, gtid.m_ny);
	}
	else {
	    if (ft) { ft = 0;
		printf ("off: term_name: nx: ny:\n");
	    }
	    printf ("%-3ld %-10s %2ld %2ld\n",
		gtid.term_offset, gtid.term_name,
		gtid.t_nx, gtid.t_ny);
	}
    }
    dmCloseStream (fp, QUIT);
}

read_spec (file)
char *file;
{
    int ft = 0;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while (dmGetDesignData (fp, GEO_SPEC) > 0) {
	if (ft) { ft = 0;
	    printf ("lay: xl: xr: yb: yt: name:\n");
	}
	printf ("%-3s %5ld %5ld %5ld %5ld  %s\n",
		gspec.layer, gspec.xl, gspec.xr,
		gspec.yb, gspec.yt, gspec.name);
    }

    dmCloseStream (fp, QUIT);
}

read_flashes (file)
char *file;
{
    register int i, j, n;
    int v;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (SCAN "%d", &v) != 1) error (3, file);
    printf ("%s%ld\n", (v_mode) ? "area = " : "", v);
    if (SCAN "%d", &v) != 1) error (3, file);
    printf ("%s%ld\n", (v_mode) ? "overlay = " : "", v);
    for (n = i = 0; i < process -> nomasks; ++i) {
	if (process -> pgt_no[i] <= 0) continue;
	++n;
	if (SCAN "%d", &v) != 1) error (3, file);
	if (v_mode && n == 1) printf ("#boxes:  (lay:)\n");
	printf ("%7ld", v);
	if (v_mode) {
	    for (j = 0; j < process -> nomasks; ++j)
		if (process -> pgt_no[j] == n) {
		    printf ("  (%s)\n", Lay (j));
		    break;
		}
	}
	else printf ("\n");
    }
    for (n = i = 0; i < process -> nomasks; ++i) {
	if (process -> pgt_no[i] <= 0) continue;
	++n;
	if (SCAN "%d", &v) != 1) error (3, file);
	printf ("%7ld", v);
	if (v_mode) {
	    for (j = 0; j < process -> nomasks; ++j)
		if (process -> pgt_no[j] == n) {
		    printf ("  (%s_neg)\n", Lay (j));
		    break;
		}
	}
	else printf ("\n");
    }
    dmCloseStream (fp, QUIT);
}

readc_info (file)
char *file;
{
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    dmGetDesignData (fp, CIR_INFO);
    printf ("bxl,bxr,byb,byt: %6ld %6ld %6ld %6ld\n",
	cinfo.bxl, cinfo.bxr, cinfo.byb, cinfo.byt);
    dmCloseStream (fp, QUIT);
}

readc_mc (file)
char *file;
{
    register long i;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    while (dmGetDesignData (fp, CIR_MC) > 0) {
	if (n_mode) {
	    if (strcmp (n_mode, cmc.cell_name)) continue;
	}
	printf ("cell:\"%s\" inst:\"%s\" attr:\"%s\" dim:%ld\n",
	    cmc.cell_name, cmc.inst_name,
	    cmc.inst_attribute, cmc.inst_dim);

	for (i = 0; i < cmc.inst_dim; ++i) {
	    printf ("lower,upper[%ld]: %ld, %ld\n",
		i, cmc.inst_lower[i], cmc.inst_upper[i]);
	}
    }
    dmCloseStream (fp, QUIT);
}

readc_term (file)
char *file;
{
    register long i;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    while (dmGetDesignData (fp, CIR_TERM) > 0) {
	printf ("term:\"%s\" attr:\"%s\" dim:%ld\n",
	    cterm.term_name,
	    cterm.term_attribute,
	    cterm.term_dim);

	for (i = 0; i < cterm.term_dim; ++i) {
	    printf ("lower,upper[%ld]: %ld, %ld\n",
		i, cterm.term_lower[i], cterm.term_upper[i]);
	}
    }
    dmCloseStream (fp, QUIT);
}

readc_net (file)
char *file;
{
    register long i, j;
    register struct cir_net *cn;
    int done = 0;

    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    while (dmGetDesignData (fp, CIR_NET) > 0) {
	if (n_mode) {
	    if (done) break;
	    if (strcmp (n_mode, cnet.net_name)) continue;
	    ++done;
	}
	printf ("net:\"%s\" inst:\"%s\" attr:\"%s\" subnets:%ld\n",
	    cnet.net_name, cnet.inst_name,
	    cnet.net_attribute, cnet.net_neqv);

	for (i = 0; i < cnet.net_dim; ++i) {
	    printf ("net_lower,upper[%ld]: %ld, %ld\n",
		i, cnet.net_lower[i], cnet.net_upper[i]);
	}
	for (i = 0; i < cnet.inst_dim; ++i) {
	    printf ("inst_lower,upper[%ld]: %ld, %ld\n",
		i, cnet.inst_lower[i], cnet.inst_upper[i]);
	}
	for (i = 0; i < cnet.ref_dim; ++i) {
	    printf ("ref_lower,upper[%ld]: %ld, %ld\n",
		i, cnet.ref_lower[i], cnet.ref_upper[i]);
	}
	for (j = 0; j < cnet.net_neqv; ++j) {
	    cn = (cnet.net_eqv) + j;
	    printf ("    subnet[%ld]:\"%s\" inst:\"%s\" attr:\"%s\"\n", j,
		cn -> net_name, cn -> inst_name,
		cn -> net_attribute);

	    for (i = 0; i < cn -> net_dim; ++i) {
		printf ("    net_lower,upper[%ld]: %ld, %ld\n",
		    i, cn -> net_lower[i], cn -> net_upper[i]);
	    }
	    for (i = 0; i < cn -> inst_dim; ++i) {
		printf ("    inst_lower,upper[%ld]: %ld, %ld\n",
		    i, cn -> inst_lower[i], cn -> inst_upper[i]);
	    }
	    for (i = 0; i < cn -> ref_dim; ++i) {
		printf ("    ref_lower,upper[%ld]: %ld, %ld\n",
		    i, cn -> ref_lower[i], cn -> ref_upper[i]);
	    }
	}
    }
    dmCloseStream (fp, QUIT);
}

readf_mc (file)
char *file;
{
    int ft = 0;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while (dmGetDesignData (fp, FLP_MC) > 0) {
	if (n_mode) {
	    if (strcmp (n_mode, fmc.cell_name)) continue;
	}
	if (ft) { ft = 0;
printf ("cell: inst: tx: ty: mt[0,1,3,4]: bxl,bxr,byb,byt: [dx,nx: dy,ny:]\n");
	}
    printf ("%-10s %-10s %5ld %5ld  %2ld %2ld %2ld %2ld %5ld %5ld %5ld %5ld",
	    fmc.cell_name, fmc.inst_name,
	    fmc.mtx[2], fmc.mtx[5],
	    fmc.mtx[0], fmc.mtx[1], fmc.mtx[3], fmc.mtx[4],
	    fmc.bxl, fmc.bxr, fmc.byb, fmc.byt);
	if (fmc.nx || fmc.ny)
	    printf ("  %ld %ld  %ld %ld", fmc.dx, fmc.nx, fmc.dy, fmc.ny);
	printf ("%s\n", (fmc.imported ? " (IMP)" : ""));
    }
    dmCloseStream (fp, QUIT);
}

readf_info (file)
char *file;
{
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    dmGetDesignData (fp, FLP_INFO);
    printf ("bxl,bxr,byb,byt: %6ld %6ld %6ld %6ld\n",
	finfo.bxl, finfo.bxr, finfo.byb, finfo.byt);
    dmCloseStream (fp, QUIT);
}

readf_term (file)
char *file;
{
    int ft = 0;
    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    if (v_mode) ++ft;
    while (dmGetDesignData (fp, FLP_TERM) > 0) {
	if (ft) { ft = 0;
	    printf ("term: lay: side:  xl,xr,yb,yt:  attr:\n");
	    printf ("[    bxl,bxr,byb,byt:  dx,nx: dy,ny: ]\n");
	}
	printf ("%-10s %-3s %d  %5d %5d %5d %5d  \"%s\"\n",
	    fterm.term_name, Lay (fterm.layer_no), fterm.side,
	    fterm.xl, fterm.xr, fterm.yb, fterm.yt,
	    fterm.term_attribute);
	if (fterm.nx || fterm.ny) {
	    printf ("%18s%5d %5d %5d %5d  %d %d  %d %d\n", "",
		fterm.bxl, fterm.bxr, fterm.byb, fterm.byt,
		fterm.dx, fterm.nx, fterm.dy, fterm.ny);
	}
    }
    dmCloseStream (fp, QUIT);
}

readf_chan (file)
char *file;
{
    register int i, j;
    register struct flp_glr *fn;
    register struct flp_connect *fc;
    int done = 0;

    header (file);
    if (!(fp = dmOpenStream (key, file, "r"))) return;
    while (dmGetDesignData (fp, FLP_CHAN) > 0) {
	if (n_mode) {
	    if (done) break;
	    if (strcmp (n_mode, fchan.channel_name)) continue;
	    ++done;
	}
printf ("chan:\"%s\" xl,xr,yb,yt:%d,%d,%d,%d kind:%d order:%d nets:%d\n",
	    fchan.channel_name, fchan.xl, fchan.xr, fchan.yb, fchan.yt,
	    fchan.kind, fchan.order, fchan.flp_nlist);

	for (j = 0; j < fchan.flp_nlist; ++j) {
	    fn = fchan.flp_netlist + j;
	    printf ("    net[%d]:\"%s\" attr:\"%s\" connects:%d\n", j,
		fn -> net_name, fn -> net_attribute, fn -> flp_nconnect);
	    for (i = 0; i < fn -> flp_nconnect; ++i) {
		fc = fn -> flp_netconnect + i;
    printf ("        con[%d]:\"%s\" type:%d origin:\"%s\" nx,ny:%d,%d\n",
		i, fc -> connect_name, fc -> connect_type,
		fc -> connect_origin, fc -> nx, fc -> ny);
	    }
	}
    }
    dmCloseStream (fp, QUIT);
}

header (file)
char *file;
{
    printf ("=> %s/%s/%s\n", view, cell, file);
}

sig_handler (sig) /* signal handler */
int sig;
{
    signal (sig, SIG_IGN); /* ignore signal */
    PE "\n");
    error (0, "");
}

dmError (s)
char *s;
{
    if (dmerrno == DME_FOPEN) {
	printf ("%s: %s ==== cannot open ====\n", argv0, s);
	return;
    }
    PE "%s: ", argv0);
    dmPerror (s);
    error (1, "");
}

char *errlist[] = {
/* 0 */  "received interrupt signal",
/* 1 */  "error in DMI function",
/* 2 */  "unknown dbstream: %s",
/* 3 */  "%s: read error",
/* 4 */  "unknown error"
};

error (nr, s)
int   nr;
char *s;
{
    if (nr < 0 || nr > 4) nr = 4;
    PE "%s: ", argv0);
    PE errlist[nr], s);
    PE "\n%s: -- program aborted --\n", argv0);
    dmQuit ();
    exit (1);
}
