static char *SccsId = "@(#)prTabs.c 4.3 (TU-Delft) 05/26/92";
/**********************************************************

Name/Version      : tecc/4.3

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"
#include "extern.h"

#define MajorProtNr  1
#define MinorProtNr  1

extern int silent;
extern int docompress;

static int layC_cnt;
static int elR_cnt;

static FILE *fp_out;

static int ElemMaxNbr;
static int elemCnt;
static int condCnt;
static int CondNbr[100];
static int CondMaxNbr;

static char resSortTab[MAXRESSORT][DM_MAXNAME + 1];
int resSortTabSize;
static char capSortTab[MAXCAPSORT][DM_MAXNAME + 1];
int capSortTabSize;

prTabs (outfile)
char *outfile;
{
    int i;

    for (i = 0; i < 100; i++) {
	CondNbr[i] = 0;
    }

    if (outfile) {
	OPENW (fp_out, outfile);
    }
    else
	fp_out = stdout;

    fprintf (fp_out, "# %d %d\n", MajorProtNr, MinorProtNr);

    prMaskinfo ();

    prBitmasks ();

    prElems ();

    prLayerCond ();

    prKeytab ();

    /*
    prElRefs ();
    */

    if (outfile)
	CLOSE (fp_out);

    if (!silent) {
	fprintf (stderr, "\n");

	{
	    struct layerRef * k;
	    extern struct layerRef * keylist;

	    fprintf (stderr, " --- keys: ");
	    for (k = keylist; k != NULL; k = k -> next) {
		switch (k -> lay -> occurrence) {
		    case SURFACE:
			fprintf (stderr, " "); 
			break;
		    case EDGE:
			fprintf (stderr, " -"); 
			break;
		    case OTHEREDGE:
			fprintf (stderr, " ="); 
			break;
		    default:
			/* ASSERT (0); */
			break;
		}
		fprintf (stderr, "%s",
		    procdata -> mask_name[k -> lay -> mask]);
	    }
	    fprintf (stderr, "\n");
	}

	fprintf (stderr, " --- number of key slots : %d\n", nbrKeySlots);

	fprintf (stderr, 
	" --- maximum number of elements per key slot : %d\n", 
	ElemMaxNbr);

	fprintf (stderr, 
	" --- maximum number of additional conditions per element : %d\n", 
	CondMaxNbr);

	fprintf (stderr, 
	" --- average number of additional conditions per element : %f\n", 
	condCnt / (double) elemCnt);

	fprintf (stderr, "\n");

	fprintf (stderr, " --- add. cond.   :");
	for (i = 0; i <= CondMaxNbr; i++) {
	    fprintf (stderr, " %2d", i);
	}
	fprintf (stderr, "\n");

	fprintf (stderr, "     no. of elem. :");
	for (i = 0; i <= CondMaxNbr; i++) {
	    fprintf (stderr, " %2d", CondNbr[i]);
	}
	fprintf (stderr, "\n");

	fprintf (stderr, "\n");
    }
}

prMaskinfo ()
{
    int i;
    int color;

    fprintf (fp_out, "%d\n", procdata -> nomasks);

    for (i = 0; i < procdata -> nomasks; i++) {
	fprintf (fp_out, "%s ", procdata -> mask_name[i]);
	if (conducTransf[i] < 0)
	    fprintf (fp_out, "0 ");
	else
	    fprintf (fp_out, "1 ");
	color = 1;
	color = color << maskTransf[i];
	fprintf (fp_out, "%d ", color);
	fprintf (fp_out, "%d ", conducTransf[i]);
	fprintf (fp_out, "\n");
    }

    fprintf (fp_out, "%d\n", conducCnt);
}

prBitmasks ()
{
    int sBitmask;
    int eBitmask;
    int oeBitmask;

    sBitmask = 1;
    sBitmask = sBitmask << sSlotCnt;
    sBitmask--;

    eBitmask = 1;
    eBitmask = eBitmask << (sSlotCnt + eSlotCnt);
    eBitmask--;
    eBitmask = eBitmask ^ sBitmask;

    oeBitmask = 1;
    oeBitmask = oeBitmask << (sSlotCnt + eSlotCnt + oeSlotCnt);
    oeBitmask--;
    oeBitmask = oeBitmask ^ sBitmask;
    oeBitmask = oeBitmask ^ eBitmask;

    fprintf (fp_out, "%d\n", sBitmask);
    fprintf (fp_out, "%d\n", eBitmask);
    fprintf (fp_out, "%d\n", oeBitmask);
}

    /*********************************************

    for (i = 0; i < procdata -> nomasks; i++) {
	fprintf (fp_out, "%d ", sLayerWeight[i]);
    }
    fprintf (fp_out, "\n");
    for (i = 0; i < procdata -> nomasks; i++) {
	fprintf (fp_out, "%d ", eLayerWeight[i]);
    }
    fprintf (fp_out, "\n");
    for (i = 0; i < procdata -> nomasks; i++) {
	fprintf (fp_out, "%d ", oeLayerWeight[i]);
    }
    fprintf (fp_out, "\n");

    *********************************************/

prElems ()
{
    int i;
    int j;
    int nbr;
    int elemtype;

    CondMaxNbr = 0;
    elemCnt = 0;
    condCnt = 0;

    layC_cnt = 0;

    resSortTabSize = 0;

    for (i = 0; i < res_cnt; i++) {
	for (j = 0; j < resSortTabSize; j++) {
	    if (strcmp (ress[i].sort, resSortTab[j]) == 0)
		break;
	}
	ress[i].sortNr = j;
	if (j == resSortTabSize) {
	    strcpy (resSortTab[j], ress[i].sort);
	    resSortTabSize++;
	}
    }

    for (i = 0; i < con_cnt; i++) {
	for (j = 0; j < resSortTabSize; j++) {
	    if (strcmp (cons[i].sort, resSortTab[j]) == 0)
		break;
	}
	cons[i].sortNr = j;
	if (j == resSortTabSize) {
	    strcpy (resSortTab[j], cons[i].sort);
	    resSortTabSize++;
	}
    }

    capSortTabSize = 0;

    for (i = 0; i < cap_cnt; i++) {
	for (j = 0; j < capSortTabSize; j++) {
	    if (strcmp (caps[i].sort, capSortTab[j]) == 0)
		break;
	}
	caps[i].sortNr = j;
	if (j == capSortTabSize) {
	    strcpy (capSortTab[j], caps[i].sort);
	    capSortTabSize++;
	}
    }

    fprintf (fp_out, "%d\n", resSortTabSize);
    for (i = 0; i < resSortTabSize; i++) {
	fprintf (fp_out, "%s\n", resSortTab[i]);
    }
    fprintf (fp_out, "%d\n", capSortTabSize);
    for (i = 0; i < capSortTabSize; i++) {
	fprintf (fp_out, "%s\n", capSortTab[i]);
    }

    fprintf (fp_out, "%d\n", con_cnt + cap_cnt + res_cnt 
			     + tor_cnt + vdim_cnt + shape_cnt);

    for (i = 0; i < con_cnt; i++) {
	nbr = howManyCond (cons[i].cond);
	if (nbr > CondMaxNbr) CondMaxNbr = nbr;
	CondNbr[nbr]++;
	elemCnt++;
	condCnt += nbr;
	fprintf (fp_out, "%s %d %d %d %d %d %d %d %e\n",
	         cons[i].name, 
		 cons[i].id,
		 layC_cnt,
		 nbr,
		 CON, /* type */
		 cons[i].sortNr,
		 cons[i].mask1,
		 cons[i].mask2,
		 cons[i].val);
	layC_cnt += nbr; 
    }

    for (i = 0; i < tor_cnt; i++) {
	nbr = howManyCond (tors[i].cond);
	if (nbr > CondMaxNbr) CondMaxNbr = nbr;
	CondNbr[nbr]++;
	elemCnt++;
	condCnt += nbr;
	fprintf (fp_out, "%s %d %d %d %d %d %d\n",
	         tors[i].name,
		 tors[i].id,
		 layC_cnt,
		 nbr,
		 TOR,
		 tors[i].g, tors[i].ds);
	layC_cnt += nbr; 
    }

    for (i = 0; i < cap_cnt; i++) {
	nbr = howManyCond (caps[i].cond);
	if (nbr > CondMaxNbr) CondMaxNbr = nbr;
	CondNbr[nbr]++;
	elemCnt++;
	condCnt += nbr;

	if (caps[i].nLay -> mask >= 0
	&& caps[i].nLay -> occurrence == OTHEREDGE) {
	    elemtype = LATCAP;
	}
	else if (caps[i].pLay -> occurrence == EDGE
	|| (caps[i].nLay -> mask >= 0
	    && caps[i].nLay -> occurrence == EDGE)) {
	    elemtype = EDGECAP;
	}
	else {
	    elemtype = SURFCAP;
	}

	fprintf (fp_out, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %e\n",
	         caps[i].name,
		 caps[i].id,
		 layC_cnt,
		 nbr,
		 elemtype,
		 caps[i].sortNr,
		 caps[i].pLay -> mask, caps[i].pLay -> occurrence,
		 caps[i].nLay -> mask, caps[i].nLay -> occurrence,
		 caps[i].sBitPresent, caps[i].sBitAbsent,
		 caps[i].oeBitPresent, caps[i].oeBitAbsent,
		 caps[i].val);
	layC_cnt += nbr; 
    }

    for (i = 0; i < res_cnt; i++) {
	nbr = howManyCond (ress[i].cond);
	CondNbr[nbr]++;
	elemCnt++;
	condCnt += nbr;
	if (nbr > CondMaxNbr) CondMaxNbr = nbr;
	fprintf (fp_out, "%s %d %d %d %d %d %d %e\n",
	         ress[i].name,
		 ress[i].id,
		 layC_cnt,
		 nbr,
		 RES,
		 ress[i].sortNr,
		 ress[i].mask,
		 ress[i].val);
	layC_cnt += nbr; 
    }

    for (i = 0; i < vdim_cnt; i++) {
	nbr = howManyCond (vdms[i].cond);
	CondNbr[nbr]++;
	elemCnt++;
	condCnt += nbr;
	if (nbr > CondMaxNbr) CondMaxNbr = nbr;
	fprintf (fp_out, "%s %d %d %d %d %d %e %e\n",
	         vdms[i].name,
		 vdms[i].id,
		 layC_cnt,
		 nbr,
		 VDIMEN,
		 vdms[i].mask,
		 vdms[i].height,
		 vdms[i].thickness);
	layC_cnt += nbr; 
    }

    for (i = 0; i < shape_cnt; i++) {
	nbr = howManyCond (shps[i].cond);
	CondNbr[nbr]++;
	elemCnt++;
	condCnt += nbr;
	if (nbr > CondMaxNbr) CondMaxNbr = nbr;
	fprintf (fp_out, "%s %d %d %d %d %d %e %e %e %e\n",
	         shps[i].name,
		 shps[i].id,
		 layC_cnt,
		 nbr,
		 shps[i].type,
		 shps[i].mask,
		 shps[i].xb1,
		 shps[i].xt1,
		 shps[i].xb2,
		 shps[i].xt2);
	layC_cnt += nbr; 
    }
}

int howManyCond (cond)
struct layCondRef *cond;
{
    int cnt;

    cnt = 0;
    while (cond != NULL) {
	cond = cond -> next;
	cnt++;
    }

    return (cnt);
}

prLayerCond ()
{
    int i;

    fprintf (fp_out, "%d\n", layC_cnt);

    for (i = 0; i < con_cnt; i++) {
	prLCs (cons[i].cond);
    }

    for (i = 0; i < tor_cnt; i++) {
	prLCs (tors[i].cond);
    }

    for (i = 0; i < cap_cnt; i++) {
	prLCs (caps[i].cond);
    }

    for (i = 0; i < res_cnt; i++) {
	prLCs (ress[i].cond);
    }
}

prLCs (cond)
struct layCondRef *cond;
{
    while (cond != NULL) {

	fprintf (fp_out, "%d %d %d\n",
		 cond -> layC -> lay -> mask,
		 cond -> layC -> lay -> occurrence,
		 cond -> layC -> present);

	cond = cond -> next;
    }
}

prKeytab ()
{
    int i;
    int j;
    int backRefer;
    int nbr;
    struct elemRef *elref;
    struct elemRef *elref_j;

    ElemMaxNbr = 0;

    fprintf (fp_out, "%d\n", nbrKeySlots);

    elR_cnt = 0;
    for (i = 0; i < nbrKeySlots; i++) {
	for (elref = keytab[i]; elref; elref = elref -> next)
	    elR_cnt++;

	elR_cnt++; /* for terminating NULL pointer */
    }

    fprintf (fp_out, "%d\n", elR_cnt);

    for (i = 0; i < nbrKeySlots; i++) {

	nbr = 0;

	backRefer = -1;
	if (docompress && keytab[i]) {

	    elref = keytab[i];
	    elref -> check = 0;
	    while (elref) {
		elref -> check += elno (elref);
	        elref = elref -> next;
	    }

	    for (j = 0; j < i; j++) {
		elref_j = keytab[j];
		if (!elref_j)
		    continue;
		elref = keytab[i];
		if (elref_j -> check < 0   
			     /* this one already refers to another one */
		    || elref -> check != elref_j -> check)
			     /* or it is sure that keytab[i] and keytab[j]
				are not equal */
		    continue;
		while (elref && elref_j) {
		    if (elno (elref) != elno (elref_j))
			break;
		    elref = elref -> next;
		    elref_j = elref_j -> next;
		}
		if (!elref && !elref_j)
		    backRefer = j;     /* keytab[i] and keytab[j] are equal */
	    }
	}

	elref = keytab[i];

	if (backRefer >= 0) {
	    elref -> check = -1;
	    fprintf (fp_out, "=%d\n", backRefer);
	}
	else {
	    while (elref) {

		nbr++;

		fprintf (fp_out, "%d", elno (elref));
		elref = elref -> next;
		if (elref)
		    fprintf (fp_out, " ");
	    }
	    fprintf (fp_out, "\n");
	}

	if (nbr > ElemMaxNbr) {
	    ElemMaxNbr = nbr;
	}
    }
}

int elno (elref)
struct elemRef *elref;
{
    int num = 0;
    switch (elref -> type) {
	case ESHAPE:
	case CSHAPE:  num += vdim_cnt;
	case VDIMEN:  num += res_cnt;
	case RES:     num += cap_cnt;
	case LATCAP:
	case EDGECAP:
	case SURFCAP: num += tor_cnt;
	case TOR:     num += con_cnt;
	case CON:     num += elref -> no;
    }
    return (num);
}

int howManyElem (elref)
struct elemRef *elref;
{
    int cnt;

    cnt = 0;
    while (elref != NULL) {
	elref = elref -> next;
	cnt++;
    }

    return (cnt);
}

prElRefs ()
{
    int i;
    struct elemRef *elref;

    fprintf (fp_out, "%d\n", elR_cnt);
    for (i = 0; i < nbrKeySlots; i++) {
	elref = keytab[i];
	while (elref != NULL) {
	    fprintf (fp_out, "%d %d\n", elref -> type, elref -> no);
	    elref = elref -> next;
	}
	if (keytab[i] != NULL)
	    fprintf (fp_out, "-1 -1\n");  /* trailing -1 */
    }
}
