/*******************************************************************************
* mbk     : user functions known as genlib                                     *
*                                                                              *
* author  : Frederic Petrot                                                    *
* version : 3.18                                                               *
* date    : 03/09/93                                                           *
*******************************************************************************/

#ident "@(#)genlib.c 3.16 : Alliance procedural generation library"

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include MUT_H
#include MLO_H
#include MLU_H
#include MPH_H
#include MPU_H

/*******************************************************************************
* global variables used in genlib                                              *
*******************************************************************************/
phins_list *WORK_PHINS;                        /* physical work figure        */
phfig_list *WORK_PHFIG;                        /* physical work instance      */
lofig_list *WORK_LOFIG;                        /* logical work instance       */

static char *checkname();
static void toolong();
int is_bus();
int bus_decod();
/*******************************************************************************
* physical user functions                                                      *
*******************************************************************************/

/*******************************************************************************
* function DEF_PHFIG                                                           *
*******************************************************************************/
void genDEF_PHFIG(name)
char	*name;
{
phfig_list *ptfig;
char *s = namealloc(name);

	mbkenv();
	for (ptfig = HEAD_PHFIG; ptfig; ptfig = ptfig->NEXT)
		if (ptfig->NAME == s)
			break;
	if (ptfig == NULL)
		WORK_PHFIG = addphfig(s);
	else
		WORK_PHFIG = ptfig;
}

/*******************************************************************************
* function LOAD_PHFIG                                                          *
*******************************************************************************/
void genLOAD_PHFIG(name)
char	*name;
{
	mbkenv();
	WORK_PHFIG = getphfig(name, 'A');
}

/*******************************************************************************
* function SAVE_PHFIG                                                          *
*******************************************************************************/
void genSAVE_PHFIG()
{
	savephfig(WORK_PHFIG);
}

/*******************************************************************************
* function DEF_AB                                                              *
*******************************************************************************/
void genDEF_AB(dx1, dy1, dx2, dy2)
long dx1, dy1, dx2, dy2;
{
phfig_list *ptfig;
phins_list *ptins;
ptype_list *ptype;
num_list *ptnum;
long x1, y1, x2, y2;
long insx1, insx2, insy1, insy2;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("DEF_AB impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_PHFIG->PHINS == NULL)
		x1 = x2 = y1 = y2 = 0;
	else {
		x1 = WORK_PHFIG->PHINS->XINS;
		y1 = WORK_PHFIG->PHINS->YINS;
		x2 = WORK_PHFIG->PHINS->XINS;
		y2 = WORK_PHFIG->PHINS->YINS;
	}
	for (ptins = WORK_PHFIG->PHINS; ptins; ptins = ptins->NEXT) {
		ptype = getptype(ptins->USER, (long)PLACEABOX);
		if (ptype == NULL) {
			ptfig = getphfig(ptins->FIGNAME, 'P');
			insx1 = ptins->XINS;
			insy1 = ptins->YINS;
			insx2 = ptins->XINS + ptfig->XAB2 - ptfig->XAB1;
			insy2 = ptins->YINS + ptfig->YAB2 - ptfig->YAB1;
		} else {
			ptnum = (num_list *)(ptype->DATA);
			insx1 = ptins->XINS;
			insy1 = ptins->YINS;
			insx2 = ptnum->DATA;
			insy2 = ptnum->NEXT->DATA;
		}
		if (x1 > insx1)
			x1 = insx1;
		if (y1 > insy1)
			y1 = insy1;
		if (x2 < insx2)
			x2 = insx2;
		if (y2 < insy2)
			y2 = insy2;
	}
	defab(WORK_PHFIG, x1 + dx1, y1 + dy1, x2 + dx2, y2 + dy2);
}

/*******************************************************************************
* function DEF_PHINS                                                           *
*******************************************************************************/
void genDEF_PHINS(name)
char *name;
{
	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("DEF_PHINS impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	WORK_PHINS = getphins(WORK_PHFIG, name);
}

/*******************************************************************************
* function PHCON                                                               *
*******************************************************************************/
phcon_list *genPHCON(layer, width, name, orient, x, y)
char orient;
char *name;
long x, y, width;
char layer;
{
	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PHCON impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	return addphcon(WORK_PHFIG, orient, checkname(name), x, y, layer, width);
}

/*******************************************************************************
* function COPY_UP_CON                                                         *
*******************************************************************************/
chain_list *genCOPY_UP_CON(index, locname, insname, newname)
long index;
char *insname;
char *locname;
char *newname;
{
phfig_list *ptnewfig, *getphfig();
phins_list *ptins;
phcon_list *ptcon, *con;
phseg_list *seg = NULL;
long xcon, ycon;
long width;
char layer;
char orient;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("COPY_UP_CON impossible :", stderr);
		(void)fputs(" missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}

	ptins = getphins(WORK_PHFIG, insname);
	ptnewfig = getphfig(ptins->FIGNAME, 'P');

	/*  looking for a connector(locname, index) */
	locname = namealloc(checkname(locname));
	for (ptcon = ptnewfig->PHCON; ptcon; ptcon = ptcon->NEXT)
		if (locname == ptcon->NAME && index == ptcon->INDEX)
			break; /* the only one is found here, since(name, index) is unique */

	if (ptcon != NULL) {
		xyflat(&xcon, &ycon, ptcon->XCON, ptcon->YCON, ptins->XINS,
		     ptins->YINS, ptnewfig->XAB1, ptnewfig->YAB1, ptnewfig->XAB2,
		     ptnewfig->YAB2, ptins->TRANSF);

		width = ptcon->WIDTH;
		layer = ptcon->LAYER;
		orient = instanceface(ptcon->ORIENT, ptins->TRANSF);

		/*  create connector and segment, now UNIQUE  */
		switch (orient) {
		case WEST :
			if (newname)
				con = addphcon(WORK_PHFIG, WEST, checkname(newname),
								WORK_PHFIG->XAB1, ycon, layer, width);
			if (xcon > WORK_PHFIG->XAB1)
				seg = addphseg(WORK_PHFIG, layer, width,
								WORK_PHFIG->XAB1,ycon, xcon, ycon, (char *)NULL);
			break;
		case EAST :
			if (newname)
				con = addphcon(WORK_PHFIG, EAST, checkname(newname),
							WORK_PHFIG->XAB2, ycon, layer, width);
			if (xcon < WORK_PHFIG->XAB2)
				seg = addphseg(WORK_PHFIG, layer, width,
								xcon, ycon, WORK_PHFIG->XAB2, ycon, (char *)NULL);
			break;
		case SOUTH :
			if (newname)
				con = addphcon(WORK_PHFIG, SOUTH, checkname(newname), xcon,
							WORK_PHFIG->YAB1, layer, width);
			if (ycon > WORK_PHFIG->YAB1)
				seg = addphseg(WORK_PHFIG, layer, width,
								xcon, WORK_PHFIG->YAB1, xcon, ycon, (char *)NULL);
			break;
		case NORTH :
			if (newname)
				con = addphcon(WORK_PHFIG, NORTH, checkname(newname), xcon,
							WORK_PHFIG->YAB2, layer, width);
			if (ycon < WORK_PHFIG->YAB2)
				seg = addphseg(WORK_PHFIG, layer, width,
								xcon, ycon, xcon, WORK_PHFIG->YAB2, (char *)NULL);
			break;
		}
		return addchain(addchain((chain_list *)NULL, (void *)seg), (void *)con);
	}

	(void)fflush(stdout);
	(void)fputs("*** genlib error ***\n", stderr);
	(void)fputs("COPY_UP_CON impossible : ", stderr);
	(void)fprintf(stderr, "connector %s index %ld of instance %s, figure %s,",
						locname, index, insname, WORK_PHFIG->NAME);
	(void)fputs(" doesn't exist\n", stderr);
	EXIT(1);
}

/*******************************************************************************
* function COPY_UP_CON_FACE                                                    *
*******************************************************************************/
chain_list *genCOPY_UP_CON_FACE(orient, locname, insname, newname)
char orient;
char *insname;
char *locname;
char *newname;
{
phfig_list *ptnewfig;
phins_list *ptins;
phcon_list *ptcon, *ptscan;
chain_list *cons = NULL, *segs = NULL;
long xcon, ycon;
long width;
char layer;
int found = 0;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("COPY_UP_CON_FACE impossible missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (orient != NORTH && orient != SOUTH && orient != EAST && orient != WEST) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fprintf(stderr, "illegal COPY_UP_CON_FACE : orientation is %ld\n",
		                   (long)orient);
		EXIT(1);
	}

	ptins = getphins(WORK_PHFIG, insname);
	ptnewfig = getphfig(ptins->FIGNAME, 'P');

	/*  recherche et remontee de tous les connecteurs (locname)  */
	locname = namealloc(checkname(locname));
	for (ptscan = ptnewfig->PHCON; ptscan; ptscan = ptscan->NEXT) {
		ptcon = NULL;
		switch (orient) {
		case WEST :
			if (ptins->TRANSF == NOSYM || ptins->TRANSF == SYM_Y) {
				if (locname == ptscan->NAME && ptscan->ORIENT == WEST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == SYMXY || ptins->TRANSF == SYM_X) {
				if (locname == ptscan->NAME && ptscan->ORIENT == EAST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_P || ptins->TRANSF == SY_RP) {
				if (locname == ptscan->NAME && ptscan->ORIENT == NORTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_M || ptins->TRANSF == SY_RM) {
				if (locname == ptscan->NAME && ptscan->ORIENT == SOUTH)
					ptcon = ptscan;
			}
			break;
		case EAST :
			if (ptins->TRANSF == NOSYM || ptins->TRANSF == SYM_Y) {
				if (locname == ptscan->NAME && ptscan->ORIENT == EAST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == SYMXY || ptins->TRANSF == SYM_X) {
				if (locname == ptscan->NAME && ptscan->ORIENT == WEST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_P || ptins->TRANSF == SY_RP) {
				if (locname == ptscan->NAME && ptscan->ORIENT == SOUTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_M || ptins->TRANSF == SY_RM) {
				if (locname == ptscan->NAME && ptscan->ORIENT == NORTH)
					ptcon = ptscan;
			}
			break;
		case NORTH :
			if (ptins->TRANSF == NOSYM || ptins->TRANSF == SYM_X) {
				if (locname == ptscan->NAME && ptscan->ORIENT == NORTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == SYMXY || ptins->TRANSF == SYM_Y) {
				if (locname == ptscan->NAME && ptscan->ORIENT == SOUTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_P || ptins->TRANSF == SY_RM) {
				if (locname == ptscan->NAME && ptscan->ORIENT == EAST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_M || ptins->TRANSF == SY_RP) {
				if (locname == ptscan->NAME && ptscan->ORIENT == WEST)
					ptcon = ptscan;
			}
			break;
		case SOUTH :
			if (ptins->TRANSF == NOSYM || ptins->TRANSF == SYM_X) {
				if (locname == ptscan->NAME && ptscan->ORIENT == SOUTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == SYMXY || ptins->TRANSF == SYM_Y) {
				if (locname == ptscan->NAME && ptscan->ORIENT == NORTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_P || ptins->TRANSF == SY_RM) {
				if (locname == ptscan->NAME && ptscan->ORIENT == WEST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_M || ptins->TRANSF == SY_RP) {
				if (locname == ptscan->NAME && ptscan->ORIENT == EAST)
					ptcon = ptscan;
			}
			break;
		}
		if (ptcon != NULL) {
			found++;
			xyflat(&xcon, &ycon, ptcon->XCON, ptcon->YCON,
						ptins->XINS, ptins->YINS, ptnewfig->XAB1, ptnewfig->YAB1,
						ptnewfig->XAB2, ptnewfig->YAB2, ptins->TRANSF);
			width = ptcon->WIDTH;
			layer = ptcon->LAYER;

			/*  create connector and segment    */
			switch (orient) {
			case WEST :
				cons = addchain(cons, (void *)addphcon(WORK_PHFIG, WEST, newname,
				    WORK_PHFIG->XAB1, ycon, layer, width));
				if (xcon > WORK_PHFIG->XAB1)
					segs = addchain(segs, (void *)addphseg(WORK_PHFIG, layer,
					    width, WORK_PHFIG->XAB1, ycon, xcon, ycon, (char *)NULL));
				break;
			case EAST :
				cons = addchain(cons, (void *)addphcon(WORK_PHFIG, EAST, newname,
				    WORK_PHFIG->XAB2, ycon, layer, width));
				if (xcon < WORK_PHFIG->XAB2)
					segs = addchain(segs, (void *)addphseg(WORK_PHFIG, layer,
					     width, xcon, ycon, WORK_PHFIG->XAB2, ycon, (char *)NULL));
				break;
			case SOUTH :
				cons = addchain(cons, (void *)addphcon(WORK_PHFIG,
				                            SOUTH, newname,
				     xcon, WORK_PHFIG->YAB1, layer, width));
				if (ycon > WORK_PHFIG->YAB1)
					segs = addchain(segs, (void *)addphseg(WORK_PHFIG, layer,
					     width, xcon, WORK_PHFIG->YAB1, xcon, ycon, (char *)NULL));
				break;
			case NORTH :
				cons = addchain(cons, (void *)addphcon(WORK_PHFIG, NORTH, newname,
				     xcon, WORK_PHFIG->YAB2, layer, width));
				if (ycon < WORK_PHFIG->YAB2)
					segs = addchain(segs, (void *)addphseg(WORK_PHFIG, layer,
					     width, xcon, ycon, xcon, WORK_PHFIG->YAB2, (char *)NULL));
				break;
			}
		}
	}

	if (!found) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("COPY_UP_CON_FACE impossible :\n", stderr);
		(void)fprintf(stderr, "connector %s of instance %s", locname, insname);
		(void)fprintf(stderr, ", figure %s, doesn't exist\n", WORK_PHFIG->NAME);
		EXIT(1);
	}
	return addchain(addchain((chain_list *)NULL, (void *)segs), (void *)cons);
}

/*******************************************************************************
* function COPY_UP_ALL_CON                                                     *
*******************************************************************************/
chain_list *genCOPY_UP_ALL_CON(orient, insname, cheminom)
char orient;
char *insname;
char cheminom;
{
phfig_list *ptnewfig, *getphfig();
phins_list *ptins;
phcon_list *ptcon, *ptscan;
chain_list *cons = NULL, *segs = NULL;
long xcon, ycon, width;
char layer;
int found = 0;
char *newname;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("COPY_UP_ALL_CON impossible missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (orient != NORTH && orient != SOUTH && orient != EAST && orient != WEST) {
		(void)fflush(stdout);
		(void)fputs("\n*** genlib error ***\n", stderr);
		(void)fprintf(stderr, "illegal COPY_UP_ALL_CON : orientation is %ld",
							(long)orient);
		(void)fprintf(stderr, "on instance %s of figure %s\n",
							insname, WORK_PHFIG->NAME);
		EXIT(1);
	}

	ptins = getphins(WORK_PHFIG, insname);
	ptnewfig = getphfig(ptins->FIGNAME, 'P');

	/*  recherche et remontee de tous les connecteurs */
	for (ptscan = ptnewfig->PHCON; ptscan; ptscan = ptscan->NEXT) {
		ptcon = NULL;
		switch (orient) {
		case WEST :
			if (ptins->TRANSF == NOSYM || ptins->TRANSF == SYM_Y) {
				if (ptscan->ORIENT == WEST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == SYMXY || ptins->TRANSF == SYM_X) {
				if (ptscan->ORIENT == EAST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_P || ptins->TRANSF == SY_RP) {
				if (ptscan->ORIENT == NORTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_M || ptins->TRANSF == SY_RM) {
				if (ptscan->ORIENT == SOUTH)
					ptcon = ptscan;
			}
			break;
		case EAST :
			if (ptins->TRANSF == NOSYM || ptins->TRANSF == SYM_Y) {
				if (ptscan->ORIENT == EAST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == SYMXY || ptins->TRANSF == SYM_X) {
				if (ptscan->ORIENT == WEST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_P || ptins->TRANSF == SY_RP) {
				if (ptscan->ORIENT == SOUTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_M || ptins->TRANSF == SY_RM) {
				if (ptscan->ORIENT == NORTH)
					ptcon = ptscan;
			}
			break;
		case NORTH :
			if (ptins->TRANSF == NOSYM || ptins->TRANSF == SYM_X) {
				if (ptscan->ORIENT == NORTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == SYMXY || ptins->TRANSF == SYM_Y) {
				if (ptscan->ORIENT == SOUTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_P || ptins->TRANSF == SY_RM) {
				if (ptscan->ORIENT == EAST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_M || ptins->TRANSF == SY_RP) {
				if (ptscan->ORIENT == WEST)
					ptcon = ptscan;
			}
			break;
		case SOUTH :
			if (ptins->TRANSF == NOSYM || ptins->TRANSF == SYM_X) {
				if (ptscan->ORIENT == SOUTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == SYMXY || ptins->TRANSF == SYM_Y) {
				if (ptscan->ORIENT == NORTH)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_P || ptins->TRANSF == SY_RM) {
				if (ptscan->ORIENT == WEST)
					ptcon = ptscan;
			} else if (ptins->TRANSF == ROT_M || ptins->TRANSF == SY_RP) {
				if (ptscan->ORIENT == EAST)
					ptcon = ptscan;
			}
			break;
		}
		if (ptcon != NULL) {
			found++;
			xyflat(&xcon, &ycon, ptcon->XCON, ptcon->YCON,
			    ptins->XINS, ptins->YINS, ptnewfig->XAB1, ptnewfig->YAB1,
			    ptnewfig->XAB2, ptnewfig->YAB2, ptins->TRANSF);
			width = ptcon->WIDTH;
			layer = ptcon->LAYER;
			newname = cheminom == 'Y' ? concatname(insname, ptcon->NAME)
												: ptcon->NAME;

			/*  create connector and segment    */
			switch (orient) {
			case WEST :
				cons = addchain(cons, (void *)addphcon(WORK_PHFIG, WEST, newname,
										WORK_PHFIG->XAB1, ycon, layer, width));
				if (xcon > WORK_PHFIG->XAB1)
					segs = addchain(segs, (void *)addphseg(WORK_PHFIG, layer,
					    					width, WORK_PHFIG->XAB1, ycon,
					    					xcon, ycon, (char *)NULL));
				break;
			case EAST :
				cons = addchain(cons, (void *)addphcon(WORK_PHFIG, EAST, newname,
				    					WORK_PHFIG->XAB2, ycon, layer, width));
				if (xcon < WORK_PHFIG->XAB2)
					segs = addchain(segs, (void *)addphseg(WORK_PHFIG, layer,
					    					width, xcon, ycon, WORK_PHFIG->XAB2,
					     					ycon, (char *)NULL));
				break;
			case SOUTH :
				cons = addchain(cons, (void *)addphcon(WORK_PHFIG, SOUTH, newname,
				     					xcon, WORK_PHFIG->YAB1, layer, width));
				if (ycon > WORK_PHFIG->YAB1)
					segs = addchain(segs, (void *)addphseg(WORK_PHFIG, layer,
					    					width, xcon, WORK_PHFIG->YAB1,
					    					xcon, ycon, (char *)NULL));
				break;
			case NORTH :
				cons = addchain(cons, (void *)addphcon(WORK_PHFIG, NORTH, newname,
				     					xcon, WORK_PHFIG->YAB2, layer, width));
				if (ycon < WORK_PHFIG->YAB2)
					segs = addchain(segs, (void *)addphseg(WORK_PHFIG, layer,
					    					width, xcon, ycon, xcon, WORK_PHFIG->YAB2,
					     					(char *)NULL));
				break;
			}
		}
	}

	if (!found) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal COPY_UP_ALL_CON : ", stderr);
		(void)fprintf(stderr, "instance %s, figure %s, has no connectors\n",
							insname, WORK_PHFIG->NAME);
		EXIT(1);
	}

	return addchain(addchain((chain_list *)NULL, (void *)segs), (void *)cons);
}

/*******************************************************************************
* function GET_CON_X                                                           *
*******************************************************************************/
long genGET_CON_X(insname, conname, index)
char *insname, *conname;
long index;
{
phfig_list *ptfig; /* pointer on model of instance called insname */
phins_list *ptins; /* pointer on instance called insname */
phcon_list *ptcon; /* pointer on the conname called con inside ptins */
long x_con, y_con; /* return values, y_con here for beauty */

	ptins = getphins(WORK_PHFIG, insname);
	ptfig = getphfig(ptins->FIGNAME, 'P');
	ptcon = getphcon(ptfig, checkname(conname), index);

	xyflat(&x_con, &y_con, ptcon->XCON, ptcon->YCON, ptins->XINS, ptins->YINS,
	     ptfig->XAB1, ptfig->YAB1,  ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);
	return x_con;
}

/*******************************************************************************
* function GET_CON_Y                                                           *
*******************************************************************************/
long genGET_CON_Y(insname, conname, index)
char *insname, *conname;
long index;
{
phfig_list *ptfig; /* pointer on model of instance called insname */
phins_list *ptins; /* pointer on instance called insname */
phcon_list *ptcon; /* pointer on the conname called con inside ptins */
long x_con, y_con; /* return values, x_con here for beauty */

	ptins = getphins(WORK_PHFIG, insname);
	ptfig = getphfig(ptins->FIGNAME, 'P');
	ptcon = getphcon(ptfig, checkname(conname), index);

	xyflat(&x_con, &y_con, ptcon->XCON, ptcon->YCON, ptins->XINS, ptins->YINS,
	     ptfig->XAB1, ptfig->YAB1,  ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);
	return y_con;
}

/*******************************************************************************
* function PHSEG                                                               *
*******************************************************************************/
phseg_list *genPHSEG(layer, width, name, x1, y1, x2, y2)
char *name;
long x1, y1, x2, y2, width;
char layer;
{
	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PHSEG impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	return addphseg(WORK_PHFIG, layer, width, x1, y1, x2, y2, name);
}

/*******************************************************************************
* function COPY_UP_SEG                                                         *
*******************************************************************************/
phseg_list *genCOPY_UP_SEG(locname, insname, newname)
char *insname;
char *locname;
char *newname;
{
phfig_list *ptnewfig;
phins_list *ptins;
phseg_list *ptseg;
long x1, x2, y1, y2;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("COPY_UP_SEG impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	ptins = getphins(WORK_PHFIG, insname);
	ptnewfig = getphfig(ptins->FIGNAME, 'A');
	locname = namealloc(checkname(locname));

	for (ptseg = ptnewfig->PHSEG; ptseg; ptseg = ptseg->NEXT) {
		if (ptseg->NAME == locname)
			break;
	}
	if (ptseg == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nCOPY_UP_SEG impossible :", stderr);
		(void)fprintf(stderr, " segment %s doesn't exist in instance %s\n",
							locname, insname);
		EXIT(1);
	}

	/*  create segment  */
	xyflat(&x1, &y1, ptseg->X1, ptseg->Y1, ptins->XINS, ptins->YINS,
	        ptnewfig->XAB1, ptnewfig->YAB1, ptnewfig->XAB2, ptnewfig->YAB2,
	        ptins->TRANSF);
	xyflat(&x2, &y2, ptseg->X2, ptseg->Y2, ptins->XINS, ptins->YINS,
	        ptnewfig->XAB1, ptnewfig->YAB1, ptnewfig->XAB2, ptnewfig->YAB2,
	        ptins->TRANSF);
	return addphseg(WORK_PHFIG, ptseg->LAYER, ptseg->WIDTH, x1, y1,
	     x2, y2, checkname(newname));
}

/*******************************************************************************
* function  THRU_H                                                             *
*******************************************************************************/
phseg_list *genTHRU_H(layer, width, y)
char	layer;
long	width, y;
{
long	x1, x2;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("THRU_H impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	x1 = WORK_PHFIG->XAB1;
	x2 = WORK_PHFIG->XAB2;
	if (x1 == 0 && WORK_PHFIG->YAB1 == 0 && x2 == 0 && WORK_PHFIG->YAB2 == 0) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("THRU_H impossible : missing DEF_AB\n", stderr);
		EXIT(1);
	}
	return addphseg(WORK_PHFIG, layer, width, x1, y, x2, y, (char *)NULL);
}

/*******************************************************************************
* function  THRU_V                                                             *
*******************************************************************************/
phseg_list *genTHRU_V(layer, width, x)
char	layer;
long	width, x;
{
long	y1, y2;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("THRU_V impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	y1 = WORK_PHFIG->YAB1;
	y2 = WORK_PHFIG->YAB2;
	if (y1 == 0 && WORK_PHFIG->XAB1 == 0 && y2 == 0 && WORK_PHFIG->XAB2 == 0) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("THRU_V impossible : missing DEF_AB\n", stderr);
		EXIT(1);
	}
	return addphseg(WORK_PHFIG, layer, width, x, y1, x, y2, (char *)NULL);
}

/*******************************************************************************
* function  THRU_CON_H                                                         *
*******************************************************************************/
chain_list *genTHRU_CON_H(layer, width , name, y)
char layer;
char *name;
long width, y;
{
long x1, x2;
chain_list *ptchain = NULL;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("THRU_CON_H impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	x1 = WORK_PHFIG->XAB1;
	x2 = WORK_PHFIG->XAB2;
	if (x1 == 0 && WORK_PHFIG->YAB1 == 0 && x2 == 0 && WORK_PHFIG->YAB2 == 0) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("THRU_CON_H impossible : missing DEF_AB\n", stderr);
		EXIT(1);
	}
	ptchain = addchain(ptchain,  (void *)addphcon(WORK_PHFIG, WEST,
	     checkname(name), x1, y, layer, width));
	ptchain = addchain(ptchain,  (void *)addphcon(WORK_PHFIG, EAST,
	     checkname(name), x2, y, layer, width));
	ptchain = addchain(ptchain,  (void *)addphseg(WORK_PHFIG, layer,
	     width, x1, y, x2, y, checkname(name)));
	return ptchain;
}

/*******************************************************************************
* function  THRU_CON_V                                                         *
*******************************************************************************/
chain_list *genTHRU_CON_V(layer, width, name, x)
char layer;
char *name;
long width, x;
{
long y1, y2;
chain_list *ptchain = NULL;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("THRU_CON_V impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	y1 = WORK_PHFIG->YAB1;
	y2 = WORK_PHFIG->YAB2;
	if (y1 == 0 && WORK_PHFIG->XAB1 == 0 && y2 == 0 && WORK_PHFIG->XAB2 == 0) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("THRU_CON_V impossible : missing DEF_AB\n", stderr);
		EXIT(1);
	}
	ptchain = addchain(ptchain, (void *)addphcon(WORK_PHFIG, SOUTH,
	     checkname(name), x, y1, layer, width));
	ptchain = addchain(ptchain, (void *)addphcon(WORK_PHFIG, NORTH,
	     checkname(name), x, y2, layer, width));
	ptchain = addchain(ptchain, (void *)addphseg(WORK_PHFIG, layer,
	     width, x, y1, x, y2, checkname(name)));
	return ptchain;
}

/*******************************************************************************
* function WIRE1                                                               *
*******************************************************************************/
chain_list *genWIRE1(layer, width, ins1, con1, index1, ins2, con2, index2)
char layer;
long width;
char *ins1, *ins2, *con1, *con2;
long index1, index2;
{
long xcon1,ycon1, xcon2, ycon2; /* connexion coordinates */
phcon_list *ptcon; /* scanning cons since getphcon exits if not present */
phref_list *ptref; /* scanning refs since getphref exits if not present */
phins_list *ptins;
phfig_list *ptfig;

	con1 = namealloc(checkname(con1));
	ptins = getphins(WORK_PHFIG, ins1);
	ptfig = getphfig(ptins->FIGNAME, 'P');
	for (ptcon = ptfig->PHCON; ptcon != NULL; ptcon = ptcon->NEXT)
		if (ptcon->NAME == con1 && ptcon->INDEX == index1) {
			xcon1 = ptcon->XCON;
			ycon1 = ptcon->YCON;
			break;
		}
	for (ptref = ptfig->PHREF; ptref != NULL; ptref = ptref->NEXT)
		if (ptref->NAME == con1) {
			xcon1 = ptref->XREF;
			ycon1 = ptref->YREF;
			break;
		}
	if (ptref != NULL && ptcon != NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("WIRE1 same name for reference and", stderr);
		(void)fprintf(stderr, " connector '%s' in figure '%s'\n",
		              ptcon->NAME, ptfig->NAME);
		EXIT(1);
	}
	if (ptref == NULL && ptcon == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nWIRE1 reference or", stderr);
		(void)fprintf(stderr, " connector '%s' does not exist in figure '%s'\n",
		              con1, ptfig->NAME);
		EXIT(1);
	}
	xyflat(&xcon1, &ycon1, xcon1, ycon1, ptins->XINS, ptins->YINS,
	    ptfig->XAB1, ptfig->YAB1, ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);
	con2 = namealloc(checkname(con2));
	ptins = getphins(WORK_PHFIG, ins2);
	ptfig = getphfig(ptins->FIGNAME, 'P');
	for (ptcon = ptfig->PHCON; ptcon != NULL; ptcon = ptcon->NEXT)
		if (ptcon->NAME == con2 && ptcon->INDEX == index2) {
			xcon2 = ptcon->XCON;
			ycon2 = ptcon->YCON;
			break;
		}
	for (ptref = ptfig->PHREF; ptref != NULL; ptref = ptref->NEXT)
		if (ptref->NAME == con2) {
			xcon2 = ptref->XREF;
			ycon2 = ptref->YREF;
			break;
		}
	if (ptref != NULL && ptcon != NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("WIRE1 same name for reference and", stderr);
		(void)fprintf(stderr, " connector '%s' in figure '%s'\n",
		              ptcon->NAME, ptfig->NAME);
		EXIT(1);
	}
	if (ptref == NULL && ptcon == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nWIRE1 reference or", stderr);
		(void)fprintf(stderr, " connector '%s' does not exist in figure '%s'\n",
		              con2, ptfig->NAME);
		EXIT(1);
	}
	xyflat(&xcon2, &ycon2, xcon2, ycon2, ptins->XINS, ptins->YINS,
	    ptfig->XAB1, ptfig->YAB1, ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);

	return addchain((chain_list *)NULL, (void *)addphseg(WORK_PHFIG,
	     layer,  width, xcon1, ycon1, xcon2, ycon2, (char *)NULL));
}

/*******************************************************************************
* function WIRE2                                                               *
*******************************************************************************/
chain_list *genWIRE2(layer, width, ins1, con1, index1, ins2, con2, index2,
 x, y)
char layer;
long width, x, y;
char *ins1, *ins2, *con1, *con2;
long index1, index2;
{
long xcon1, ycon1, xcon2, ycon2; /* connexion coordinates */
phcon_list *ptcon; /* scanning cons since getphcon exits if not present */
phref_list *ptref; /* scanning refs since getphref exits if not present */
phins_list *ptins;
phfig_list *ptfig;
chain_list *ptchain = NULL; /* return pointers on created segments */

	con1 = namealloc(checkname(con1));
	ptins = getphins(WORK_PHFIG, ins1);
	ptfig = getphfig(ptins->FIGNAME, 'P');
	for (ptcon = ptfig->PHCON; ptcon != NULL; ptcon = ptcon->NEXT)
		if (ptcon->NAME == con1 && ptcon->INDEX == index1) {
			xcon1 = ptcon->XCON;
			ycon1 = ptcon->YCON;
			break;
		}
	for (ptref = ptfig->PHREF; ptref != NULL; ptref = ptref->NEXT)
		if (ptref->NAME == con1) {
			xcon1 = ptref->XREF;
			ycon1 = ptref->YREF;
			break;
		}
	if (ptref != NULL && ptcon != NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("WIRE2 same name for reference and", stderr);
		(void)fprintf(stderr, " connector '%s' in figure '%s'\n",
		              ptcon->NAME, ptfig->NAME);
		EXIT(1);
	}
	if (ptref == NULL && ptcon == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nWIRE2 reference or", stderr);
		(void)fprintf(stderr, " connector '%s' does not exist in figure '%s'\n",
		              con1, ptfig->NAME);
		EXIT(1);
	}
	xyflat(&xcon1, &ycon1, xcon1, ycon1, ptins->XINS, ptins->YINS,
	    ptfig->XAB1, ptfig->YAB1, ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);
	con2 = namealloc(checkname(con2));
	ptins = getphins(WORK_PHFIG, ins2);
	ptfig = getphfig(ptins->FIGNAME, 'P');
	for (ptcon = ptfig->PHCON; ptcon != NULL; ptcon = ptcon->NEXT)
		if (ptcon->NAME == con2 && ptcon->INDEX == index2) {
			xcon2 = ptcon->XCON;
			ycon2 = ptcon->YCON;
			break;
		}
	for (ptref = ptfig->PHREF; ptref != NULL; ptref = ptref->NEXT)
		if (ptref->NAME == con2) {
			xcon2 = ptref->XREF;
			ycon2 = ptref->YREF;
			break;
		}
	if (ptref != NULL && ptcon != NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("WIRE2 same name for reference and", stderr);
		(void)fprintf(stderr, " connector '%s' in figure '%s'\n",
		              ptcon->NAME, ptfig->NAME);
		EXIT(1);
	}
	if (ptref == NULL && ptcon == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nWIRE2 reference or", stderr);
		(void)fprintf(stderr, " connector '%s' does not exist in figure '%s'\n",
		              con2, ptfig->NAME);
		EXIT(1);
	}
	xyflat(&xcon2, &ycon2, xcon2, ycon2, ptins->XINS, ptins->YINS,
	    ptfig->XAB1, ptfig->YAB1, ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);

	ptchain = addchain(ptchain, (void *)addphseg(WORK_PHFIG, layer,
	      width, xcon1, ycon1, x, y, (char *)NULL));
	ptchain = addchain(ptchain, (void *)addphseg(WORK_PHFIG, layer,
	      width, xcon2, ycon2, x, y, (char *)NULL));
	return ptchain;
}

/*******************************************************************************
* function WIRE3                                                               *
*******************************************************************************/
chain_list *genWIRE3(layer, width, ins1, con1, index1, ins2, con2, index2,
x1, y1, x2, y2)
char layer;
long width, x1, y1, x2, y2;
char *ins1, *ins2, *con1, *con2;
long index1, index2;
{
long xcon1, ycon1, xcon2, ycon2; /* connexion coordinates */
phcon_list *ptcon; /* scanning cons since getphcon exits if not present */
phref_list *ptref; /* scanning refs since getphref exits if not present */
phins_list *ptins;
phfig_list *ptfig;
chain_list *ptchain = NULL; /* return values : pointer on created segments */

	con1 = namealloc(checkname(con1));
	ptins = getphins(WORK_PHFIG, ins1);
	ptfig = getphfig(ptins->FIGNAME, 'P');
	for (ptcon = ptfig->PHCON; ptcon != NULL; ptcon = ptcon->NEXT)
		if (ptcon->NAME == con1 && ptcon->INDEX == index1) {
			xcon1 = ptcon->XCON;
			ycon1 = ptcon->YCON;
			break;
		}
	for (ptref = ptfig->PHREF; ptref != NULL; ptref = ptref->NEXT)
		if (ptref->NAME == con1) {
			xcon1 = ptref->XREF;
			ycon1 = ptref->YREF;
			break;
		}
	if (ptref != NULL && ptcon != NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("WIRE3 same name for reference and", stderr);
		(void)fprintf(stderr, " connector '%s' in figure '%s'\n",
		              ptcon->NAME, ptfig->NAME);
		EXIT(1);
	}
	if (ptref == NULL && ptcon == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nWIRE3 reference or", stderr);
		(void)fprintf(stderr, " connector '%s' does not exist in figure '%s'\n",
		              con1, ptfig->NAME);
		EXIT(1);
	}
	xyflat(&xcon1, &ycon1, xcon1, ycon1, ptins->XINS, ptins->YINS,
	    ptfig->XAB1, ptfig->YAB1, ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);
	con2 = namealloc(checkname(con2));
	ptins = getphins(WORK_PHFIG, ins2);
	ptfig = getphfig(ptins->FIGNAME, 'P');
	for (ptcon = ptfig->PHCON; ptcon != NULL; ptcon = ptcon->NEXT)
		if (ptcon->NAME == con2 && ptcon->INDEX == index2) {
			xcon2 = ptcon->XCON;
			ycon2 = ptcon->YCON;
			break;
		}
	for (ptref = ptfig->PHREF; ptref != NULL; ptref = ptref->NEXT)
		if (ptref->NAME == con2) {
			xcon2 = ptref->XREF;
			ycon2 = ptref->YREF;
			break;
		}
	if (ptref != NULL && ptcon != NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("WIRE3 same name for reference and", stderr);
		(void)fprintf(stderr, " connector '%s' in figure '%s'\n",
		              ptcon->NAME, ptfig->NAME);
		EXIT(1);
	}
	if (ptref == NULL && ptcon == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nWIRE3 reference or", stderr);
		(void)fprintf(stderr, " connector '%s' does not exist in figure '%s'\n",
		            con2, ptfig->NAME);
		EXIT(1);
	}
	xyflat(&xcon2, &ycon2, xcon2, ycon2, ptins->XINS, ptins->YINS,
	    ptfig->XAB1, ptfig->YAB1, ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);
	ptchain = addchain(ptchain, (void *)addphseg(WORK_PHFIG, layer,
	      width, xcon1, ycon1, x1, y1, (char *)NULL));
	ptchain = addchain(ptchain, (void *)addphseg(WORK_PHFIG, layer,
	      width, x2, y2,  x1, y1, (char *)NULL));
	ptchain = addchain(ptchain, (void *)addphseg(WORK_PHFIG, layer,
	      width, xcon2, ycon2, x2, y2, (char *)NULL));
	return ptchain;
}

/*******************************************************************************
* function  PHVIA                                                              *
*******************************************************************************/
phvia_list *genPHVIA(type, x, y)
char	type;
long	x, y;
{
	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PHVIA impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	return addphvia(WORK_PHFIG, type, x, y);
}

/*******************************************************************************
* function  PLACE                                                              *
*******************************************************************************/
void genPLACE(figname, insname, sym, x, y)
char *figname;
char *insname;
int sym;
long x, y;
{
phfig_list *ptfig;
long deltax, deltay;
num_list *ptnum;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	WORK_PHINS = addphins(WORK_PHFIG, figname, insname, sym, x, y);
	ptfig = getphfig(figname, 'P');
	if (sym == NOSYM || sym == SYM_X || sym == SYM_Y || sym == SYMXY) {
		deltax = x + ptfig->XAB2 - ptfig->XAB1;
		deltay = y + ptfig->YAB2 - ptfig->YAB1;
	}
	if (sym == ROT_P || sym == ROT_M || sym == SY_RP || sym == SY_RM) {
		deltax = x + ptfig->YAB2 - ptfig->YAB1;
		deltay = y + ptfig->XAB2 - ptfig->XAB1;
	}
	ptnum = addnum((num_list *)NULL, deltay);
	ptnum = addnum(ptnum, deltax);
	WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
	    (void *)ptnum);
}

/*******************************************************************************
* function  PLACE_RIGHT                                                        *
*******************************************************************************/
void genPLACE_RIGHT(figname, insname, sym)
char *figname;
char *insname;
int sym;
{
long x, y;
long deltax, deltay;
char trsf;
phfig_list *ptfig = NULL;
ptype_list *ptype = NULL;
num_list *ptnum = NULL;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_RIGHT impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_PHINS == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_RIGHT impossible : no previous instance ", stderr);
		(void)fprintf(stderr, "in figure %s\n", WORK_PHFIG->NAME);
		EXIT(1);
	}
	ptype = getptype(WORK_PHINS->USER, (long)PLACEABOX);
	if (ptype == NULL) {
		ptfig = getphfig(WORK_PHINS->FIGNAME, 'P');
		trsf = WORK_PHINS->TRANSF;
		if (trsf == NOSYM || trsf == SYM_X || trsf == SYM_Y || trsf == SYMXY) {
			deltax = WORK_PHINS->XINS + ptfig->XAB2 - ptfig->XAB1;
			deltay = WORK_PHINS->YINS + ptfig->YAB2 - ptfig->YAB1;
		}
		if (trsf == ROT_P || trsf == ROT_M || trsf == SY_RP || trsf == SY_RM) {
			deltax = WORK_PHINS->XINS + ptfig->YAB2 - ptfig->YAB1;
			deltay = WORK_PHINS->YINS + ptfig->XAB2 - ptfig->XAB1;
		}
		ptnum = addnum((num_list *)NULL, deltay);
		ptnum = addnum(ptnum, deltax);
		WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
		     (void *)ptnum);
		ptype = WORK_PHINS->USER;
	}
	x = ((num_list *)(ptype->DATA))->DATA;
	y = WORK_PHINS->YINS;

	WORK_PHINS = addphins(WORK_PHFIG, figname, insname, sym, x, y);
	ptfig = getphfig(figname, 'P');
	if (sym == NOSYM || sym == SYM_X || sym == SYM_Y || sym == SYMXY) {
		deltax = x + ptfig->XAB2 - ptfig->XAB1;
		deltay = y + ptfig->YAB2 - ptfig->YAB1;
	}
	if (sym == ROT_P || sym == ROT_M || sym == SY_RP || sym == SY_RM) {
		deltax = x + ptfig->YAB2 - ptfig->YAB1;
		deltay = y + ptfig->XAB2 - ptfig->XAB1;
	}
	ptnum = addnum((num_list *)NULL, deltay);
	ptnum = addnum(ptnum, deltax);
	WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
	    (void *)ptnum);
}

/*******************************************************************************
* function  PLACE_TOP                                                          *
*******************************************************************************/
void genPLACE_TOP(figname, insname, sym)
char *figname;
char *insname;
int sym;
{
long x, y;
long deltax, deltay;
char trsf;
phfig_list *ptfig = NULL;
ptype_list *ptype = NULL;
num_list *ptnum = NULL;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_TOP impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_PHINS == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_TOP impossible : no previous instance ", stderr);
		(void)fprintf(stderr, "in figure %s\n", WORK_PHFIG->NAME);
		EXIT(1);
	}
	ptype = getptype(WORK_PHINS->USER, (long)PLACEABOX);
	if (ptype == NULL) {
		ptfig = getphfig(WORK_PHINS->FIGNAME, 'P');
		trsf = WORK_PHINS->TRANSF;
		if (trsf == NOSYM || trsf == SYM_X || trsf == SYM_Y || trsf == SYMXY) {
			deltax = WORK_PHINS->XINS + ptfig->XAB2 - ptfig->XAB1;
			deltay = WORK_PHINS->YINS + ptfig->YAB2 - ptfig->YAB1;
		}
		if (trsf == ROT_P || trsf == ROT_M || trsf == SY_RP || trsf == SY_RM) {
			deltax = WORK_PHINS->XINS + ptfig->YAB2 - ptfig->YAB1;
			deltay = WORK_PHINS->YINS + ptfig->XAB2 - ptfig->XAB1;
		}
		ptnum = addnum((num_list *)NULL, deltay);
		ptnum = addnum(ptnum, deltax);
		WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
		     (void *)ptnum);
		ptype = WORK_PHINS->USER;
	}
	y = ((num_list *)(ptype->DATA))->NEXT->DATA;
	x = WORK_PHINS->XINS;
	WORK_PHINS = addphins(WORK_PHFIG, figname, insname, sym, x, y);

	ptfig = getphfig(figname, 'P');
	if (sym == NOSYM || sym == SYM_X || sym == SYM_Y || sym == SYMXY) {
		deltax = x + ptfig->XAB2 - ptfig->XAB1;
		deltay = y + ptfig->YAB2 - ptfig->YAB1;
	}
	if (sym == ROT_P || sym == ROT_M || sym == SY_RP || sym == SY_RM) {
		deltax = x + ptfig->YAB2 - ptfig->YAB1;
		deltay = y + ptfig->XAB2 - ptfig->XAB1;
	}
	ptnum = addnum((num_list *)NULL, deltay);
	ptnum = addnum(ptnum, deltax);
	WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
	    (void *)ptnum);
}

/*******************************************************************************
* function  PLACE_LEFT                                                         *
*******************************************************************************/
void genPLACE_LEFT(figname, insname, sym)
char *figname;
char *insname;
int sym;
{
long x, y;
long deltax, deltay;
char trsf;
phfig_list *ptfig = NULL;
ptype_list *ptype = NULL;
num_list *ptnum = NULL;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_LEFT impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_PHINS == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_LEFT impossible : no previous instance ", stderr);
		(void)fprintf(stderr, "in figure %s\n", WORK_PHFIG->NAME);
		EXIT(1);
	}
	ptype = getptype(WORK_PHINS->USER, (long)PLACEABOX);
	if (ptype == NULL) {
		ptfig = getphfig(WORK_PHINS->FIGNAME, 'P');
		trsf = WORK_PHINS->TRANSF;
		if (trsf == NOSYM || trsf == SYM_X || trsf == SYM_Y || trsf == SYMXY) {
			deltax = WORK_PHINS->XINS + ptfig->XAB2 - ptfig->XAB1;
			deltay = WORK_PHINS->YINS + ptfig->YAB2 - ptfig->YAB1;
		}
		if (trsf == ROT_P || trsf == ROT_M || trsf == SY_RP || trsf == SY_RM) {
			deltax = WORK_PHINS->XINS + ptfig->YAB2 - ptfig->YAB1;
			deltay = WORK_PHINS->YINS + ptfig->XAB2 - ptfig->XAB1;
		}
		ptnum = addnum((num_list *)NULL, deltay);
		ptnum = addnum(ptnum, deltax);
		WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
		     (void *)ptnum);
	}
	ptfig = getphfig(figname, 'P');
	if (sym == NOSYM || sym == SYM_X || sym == SYM_Y || sym == SYMXY) {
		deltax = ptfig->XAB2 - ptfig->XAB1;
		deltay = ptfig->YAB2 - ptfig->YAB1;
	}
	if (sym == ROT_P || sym == ROT_M || sym == SY_RP || sym == SY_RM) {
		deltax = ptfig->YAB2 - ptfig->YAB1;
		deltay = ptfig->XAB2 - ptfig->XAB1;
	}
	x = WORK_PHINS->XINS - deltax;
	y = WORK_PHINS->YINS;
	WORK_PHINS = addphins(WORK_PHFIG, figname, insname, sym, x, y);
	ptnum = addnum((num_list *)NULL, y + deltay);
	ptnum = addnum(ptnum, x + deltax);
	WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
	    (void *)ptnum);
}

/*******************************************************************************
* function  PLACE_BOTTOM                                                       *
*******************************************************************************/
void genPLACE_BOTTOM(figname, insname, sym)
char *figname;
char *insname;
int sym;
{
long x, y;
long deltax, deltay;
char trsf;
phfig_list *ptfig = NULL;
ptype_list *ptype = NULL;
num_list *ptnum = NULL;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_BOTTOM impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_PHINS == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_BOTTOM impossible : no previous instance ", stderr);
		(void)fprintf(stderr, "in figure %s\n", WORK_PHFIG->NAME);
		EXIT(1);
	}
	ptype = getptype(WORK_PHINS->USER, (long)PLACEABOX);
	if (ptype == NULL) {
		ptfig = getphfig(WORK_PHINS->FIGNAME, 'P');
		trsf = WORK_PHINS->TRANSF;
		if (trsf == NOSYM || trsf == SYM_X || trsf == SYM_Y || trsf == SYMXY) {
			deltax = WORK_PHINS->XINS + ptfig->XAB2 - ptfig->XAB1;
			deltay = WORK_PHINS->YINS + ptfig->YAB2 - ptfig->YAB1;
		}
		if (trsf == ROT_P || trsf == ROT_M || trsf == SY_RP || trsf == SY_RM) {
			deltax = WORK_PHINS->XINS + ptfig->YAB2 - ptfig->YAB1;
			deltay = WORK_PHINS->YINS + ptfig->XAB2 - ptfig->XAB1;
		}
		ptnum = addnum((num_list *)NULL, deltay);
		ptnum = addnum(ptnum, deltax);
		WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
		     (void *)ptnum);
	}
	ptfig = getphfig(figname, 'P');
	if (sym == NOSYM || sym == SYM_X || sym == SYM_Y || sym == SYMXY) {
		deltax = ptfig->XAB2 - ptfig->XAB1;
		deltay = ptfig->YAB2 - ptfig->YAB1;
	}
	if (sym == ROT_P || sym == ROT_M || sym == SY_RP || sym == SY_RM) {
		deltax = ptfig->YAB2 - ptfig->YAB1;
		deltay = ptfig->XAB2 - ptfig->XAB1;
	}
	x = WORK_PHINS->XINS;
	y = WORK_PHINS->YINS - deltay;
	WORK_PHINS = addphins(WORK_PHFIG, figname, insname, sym, x, y);
	ptnum = addnum((num_list *)NULL, y + deltay);
	ptnum = addnum(ptnum, x + deltax);
	WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
	    (void *)ptnum);
}

/*******************************************************************************
* function  PLACE_REF                                                          *
*******************************************************************************/
void genPLACE_REF(figname, insname, sym, insref, refname)
char *figname;
char *insname;
char *insref;
char *refname;
int sym;
{
long x, y;
long deltax, deltay;
char trsf;
phfig_list *ptfig = NULL;
phins_list *ptins = NULL;
phref_list *ptref = NULL;
ptype_list *ptype = NULL;
num_list *ptnum = NULL;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_REF impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_PHINS == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_REF impossible : no previous instance ", stderr);
		(void)fprintf(stderr, "in figure %s\n", WORK_PHFIG->NAME);
		EXIT(1);
	}
	ptype = getptype(WORK_PHINS->USER, (long)PLACEABOX);
	if (ptype == NULL) {
		ptfig = getphfig(WORK_PHINS->FIGNAME, 'P');
		trsf = WORK_PHINS->TRANSF;
		if (trsf == NOSYM || trsf == SYM_X || trsf == SYM_Y || trsf == SYMXY) {
			deltax = WORK_PHINS->XINS + ptfig->XAB2 - ptfig->XAB1;
			deltay = WORK_PHINS->YINS + ptfig->YAB2 - ptfig->YAB1;
		}
		if (trsf == ROT_P || trsf == ROT_M || trsf == SY_RP || trsf == SY_RM) {
			deltax = WORK_PHINS->XINS + ptfig->YAB2 - ptfig->YAB1;
			deltay = WORK_PHINS->YINS + ptfig->XAB2 - ptfig->XAB1;
		}
		ptnum = addnum((num_list *)NULL, deltay);
		ptnum = addnum(ptnum, deltax);
		WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
		     (void *)ptnum);
	}
	ptins = getphins(WORK_PHFIG, insref);
	ptfig = getphfig(ptins->FIGNAME, 'A');
	ptref = getphref(ptfig, checkname(refname));
	xyflat(&x, &y, ptref->XREF, ptref->YREF, ptins->XINS, ptins->YINS,
	      ptfig->XAB1, ptfig->YAB1, ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);
	WORK_PHINS = addphins(WORK_PHFIG, figname, insname, sym, x, y);

	ptfig = getphfig(figname, 'P');
	if (sym == NOSYM || sym == SYM_X || sym == SYM_Y || sym == SYMXY) {
		deltax = x + ptfig->XAB2 - ptfig->XAB1;
		deltay = y + ptfig->YAB2 - ptfig->YAB1;
	}
	if (sym == ROT_P || sym == ROT_M || sym == SY_RP || sym == SY_RM) {
		deltax = x + ptfig->YAB2 - ptfig->YAB1;
		deltay = y + ptfig->XAB2 - ptfig->XAB1;
	}
	ptnum = addnum((num_list *)NULL, deltay);
	ptnum = addnum(ptnum, deltax);
	WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
	    (void *)ptnum);
}

/*******************************************************************************
* function  PLACE_ON                                                           *
*******************************************************************************/
void genPLACE_ON(figname, insname1, con1, index1, sym, insname2, con2,
index2)
char *figname;
char *insname1, *insname2, *con1, *con2;
int sym;
long index1, index2;
{
long x, y, x1, y1, x2, y2;
long xrc1, yrc1, xrc2, yrc2;
long deltax, deltay;
char trsf;
phfig_list *ptfig = NULL;
ptype_list *ptype = NULL;
num_list *ptnum = NULL;
phins_list *ptins;
phcon_list *ptcon;
phref_list *ptref;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_ON impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_PHINS == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_ON impossible : no previous instance ", stderr);
		(void)fprintf(stderr, "in figure %s\n", WORK_PHFIG->NAME);
		EXIT(1);
	}
	ptins = getphins(WORK_PHFIG, insname2);
	ptype = getptype(ptins->USER, (long)PLACEABOX);
	if (ptype == NULL) {
		ptfig = getphfig(ptins->FIGNAME, 'P');
		trsf = ptins->TRANSF;
		if (trsf == NOSYM || trsf == SYM_X || trsf == SYM_Y || trsf == SYMXY) {
			deltax = ptins->XINS + ptfig->XAB2 - ptfig->XAB1;
			deltay = ptins->YINS + ptfig->YAB2 - ptfig->YAB1;
		}
		if (trsf == ROT_P || trsf == ROT_M || trsf == SY_RP || trsf == SY_RM) {
			deltax = ptins->XINS + ptfig->YAB2 - ptfig->YAB1;
			deltay = ptins->YINS + ptfig->XAB2 - ptfig->XAB1;
		}
		ptnum = addnum((num_list *)NULL, deltay);
		ptnum = addnum(ptnum, deltax);
		ptins->USER = addptype(ptins->USER, (long)PLACEABOX, (void *)ptnum);
		ptype = ptins->USER;
	}

	ptfig = getphfig(ptins->FIGNAME, 'P');
	con2 = namealloc(checkname(con2));
	for (ptcon = ptfig->PHCON; ptcon != NULL; ptcon = ptcon->NEXT)
		if (ptcon->NAME == con2 && ptcon->INDEX == index2) {
			xrc2 = ptcon->XCON;
			yrc2 = ptcon->YCON;
			break;
		}
	for (ptref = ptfig->PHREF; ptref != NULL; ptref = ptref->NEXT)
		if (ptref->NAME == con2) {
			xrc2 = ptref->XREF;
			yrc2 = ptref->YREF;
			break;
		}
	if (ptref != NULL && ptcon != NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nPLACE_ON : same name for ", stderr);
		(void)fprintf(stderr, "reference and connector '%s' in figure '%s'\n",
		                   con2, ptfig->NAME);
		EXIT(1);
	}
	if (ptref == NULL && ptcon == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nPLACE_ON : reference or", stderr);
		(void)fprintf(stderr, " connector '%s' does not exist in figure '%s'\n",
		                   con2, ptfig->NAME);
		EXIT(1);
	}
	xyflat(&x2, &y2, xrc2, yrc2, ptins->XINS, ptins->YINS, ptfig->XAB1,
	     ptfig->YAB1, ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);
	ptfig = getphfig(figname, 'P');
	con1 = namealloc(checkname(con1));
	for (ptcon = ptfig->PHCON; ptcon != NULL; ptcon = ptcon->NEXT)
		if (ptcon->NAME == con1 && ptcon->INDEX == index1) {
			xrc1 = ptcon->XCON;
			yrc1 = ptcon->YCON;
			break;
		}
	for (ptref = ptfig->PHREF; ptref != NULL; ptref = ptref->NEXT)
		if (ptref->NAME == con1) {
			xrc1 = ptref->XREF;
			yrc1 = ptref->YREF;
			break;
		}
	if (ptref != NULL && ptcon != NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nPLACE_ON : same name for ", stderr);
		(void)fprintf(stderr, "reference and connector '%s' in figure '%s'\n",
		                   con1, ptfig->NAME);
		EXIT(1);
	}
	if (ptref == NULL && ptcon == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nPLACE_ON : reference or", stderr);
		(void)fprintf(stderr, " connector '%s' does not exist in figure '%s'\n",
		                   con1, ptfig->NAME);
		EXIT(1);
	}
	xyflat(&x1, &y1, xrc1, yrc1, 0L, 0L, ptfig->XAB1, ptfig->YAB1,
	    ptfig->XAB2, ptfig->YAB2, sym);

	if (sym == NOSYM || sym == SYM_X || sym == SYM_Y || sym == SYMXY) {
		deltax = ptfig->XAB2 - ptfig->XAB1;
		deltay = ptfig->YAB2 - ptfig->YAB1;
	}
	if (sym == ROT_P || sym == ROT_M || sym == SY_RP || sym == SY_RM) {
		deltax = ptfig->YAB2 - ptfig->YAB1;
		deltay = ptfig->XAB2 - ptfig->XAB1;
	}

	x = x2 - x1;
	y = y2 - y1;

	ptnum = addnum((num_list *)NULL, y + deltay);
	ptnum = addnum(ptnum, x + deltax);

	WORK_PHINS = addphins(WORK_PHFIG, figname, insname1, sym, x, y);

	WORK_PHINS->USER = addptype(WORK_PHINS->USER, (long)PLACEABOX,
	    (void *)ptnum);
}

/*******************************************************************************
* function HEIGHT                                                              *
*******************************************************************************/
long genHEIGHT(cellName)
char *cellName;
{
phfig_list *pf;

	pf = getphfig(cellName, 'P');
	return pf->YAB2 - pf->YAB1;
}

/*******************************************************************************
* function WIDTH                                                               *
*******************************************************************************/
long genWIDTH(cellName)
char *cellName;
{
phfig_list *pf;

	pf = getphfig(cellName, 'P');
	return pf->XAB2 - pf->XAB1;
}

/*******************************************************************************
* function  GET_INS_X                                                          *
*******************************************************************************/
long genGET_INS_X(insname)
char *insname;
{
	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("Illegal GET_INS_X : No DEF_PHFIG\n", stderr);
		EXIT(1);
	}

	return getphins(WORK_PHFIG, insname)->XINS;
}

/*******************************************************************************
* function  GET_INS_Y                                                          *
*******************************************************************************/
long genGET_INS_Y(insname)
char *insname;
{
	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("Illegal GET_INS_X : No DEF_PHFIG\n", stderr);
		EXIT(1);
	}

	return getphins(WORK_PHFIG, insname)->YINS;
}

/*******************************************************************************
* function FLATTEN_PHFIG                                                       *
*******************************************************************************/
void genFLATTEN_PHFIG(insname, concat)
char *insname;
char concat;
{
	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("FLATTEN_PHFIG impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	flattenphfig(WORK_PHFIG, insname, concat);
}

/*******************************************************************************
* function FLATTEN_ALL_PHINS                                                   *
*******************************************************************************/
void genFLATTEN_ALL_PHINS(concat, catal)
char concat, catal;
{
chain_list *c, *namelist = NULL;
phins_list *l;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("Illegal FLATTEN_ALL_PHINS : No DEF_PHFIG\n", stderr);
		EXIT(1);
	}

	for (l = WORK_PHFIG->PHINS; l; l = l->NEXT)
		if (catal == NO || !incatalog(l->FIGNAME))
			namelist = addchain(namelist, (void *)l->INSNAME);

	for (c = namelist; c; c = c->NEXT)
		flattenphfig(WORK_PHFIG, (char *)c->DATA, concat);

	freechain(namelist);
}

/*******************************************************************************
* function  PHREF                                                              *
*******************************************************************************/
phref_list *genPHREF(type, name, x, y)
char *type;
char *name;
long x, y;
{
	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PHREF impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	return addphref(WORK_PHFIG, type, checkname(name), x, y);
}

/*******************************************************************************
* function  COPY_UP_REF                                                        *
*******************************************************************************/
phref_list *genCOPY_UP_REF(refname, insname, newname)
char *refname;
char *insname;
char *newname;
{
phfig_list *ptnewfig;
phins_list *ptins;
phref_list *ptref;
long x, y;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("COPY_UP_REF impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	ptins = getphins(WORK_PHFIG, insname);
	ptnewfig = getphfig(ptins->FIGNAME, 'A');
	ptref = getphref(ptnewfig, checkname(refname));

	/*  create reference  */
	xyflat(&x, &y, ptref->XREF, ptref->YREF, ptins->XINS, ptins->YINS,
	      ptnewfig->XAB1, ptnewfig->YAB1, ptnewfig->XAB2, ptnewfig->YAB2,
	      ptins->TRANSF);
	return addphref(WORK_PHFIG, ptref->FIGNAME, checkname(newname), x, y);
}

/*******************************************************************************
* function  COPY_UP_ALL_REF                                                    *
*******************************************************************************/
chain_list *genCOPY_UP_ALL_REF(reftype, insname, cheminom)
char *reftype;
char *insname;
char cheminom;
{
phfig_list *newfig;
phins_list *ins;
phref_list *ref;
chain_list *refs = NULL;
long x, y;
char *ref_;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("COPY_UP_ALL_REF impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if ((WORK_PHFIG->XAB1 | WORK_PHFIG->YAB1 | WORK_PHFIG->XAB2
			| WORK_PHFIG->YAB2) == 0) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs(" COPY_UP_ALL_REF impossible : missing DEF_AB ", stderr);
		(void)fprintf(stderr, "on figure %s\n", WORK_PHFIG->NAME);
		EXIT(1);
	}

	ins = getphins(WORK_PHFIG, insname);
	newfig = getphfig(ins->FIGNAME, 'P');
	reftype = namealloc(reftype);

	for (ref = newfig->PHREF; ref != NULL; ref = ref->NEXT) {
		ref_ = ref->FIGNAME;
		if (ref_ != reftype)
			continue;
		xyflat(&x, &y, ref->XREF, ref->YREF, ins->XINS, ins->YINS,
		            newfig->XAB1, newfig->YAB1, newfig->XAB2, newfig->YAB2,
		     ins->TRANSF);
		refs = addchain(refs, (void *)addphref(WORK_PHFIG, ref_,
		            cheminom == 'Y' ? concatname(insname, ref->NAME) :
		    ref->NAME, x, y));
	}
	/* Absolutly needed for GenView */
	return refs;
}

/*******************************************************************************
* function  PLACE_VIA_REF                                                      *
*******************************************************************************/
phvia_list *genPLACE_VIA_REF(insname, refname, type)
char *insname;
char *refname;
char type;
{
phfig_list *ptnewfig;
phins_list *ptins;
phref_list *ptref;
long x, y;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_VIA_REF impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	ptins = getphins(WORK_PHFIG, insname);
	ptnewfig = getphfig(ptins->FIGNAME, 'P');
	ptref = getphref(ptnewfig, checkname(refname));

	xyflat(&x, &y, ptref->XREF, ptref->YREF, ptins->XINS, ptins->YINS,
	         ptnewfig->XAB1, ptnewfig->YAB1, ptnewfig->XAB2, ptnewfig->YAB2,
	         ptins->TRANSF);

	return addphvia(WORK_PHFIG, type, x, y);
}

/*******************************************************************************
* function  PLACE_CON_REF                                                      *
*******************************************************************************/
chain_list *genPLACE_CON_REF(insname, refname, conname, layer, width, face)
char *insname;
char *refname;
char *conname;
char layer;
long width;
char face;
{
phfig_list *newfig;
phins_list *ins;
phcon_list *con;
phseg_list *seg = NULL; /* may not be overwritten */
phref_list *ref;
chain_list *chain = NULL;
long x, y;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_CON_REF impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (!(WORK_PHFIG->XAB1 | WORK_PHFIG->YAB1 | WORK_PHFIG->XAB2
			| WORK_PHFIG->YAB2)) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_CON_REF impossible : missing DEF_AB ", stderr);
		(void)fprintf(stderr, "on figure %s\n", WORK_PHFIG->NAME);
		EXIT(1);
	}

	ins = getphins(WORK_PHFIG, insname);
	newfig = getphfig(ins->FIGNAME, 'P');
	ref = getphref(newfig, checkname(refname));

	xyflat(&x, &y, ref->XREF, ref->YREF, ins->XINS, ins->YINS, newfig->XAB1,
	     newfig->YAB1, newfig->XAB2, newfig->YAB2, ins->TRANSF);

	switch (face) {
		case WEST :
			con = addphcon(WORK_PHFIG, face, checkname(conname),
								WORK_PHFIG->XAB1, y, layer, width);
			if (x > WORK_PHFIG->XAB1)
				seg = addphseg(WORK_PHFIG, layer, width, WORK_PHFIG->XAB1,
			                            	y, x, y, (char *)NULL);
			break;
		case EAST :
			con = addphcon(WORK_PHFIG, face, checkname(conname), WORK_PHFIG->XAB2,
		                            	y, layer, width);
			if (x < WORK_PHFIG->XAB2)
				seg = addphseg(WORK_PHFIG, layer, width, x, y,
			    					WORK_PHFIG->XAB2, y, (char *)NULL);
			break;
		case NORTH :
			con = addphcon(WORK_PHFIG, face, checkname(conname), x,
								WORK_PHFIG->YAB2, layer, width);
			if (y < WORK_PHFIG->YAB2)
				seg = addphseg(WORK_PHFIG, layer, width, x, y, x,
			    					WORK_PHFIG->YAB2, (char *)NULL);
			break;
		case SOUTH :
			con = addphcon(WORK_PHFIG, face, checkname(conname), x,
								WORK_PHFIG->YAB1, layer, width);
			if (y > WORK_PHFIG->YAB1)
				seg = addphseg(WORK_PHFIG, layer, width, x, y, x,
			    					WORK_PHFIG->YAB1, (char *)NULL);
			break;
	}

	/* Absolutly needed for GenView */
	if (seg)
		chain = addchain(chain, (void *)seg);
	return addchain(chain, (void *)con);
}

/*******************************************************************************
* function  PLACE_SEG_REF                                                      *
*******************************************************************************/
phseg_list *genPLACE_SEG_REF(insname, refname, layer, width, face)
char *insname;
char *refname;
char layer;
long width;
char face;
{
phfig_list *newfig;
phins_list *ins;
phseg_list *seg = NULL;
phref_list *ref;
long x, y;

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_SEG_REF impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (!(WORK_PHFIG->XAB1 | WORK_PHFIG->YAB1 | WORK_PHFIG->XAB2
			| WORK_PHFIG->YAB2)) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("PLACE_SEG_REF impossible : missing DEF_AB ", stderr);
		(void)fprintf(stderr, "on figure %s\n", WORK_PHFIG->NAME);
		EXIT(1);
	}

	ins = getphins(WORK_PHFIG, insname);
	newfig = getphfig(ins->FIGNAME, 'P');
	ref = getphref(newfig, checkname(refname));

	xyflat(&x, &y, ref->XREF, ref->YREF, ins->XINS, ins->YINS, newfig->XAB1,
	     newfig->YAB1, newfig->XAB2, newfig->YAB2, ins->TRANSF);

	switch (face) {
	case WEST :
		if (x > WORK_PHFIG->XAB1)
			seg = addphseg(WORK_PHFIG, layer, width, WORK_PHFIG->XAB1,
			                            y, x, y, (char *)NULL);
		break;
	case EAST :
		if (x < WORK_PHFIG->XAB2)
			seg = addphseg(WORK_PHFIG, layer, width, x, y,
			    WORK_PHFIG->XAB2, y, (char *)NULL);
		break;
	case NORTH :
		if (y < WORK_PHFIG->YAB2)
			seg = addphseg(WORK_PHFIG, layer, width, x, y,
			    WORK_PHFIG->YAB2, y, (char *)NULL);
		break;
	case SOUTH :
		if (y < WORK_PHFIG->YAB1)
			seg = addphseg(WORK_PHFIG, layer, width, x, y,
			    WORK_PHFIG->YAB1, y, (char *)NULL);
		break;
	}
	return seg;
}

/*******************************************************************************
* function GET_REF_X                                                           *
*******************************************************************************/
long genGET_REF_X(insname, refname)
char *insname, *refname;
{
phfig_list *ptfig; /* pointer on model of instance called insname */
phins_list *ptins; /* pointer on instance called insname */
phref_list *ptref; /* pointer on the refname called ref inside ptins */
long x_ref, y_ref; /* return values, y_ref here for beauty */

	ptins = getphins(WORK_PHFIG, insname);
	ptfig = getphfig(ptins->FIGNAME, 'P');
	ptref = getphref(ptfig, checkname(refname));

	xyflat(&x_ref, &y_ref, ptref->XREF, ptref->YREF, ptins->XINS, ptins->YINS,
	     ptfig->XAB1, ptfig->YAB1,  ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);
	return x_ref;
}

/*******************************************************************************
* function GET_REF_Y                                                           *
*******************************************************************************/
long genGET_REF_Y(insname, refname)
char *insname, *refname;
{
phfig_list *ptfig; /* pointer on model of instance called insname */
phins_list *ptins; /* pointer on instance called insname */
phref_list *ptref; /* pointer on the refname called ref inside ptins */
long x_ref, y_ref; /* return values, x_ref here for beauty */

	ptins = getphins(WORK_PHFIG, insname);
	ptfig = getphfig(ptins->FIGNAME, 'P');
	ptref = getphref(ptfig, checkname(refname));

	xyflat(&x_ref, &y_ref, ptref->XREF, ptref->YREF, ptins->XINS, ptins->YINS,
	     ptfig->XAB1, ptfig->YAB1,  ptfig->XAB2, ptfig->YAB2, ptins->TRANSF);
	return y_ref;
}

/*******************************************************************************
* set of functions to reverse the `logical' ordering of a set of connectors    *
*******************************************************************************/
#define HARD_CONNECTOR    'H'
#define VIRTUAL_CONNECTOR 'V'
/* connector name :
	since connectors may be either hard, mbk phcon, or virtual, mbk phref,
	we need to do some tricky businness when working on the overall
	connector list. */
#define HVNAME(c) (*((c)->TYPE == HARD_CONNECTOR \
							? &((phcon_list *)((c)->DATA))->NAME \
							: &((phref_list *)((c)->DATA))->NAME))

static int hvconnectorcmp(flc, slc)
ptype_list **flc, **slc;
{
	return naturalstrcmp(HVNAME(*slc), HVNAME(*flc));
}

static ptype_list *sorthvcon(connectors, cmp)
ptype_list *connectors;
int (*cmp)();
{
long n, i;
ptype_list *phc, **tc;

	if (!connectors) 
		return NULL;

	/* first :
	   count connectors. */
	for (n = 0, phc = connectors; phc; phc = phc->NEXT)
		n++;
	tc = (ptype_list **)mbkalloc(n * sizeof(ptype_list *));
	for (n = 0, phc = connectors; phc; phc = phc->NEXT)
		tc[n++] = phc;
	/* second :
	   sort them. */
	qsort((void *)tc, n, sizeof(ptype_list *), cmp);
	/* tables :
	   the last element of the table is t[n - 1].
	   relink the list in the sorted order. */
	n--;
	connectors = tc[0];
	for (i = 0; i < n; i++)
		tc[i]->NEXT = tc[i + 1];
	tc[n]->NEXT = (ptype_list *)NULL;
	mbkfree((void *)tc);
	return connectors;
}

void genREVERSE_PHCON(conname)
char *conname;
{
ptype_list *c = NULL, *cstart, *cend;
char *s = namealloc("ref_con"); /* only for a short time, to build the list */
long i, j, k, sign;
void *hvc; /* hard and virtual connectors */

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("REVERSE_PHCON impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}

	/* first :
		create a list containing typed connectors.
		virtual connectors are known as "ref_con", and s is initialized
		to this nameallocated value. */
	for (hvc = (void *)WORK_PHFIG->PHCON; hvc;
			hvc = (void *)((phcon_list *)hvc)->NEXT)
		c = addptype(c, HARD_CONNECTOR, hvc);
	for (hvc = (void *)WORK_PHFIG->PHREF; hvc;
			hvc = (void *)((phref_list *)hvc)->NEXT)
		if (((phref_list *)hvc)->FIGNAME == s)
			c = addptype(c, VIRTUAL_CONNECTOR, hvc);
	
	hvc = (void *)sorthvcon(c, hvconnectorcmp);
	k = strlen(conname);
	for (cstart = (ptype_list *)hvc; cstart; cstart = cstart->NEXT) {
		/* not a vector :
		   If the connector doesn't belong to a vector, nobody cares. */
		if ((s = strchr(HVNAME(cstart), ' ')) == NULL)
			continue;
		if (!strcmp(vectorradical(HVNAME(cstart)), conname)) {
			cend = cstart;
			/* simple :
			   Only one connector s'got this name. */
			if ((c = cstart->NEXT) == NULL)
				return;
			while (c && !strcmp(vectorradical(HVNAME(c)), conname)) {
				cend = c;
				c = c->NEXT;
			}
			break;
		}
	}
	if (!cstart)
		return;
	i = vectorindex(HVNAME(cstart));
	j = vectorindex(HVNAME(cend));
	/* hypothesys :
	   since I assume the vectorized values are correct from a mbk point of
	   view, the algorithm is quit simple.
	   Given a first vector number and its growing direction, the number of
	   elements of the list supplies the range. */
	sign = j > i ? 1 : -1;
	/* delta :
	   I need only the delta value between the vector borders. */
	j -= i;
	k = vectorindex(HVNAME(cstart));
	for (c = cstart; c != cend->NEXT; c = c->NEXT) {
		if (k != vectorindex(HVNAME(c))) {
			j -= sign;
			k = vectorindex(HVNAME(c));
		}
		/* Since for obscure reasons the datapath compiler needs virtual
		   connector indexing as `name index_track', I have to take care
			of that s**t.
			If I get that to change in the futur, then only the following
			line will be needed :
		   HVNAME(c) = vectorize(conname, i + j);
		*/
		if (c->TYPE == HARD_CONNECTOR)
		   HVNAME(c) = vectorize(conname, i + j);
		else {
			if ((s = strrchr(HVNAME(c), '_')) != NULL) {
			char buffer[256]; /* I don't want to malloc here */
				(void)sprintf(buffer, "%s %d%s", conname, i + j, s);
				HVNAME(c) = namealloc(buffer);
			} else
		   	HVNAME(c) = vectorize(conname, i + j);
		}
	}
}

/*******************************************************************************
* OUTLINE                                                                      *
*******************************************************************************/
void genOUTLINE()
{
void **now, *next;

	/* delete instances and vias */
	for (now = (void *)&WORK_PHFIG->PHINS; *now;) {
		next = (void *)(*(phins_list **)now)->NEXT;
		mbkfree(*now);
		*now = next;
	}
	for (now = (void *)&WORK_PHFIG->PHVIA; *now;) {
		next = (void *)(*(phvia_list **)now)->NEXT;
		mbkfree(*now);
		*now = next;
	}
	/* delete the segments other than feed through */
	for (now = (void *)&WORK_PHFIG->PHSEG; *now;) {
		if ((*(phseg_list **)now)->LAYER == TPOLY ||
				(*(phseg_list **)now)->LAYER == TALU1 ||
				(*(phseg_list **)now)->LAYER == TALU2 ||
				(*(phseg_list **)now)->LAYER == TALU3)
			now = (void **)&(*(phseg_list **)now)->NEXT;
		else {
			next = (void *)(*(phseg_list **)now)->NEXT;
			mbkfree(*now);
			*now = next;
		}
	}
}


/*******************************************************************************
* logical user functions                                                       *
*******************************************************************************/
#include <varargs.h>

long	num_index = 0;

/*******************************************************************************
* function DEF_LOFIG                                                           *
*******************************************************************************/
void genDEF_LOFIG(name)
char *name;
{
char *s = namealloc(name);
lofig_list *ptfig;

	mbkenv();

	for (ptfig = HEAD_LOFIG; ptfig; ptfig = ptfig->NEXT)
		if (ptfig->NAME == s)
			break;
	if (ptfig == NULL)
		WORK_LOFIG = addlofig(s);
	else
		WORK_LOFIG = ptfig;
}

/*******************************************************************************
* function LOAD_LOFIG                                                          *
*******************************************************************************/
void genLOAD_LOFIG(name)
char *name;
{
	mbkenv();
	WORK_LOFIG = getlofig(name, 'A');
}

/*******************************************************************************
* function SAVE_LOFIG                                                          *
*******************************************************************************/
void genSAVE_LOFIG()
{
losig_list *s;
locon_list *c;
chain_list *l;
ptype_list *t;
int external; /* more that one external connector on the same net? */

	/* sets correct signal type :
	   the use of some genlib function may create figures with badly typed
	   external signal. */
	for (c = WORK_LOFIG->LOCON; c; c = c->NEXT)
		c->SIG->TYPE = EXTERNAL;
	lofigchain(WORK_LOFIG); /* builds up a list of connectors on each signals */
	for (s = WORK_LOFIG->LOSIG; s; s = s->NEXT) {
		external = 0; /* no external connector */
		t = getptype(s->USER, (long)LOFIGCHAIN);
		for (l = (chain_list *)t->DATA; l; l = l->NEXT) {
			c = (locon_list *)l->DATA;
			if (c->TYPE == EXTERNAL)
				external++;
		}
		if (external > 1) {
			(void)fflush(stdout);
			(void)fputs("*** genlib error ***\n", stderr);
			(void)fputs("The following external connectors are", stderr);
			(void)fputs(" on the same signal: \n", stderr);
			for (l = (chain_list *)t->DATA; l; l = l->NEXT) {
				c = (locon_list *)l->DATA;
				if (c->TYPE == EXTERNAL)
					(void)fprintf(stderr, "\t%s\n", c->NAME);
			}
			(void)fprintf(stderr, "\ton signal %s\n", getsigname(c->SIG));
			EXIT(1);
		}
	}
	checkloconorder(WORK_LOFIG->LOCON);
	sortlosig(&WORK_LOFIG->LOSIG);
	savelofig(WORK_LOFIG);
}

/*******************************************************************************
* function LOINS                                                               *
*******************************************************************************/
void genLOINS(va_alist)
va_dcl
{
losig_list *ptsig;
chain_list *ptchain = NULL, *ptchain1, *ptchain2 = NULL , *ptchain3;
va_list arg;
char *figname, *insname, *signame;
lofig_list *ptfig;

	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal LOINS : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}
	va_start(arg);
	figname = namealloc(va_arg(arg, char *));
	ptfig = getlofig(figname, 'P');
	insname = va_arg(arg, char *);
	/* expanding the bus names */
	while ((signame = va_arg(arg, char *)) != NULL) {
		if (!is_bus(signame))  /* normal signal */
			ptchain2 = addchain(ptchain2, (void *)namealloc(checkname(signame)));
		else { /* it's a bus */
			long	i, from, to;
			char	*zig, *newzig;
			chain_list *ptchain4 = NULL;

			zig = (char *)mbkalloc((unsigned int)(strlen(signame) + 1));
			newzig = (char *)mbkalloc((unsigned int)(strlen(signame) + 1));
			if (!bus_decod(signame, zig, &from, &to)) {
				(void)fflush(stdout);
				(void)fputs("*** genlib error ***\n", stderr);
				(void)fprintf(stderr, "Bad signal bus name %s\n", signame);
				EXIT(1);
			}
			if (from > to)
				for (i = from; i >= to; i--) {
					(void)sprintf(newzig, "%s %ld", zig, i);
					ptchain4 = addchain(ptchain4, (void *)namealloc(newzig));
				}
			else
				for (i = from; i <= to; i++) {
					(void)sprintf(newzig, "%s %ld", zig, i);
					ptchain4 = addchain(ptchain4, (void *)namealloc(newzig));
				}
			for (ptchain1 = ptchain4; ptchain1->NEXT != NULL;
			    ptchain1 = ptchain1->NEXT);
			ptchain1->NEXT = ptchain2;
			ptchain2 = ptchain4;
		}
	}
	ptchain2 = (chain_list *)reverse(ptchain2);

	/* adding the signals if needed */
	for (ptchain3 = ptchain2; ptchain3 != NULL; ptchain3 = ptchain3->NEXT) {
		signame = namealloc((char *)ptchain3->DATA);
		for (ptsig = WORK_LOFIG->LOSIG; ptsig != NULL; ptsig = ptsig->NEXT) {
			for (ptchain1 = ptsig->NAMECHAIN; ptchain1; ptchain1 = ptchain1->NEXT)
				if (ptchain1->DATA == (void *)signame)
					break;
			if (ptchain1 != NULL)
				break;
		}
		if (ptsig == NULL) {
			num_index++;
			ptsig = addlosig(WORK_LOFIG, num_index,
									addchain((chain_list *)NULL, (void *)signame),
									INTERNAL, 0.0);
		}
		ptchain = addchain(ptchain, (void *)ptsig);
	}
	(void)addloins(WORK_LOFIG, insname, ptfig, ptchain);
	va_end(arg);
}

/*******************************************************************************
* function LOINSE                                                              *
*******************************************************************************/
void genLOINSE(va_alist)
va_dcl
{
va_list arg;
char *figname, *insname, *signame;
lofig_list  *ptfig;
char con[100], sig[100];
int icon, jcon, isig, jsig;
int inc, ins, nb, nbs;
ptype_list *consiglist = NULL, *pcon;
locon_list *locon;
chain_list *sigchain = NULL, *chain;
losig_list *ptsig;
chain_list *ptchain = NULL;


	if (WORK_LOFIG == NULL) {
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal LOINSE : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}

	va_start(arg);
	figname = namealloc(va_arg(arg, char *));
	ptfig = getlofig(figname, 'P');
	insname = va_arg(arg, char *);

	while ((signame = va_arg(arg, char *)) != NULL) {  
	char	*s, *buffer = mbkstrdup(signame); /* I shall not alter user strings */

		signame = buffer;
		for (s = signame; *s != '\0'; s++)
			if (*s == ':') {
				for (s = signame; *s != '\0'; s++)
					if (*s == '[' || *s == ']')   
						*s = ' ';
				break;
			}
		if (sscanf(signame, " %s %d:%d => %s %d:%d ", con, &icon, &jcon, sig, &isig, &jsig) == 6) {
			if (abs(icon - jcon) != abs(isig - jsig) || icon == jcon) {

				fprintf(stderr, "Not a valid range : %s[%d:%d] => %s[%d:%d]\n",
							con, icon, jcon, sig, isig, jsig);
				EXIT(1);
			}
			inc = (icon > jcon) ? -1 : 1;
			ins = (isig > jsig) ? -1 : 1;
			for (nb = icon, nbs = isig; nb != (jcon + inc); nbs += ins, nb += inc)
				consiglist = addptype(consiglist,
												vectorize(con, nb),
												vectorize(sig, nbs));
		} else if (sscanf(signame, " %s => %s ", con, sig) == 2)
			consiglist = addptype(consiglist, namealloc(checkname(con)),
											namealloc(checkname(sig)));
		else {
			fprintf(stderr, "Illegal signal affectation syntax : %s\n", signame);
			EXIT(1);
		}
		mbkfree(signame);
	}

	/*  Put sigs and cons in dictionnary  */
	for (pcon = consiglist; pcon; pcon = pcon->NEXT) {
		pcon->TYPE = (long)namealloc((char *)pcon->TYPE);
		pcon->DATA = (void *)namealloc((char *)pcon->DATA);
	}

	/*  Check Connectors name consistency  */
	for (locon = ptfig->LOCON; locon; locon = locon->NEXT) {
		for (pcon = consiglist; pcon; pcon = pcon->NEXT)
			if (locon->NAME == (char *)pcon->TYPE) {
				sigchain = addchain(sigchain, pcon->DATA);
				pcon->TYPE = 0L;
				break;
			}
		if (pcon == NULL) {
			fprintf(stderr, "No model connector %s for instance %s\n",
									locon->NAME, insname);
			EXIT(1);
		}
	}

	for (pcon = consiglist; pcon; pcon = pcon->NEXT)
		if (pcon->TYPE != 0L) {
			fprintf(stderr, "Connector %s in instance %s do not exist in model",
						(char *)pcon->TYPE, insname);
			fprintf(stderr, " in model %s\n", figname);
			EXIT(1);
		}

	/* adding the signals if needed */
	for (chain = sigchain; chain; chain = chain->NEXT) {
		signame = (char *)chain->DATA;
		for (ptsig = WORK_LOFIG->LOSIG; ptsig; ptsig = ptsig->NEXT) {
			for (sigchain = ptsig->NAMECHAIN; sigchain; sigchain = sigchain->NEXT)
				if (sigchain->DATA == (void *)signame)  
					break;
			if (sigchain != NULL)  
				break;
		}
		if (ptsig == NULL)
			ptsig = addlosig(WORK_LOFIG, ++num_index,
						addchain((chain_list *)NULL, (void *)signame), 'I', 0.0);
		ptchain = addchain(ptchain, (void *)ptsig);
	}
	(void)addloins(WORK_LOFIG, insname, ptfig, ptchain);
	va_end(arg);
}

/*******************************************************************************
* function LOSIG                                                               *
*******************************************************************************/
void genLOSIG(signame)
char *signame;
{
losig_list *ptsig;
chain_list *ptchain, *ptchain1 = NULL;
char	*s;

	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal LOSIG : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}

	if (!is_bus(signame)) {
		s = namealloc(checkname(signame));
		for (ptsig = WORK_LOFIG->LOSIG; ptsig; ptsig = ptsig->NEXT) {
			for (ptchain = ptsig->NAMECHAIN; ptchain != NULL;
			    ptchain = ptchain->NEXT)
				if (ptchain->DATA == (void *)s)
					break;
			if (ptchain != NULL)
				break;
		}
		if (ptsig == NULL) {
			num_index++;
			ptsig = addlosig(WORK_LOFIG, num_index,
									addchain((chain_list *)NULL, (void *)s),
									INTERNAL, 0.0);
		}
	} else { /* expanding signal names */
		long	from, to, i;
		char	*zig, *newzig;

		s = (char *)mbkalloc((unsigned int)(strlen(signame) + 1));
		(void)strcpy(s, signame);

		/* expanding signal names */
		zig = (char *)mbkalloc((unsigned int)(strlen(signame) + 1));
		newzig = (char *)mbkalloc((unsigned int)(strlen(signame) + 1));

		if (!bus_decod(s, zig, &from, &to)) {
			(void)fflush(stdout);
			(void)fputs("*** genlib error ***\n", stderr);
			(void)fprintf(stderr, "LOSIG : Bad signal bus name %s\n", s);
			EXIT(1);
		}
		mbkfree((void *)s);
		if (from > to) {
			for (i = from; i >= to; i--) {
				(void)sprintf(newzig, "%s %ld", zig, i);
				ptchain1 = addchain(ptchain1, (void *)namealloc(newzig));
			}
		} else {
			for (i = from; i <= to; i++) {
				(void)sprintf(newzig, "%s %ld", zig, i);
				ptchain1 = addchain(ptchain1, (void *)namealloc(newzig));
			}
		}
		mbkfree((void *)zig);
		mbkfree((void *)newzig);
		while (ptchain1 != NULL) {
			s = (char *)ptchain1->DATA;
			for (ptsig = WORK_LOFIG->LOSIG; ptsig; ptsig = ptsig->NEXT) {
				for (ptchain = ptsig->NAMECHAIN; ptchain
				   	!= NULL; ptchain = ptchain->NEXT)
					if (ptchain->DATA == (void *)s)
						break;
				if (ptchain != NULL)
					break;
			}
			if (ptsig == NULL) {
				num_index++;
				ptsig = addlosig(WORK_LOFIG, num_index,
									addchain((chain_list *)NULL, (void *)s), 
									INTERNAL, 0.0);
			}
			ptchain1 = ptchain1->NEXT;
		}
		ptchain1 = (chain_list *)reverse(ptchain1);
	}
}

/*******************************************************************************
* function LOCON                                                               *
*******************************************************************************/
void genLOCON(conname, direction, signame)
char *conname, direction, *signame;
{
losig_list * ptsig;
chain_list * ptchain, *ptchain1 = NULL, *ptchain2 = NULL;
char	*s;

	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal LOCON : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}
	/* one shall not deeclare connectors after instances */
	if (WORK_LOFIG->LOINS != NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal LOCON : ", stderr);
		(void)fputs("all LOCON must be defined before any LOINS\n", stderr);
		EXIT(1);
	}

	if (!is_bus(signame)) {
		s = namealloc(checkname(signame));
		for (ptsig = WORK_LOFIG->LOSIG; ptsig; ptsig = ptsig->NEXT) {
			for (ptchain = ptsig->NAMECHAIN; ptchain != NULL;
			    ptchain = ptchain->NEXT)
				if (ptchain->DATA == (void *)s)
					break;
			if (ptchain != NULL)
				break;
		}
		if (ptsig == NULL) {
			num_index++;
			ptsig = addlosig(WORK_LOFIG, num_index,
									addchain((chain_list *)NULL, (void *)s),
									EXTERNAL, 0.0);
		}
		(void)addlocon(WORK_LOFIG, checkname(conname), ptsig, direction);
	} else { /* expanding connector names */
		long	from, to, dc, ds, i;
		char	*gon, *newgon;
		char	*zig, *newzig;

		s = (char *)mbkalloc((unsigned int)(strlen(signame) + 1));
		(void)strcpy(s, signame);

		gon = (char *)mbkalloc((unsigned int)(strlen(conname) + 1));
		newgon = (char *)mbkalloc((unsigned int)(strlen(conname) + 1));
		if (!bus_decod(conname, gon, &from, &to)) {
			(void)fflush(stdout);
			(void)fputs("*** genlib error ***\n", stderr);
			(void)fprintf(stderr, "LOCON : Bad connector bus name %s\n", conname);
			EXIT(1);
		}
		if (from > to) {
			dc = from - to;
			for (i = from; i >= to; i--) {
				(void)sprintf(newgon, "%s %ld", gon, i);
				ptchain1 = addchain(ptchain1, (void *)namealloc(newgon));
			}
		} else {
			dc = to - from;
			for (i = from; i <= to; i++) {
				(void)sprintf(newgon, "%s %ld", gon, i);
				ptchain1 = addchain(ptchain1, (void *)namealloc(newgon));
			}
		}
		mbkfree((void *)gon);
		mbkfree((void *)newgon);
		/* expanding signal names */
		zig = (char *)mbkalloc((unsigned int)(strlen(signame) + 1));
		newzig = (char *)mbkalloc((unsigned int)(strlen(signame) + 1));

		if (!bus_decod(s, zig, &from, &to)) {
			(void)fflush(stdout);
			(void)fputs("*** genlib error ***\n", stderr);
			(void)fprintf(stderr, "LOCON : Bad signal bus name %s\n", s);
			EXIT(1);
		}
		mbkfree((void *)s);
		if (from > to) {
			ds = from - to;
			for (i = from; i >= to; i--) {
				(void)sprintf(newzig, "%s %ld", zig, i);
				ptchain2 = addchain(ptchain2, (void *)namealloc(newzig));
			}
		} else {
			ds = to - from;
			for (i = from; i <= to; i++) {
				(void)sprintf(newzig, "%s %ld", zig, i);
				ptchain2 = addchain(ptchain2, (void *)namealloc(newzig));
			}
		}
		mbkfree((void *)zig);
		mbkfree((void *)newzig);
		if (dc != ds) {
			(void)fflush(stdout);
			(void)fputs("*** genlib error ***\n", stderr);
			(void)fputs(
					"Illegal LOCON : different number of signals and connectors\n",
					stderr);
			EXIT(-1);
		}
		ptchain1 = (chain_list *)reverse(ptchain1);
		ptchain2 = (chain_list *)reverse(ptchain2);

		while (ptchain1 != NULL) {
			gon = (char *)ptchain1->DATA;
			s = (char *)ptchain2->DATA;
			for (ptsig = WORK_LOFIG->LOSIG; ptsig; ptsig = ptsig->NEXT) {
				for (ptchain = ptsig->NAMECHAIN; ptchain
				    != NULL; ptchain = ptchain->NEXT)
					if (ptchain->DATA == (void *)s)
						break;
				if (ptchain != NULL)
					break;
			}
			if (ptsig == NULL) {
				num_index++;
				ptsig = addlosig(WORK_LOFIG, num_index,
										addchain((chain_list *)NULL, (void *)s),
										EXTERNAL, 0.0);
			}
			(void)addlocon(WORK_LOFIG, gon, ptsig, direction);
			ptchain1 = ptchain1->NEXT;
			ptchain2 = ptchain2->NEXT;
		}
	}
}

/*******************************************************************************
* function LOTRS                                                               *
*******************************************************************************/
void genLOTRS(type, width, length, grid, source, drain)
char type;
unsigned short width, length;
char *grid, *source, *drain;
{
int i = 0;
losig_list *s_grid, *s_source, *s_drain, *ptsig;
chain_list *ptchain;
char *signame;

	for (i = 0; i < 3; i++) {
		switch (i) {
			case 0 :
				signame = namealloc(checkname(grid));
				break;
			case 1 :
				signame = namealloc(checkname(source));
				break;
			case 2 :
				signame = namealloc(checkname(drain));
				break;
		}
		for (ptsig = WORK_LOFIG->LOSIG; ptsig; ptsig = ptsig->NEXT) {
			for (ptchain = ptsig->NAMECHAIN; ptchain; ptchain = ptchain->NEXT)
				if (ptchain->DATA == (void *)signame)
					break;
			if (ptchain)
				break;
		}
		if (!ptsig) {
			num_index++;
			ptsig = addlosig(WORK_LOFIG, num_index,
									addchain((chain_list *)NULL, (void *)signame),
									INTERNAL, 0.0);
		}
		switch (i) {
			case 0 :
				s_grid = ptsig;
				break;
			case 1 :
				s_source = ptsig;
				break;
			case 2 :
				s_drain = ptsig;
				break;
		}
	}
	(void)addlotrs(WORK_LOFIG, type, 0L, 0L, width, length, 0, 0, 0, 0,
						s_grid, s_source, s_drain);
}

/*******************************************************************************
* function LOSIGMERGE                                                          *
*******************************************************************************/
void genLOSIGMERGE(sig1, sig2)
char *sig1, *sig2;
{
losig_list *ls0, *ls1, *ls2;
locon_list *c;
loins_list *i;
lotrs_list *t;
chain_list *chain;

	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal LOMERGE : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}
	sig1 = namealloc(checkname(sig1));
	sig2 = namealloc(checkname(sig2));
	for (ls1 = WORK_LOFIG->LOSIG; ls1; ls1 = ls1->NEXT) {
		for (chain = ls1->NAMECHAIN; chain; chain = chain->NEXT)
			if (chain->DATA == (void *)sig1)
				break;
		if (chain)
			break;
	}
	for (ls2 = WORK_LOFIG->LOSIG; ls2; ls2 = ls2->NEXT) {
		for (chain = ls2->NAMECHAIN; chain; chain = chain->NEXT)
			if (chain->DATA == (void *)sig2)
				break;
		if (chain)
			break;
	}
	if (ls1 == NULL && ls2 == NULL) { /* none of them exists ! */
		num_index++;
		chain = addchain((chain_list *)NULL, (void *)sig1);
		chain = addchain(chain, (void *)sig2);
		(void)addlosig(WORK_LOFIG, num_index, chain, INTERNAL, 0.0);
		return;
	}
	if (ls1 == ls2) /* already joined!, just return */
		return;
	if (ls1 == NULL || ls2 == NULL) { /* one of them exists ! */
		if (ls1 == NULL)
			ls2->NAMECHAIN = addchain((chain_list *)ls2->NAMECHAIN, (void *)sig1);
		else
			ls1->NAMECHAIN = addchain((chain_list *)ls1->NAMECHAIN, (void *)sig2);
		return;
	}
	/* if both exists */
	if (ls2->TYPE == EXTERNAL) { /* delete ls1 */
		ls2->NAMECHAIN = addchain(ls2->NAMECHAIN, (void *)sig1);
		ls0 = ls2; /* swap ls1 and ls2 for deleting purpose */
		ls2 = ls1;
		ls1 = ls0;
	} else
		ls1->NAMECHAIN = addchain(ls1->NAMECHAIN, (void *)sig2);
	
	/* delete ls2, why not */
	for (c = WORK_LOFIG->LOCON; c; c = c->NEXT)
		if (c->SIG == ls2)
			c->SIG = ls1;
	for (i = WORK_LOFIG->LOINS; i; i = i->NEXT)
		for (c = i->LOCON; c; c = c->NEXT)
			if (c->SIG == ls2)
				c->SIG = ls1;
	for (t = WORK_LOFIG->LOTRS; t; t = t->NEXT) {
		if (t->GRID->SIG == ls2)
			t->GRID->SIG = ls1;
		if (t->DRAIN->SIG == ls2)
			t->DRAIN->SIG = ls1;
		if (t->SOURCE->SIG == ls2)
			t->SOURCE->SIG = ls1;
	}
	(void)addcapa(ls1, ls2->CAPA);
	(void)dellosig(WORK_LOFIG, ls2->INDEX);
}

/*******************************************************************************
* function FLATTEN_LOFIG                                                       *
*******************************************************************************/
void genFLATTEN_LOFIG(insname, concat)
char *insname;
char concat;
{
long i = 0;
losig_list *s;

	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal FLATTEN_LOFIG : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}
	flattenlofig(WORK_LOFIG, insname, concat);
	/* flattenlofig will create many signals, and genlib should be kept
	   up to date with the last used index.*/
	for (s = WORK_LOFIG->LOSIG; s; s = s->NEXT)
		if (s->INDEX > i)
			i = s->INDEX;
	num_index = ++i;
}

/*******************************************************************************
* flattens FLATTEN_ALL_LOINS                                                   *
*******************************************************************************/
void genFLATTEN_ALL_LOINS(concat, catal)
char concat, catal;
{
chain_list *c, *namelist = NULL;
loins_list *l;
long i = 0;
losig_list *s;

	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal FLATTEN_ALL_LOINS : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}

	for (l = WORK_LOFIG->LOINS; l; l = l->NEXT)
		if (catal == NO || !incatalog(l->FIGNAME))
			namelist = addchain(namelist, (void *)l->INSNAME);

	for (c = namelist; c; c = c->NEXT)
		flattenlofig(WORK_LOFIG, (char *)c->DATA, concat);

	freechain(namelist);
	/* flattenlofig will create many signals, and genlib should be kept
	   up to date with the last used index.*/
	for (s = WORK_LOFIG->LOSIG; s; s = s->NEXT)
		if (s->INDEX > i)
			i = s->INDEX;
	num_index = ++i;
}

/*******************************************************************************
* function UNFLATTEN_LOFIG                                                     *
*******************************************************************************/
void genUNFLATTEN_LOFIG(va_alist)
va_dcl
{
va_list instancelist;
char *modelname, *instancename, *iname;
chain_list *ilist = NULL;

	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal UNFLATTEN_LOFIG : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}
	va_start(instancelist);
	if ((modelname = va_arg(instancelist, char *)) == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal UNFLATTEN_LOFIG : missing arguments\n", stderr);
		EXIT(1);
	};
	if ((instancename = va_arg(instancelist, char *)) == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal UNFLATTEN_LOFIG : only one arguments\n", stderr);
		EXIT(1);
	};
	while ((iname = va_arg(instancelist, char *)) != NULL)
		ilist = addchain(ilist, (void *)getloins(WORK_LOFIG, iname));
	/* this new hierachy level needs to be saved */
	savelofig(unflattenlofig(WORK_LOFIG, modelname, instancename, ilist));
	freechain(ilist); 
	va_end(instancelist);
}

/*******************************************************************************
* standard-cell user functions                                                 *
*******************************************************************************/

/*******************************************************************************
* function SC_PLACE                                                            *
*******************************************************************************/
void genSC_PLACE(insname, sym, x, y)
char	*insname;
int	sym;
long	x, y;
{
loins_list * ptins;
char	*s = namealloc(insname);

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("SC_PLACE impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("SC_PLACE impossible : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}
	for (ptins = WORK_LOFIG->LOINS; ptins != NULL; ptins = ptins->NEXT)
		if (ptins->INSNAME == s)
			break;
	if (ptins == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fprintf(stderr,
					"SC_PLACE impossible : no logical instance %s in figure %s\n",
					insname, WORK_LOFIG->NAME);
		EXIT(1);
	}
	genPLACE(ptins->FIGNAME, s, sym, x, y);
}

/*******************************************************************************
* function SC_RIGHT                                                            *
*******************************************************************************/
void genSC_RIGHT(insname, sym)
char	*insname;
int	sym;
{
loins_list * ptins;
char	*s = namealloc(insname);

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("SC_RIGHT impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("SC_RIGHT impossible : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}
	for (ptins = WORK_LOFIG->LOINS; ptins != NULL; ptins = ptins->NEXT)
		if (ptins->INSNAME == s)
			break;
	if (ptins == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fprintf(stderr,
						"SC_RIGHT impossible : no logical instance %s in figure %s\n",
						insname, WORK_LOFIG->NAME);
		EXIT(1);
	}
	genPLACE_RIGHT(ptins->FIGNAME, s, sym);
}

/*******************************************************************************
* function SC_LEFT                                                             *
*******************************************************************************/
void genSC_LEFT(insname, sym)
char	*insname;
int	sym;
{
loins_list *ptins;
char *s = namealloc(insname);

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("SC_LEFT impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("SC_LEFT impossible : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}
	for (ptins = WORK_LOFIG->LOINS; ptins != NULL; ptins = ptins->NEXT)
		if (ptins->INSNAME == s)
			break;
	if (ptins == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fprintf(stderr, "SC_LEFT impossible : no logical instance %s in figure %s\n", insname, WORK_LOFIG->NAME);
		EXIT(1);
	}
	genPLACE_LEFT(ptins->FIGNAME, s, sym);
}

/*******************************************************************************
* function SC_TOP                                                              *
*******************************************************************************/
void genSC_TOP(insname, sym)
char *insname;
int sym;
{
loins_list *ptins;
char *s = namealloc(insname);

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("SC_TOP impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("SC_TOP impossible : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}
	for (ptins = WORK_LOFIG->LOINS; ptins != NULL; ptins = ptins->NEXT)
		if (ptins->INSNAME == s)
			break;
	if (ptins == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fprintf(stderr, "SC_TOP impossible : no logical instance %s in figure %s\n", insname, WORK_LOFIG->NAME);
		EXIT(1);
	}
	genPLACE_TOP(ptins->FIGNAME, s, sym);
}

/*******************************************************************************
* function SC_BOTTOM                                                           *
*******************************************************************************/
void genSC_BOTTOM(insname, sym)
char *insname;
int sym;
{
loins_list *ptins;
char *s = namealloc(insname);

	if (WORK_PHFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("SC_BOTTOM impossible : missing DEF_PHFIG\n", stderr);
		EXIT(1);
	}
	if (WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("SC_BOTTOM impossible : missing DEF_LOFIG\n", stderr);
		EXIT(1);
	}
	for (ptins = WORK_LOFIG->LOINS; ptins != NULL; ptins = ptins->NEXT)
		if (ptins->INSNAME == s)
			break;
	if (ptins == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("SC_BOTTOM impossible : no logical instance ", stderr);
		(void)fprintf(stderr, "%s in figure %s\n", insname, WORK_LOFIG->NAME);
		EXIT(1);
	}
	genPLACE_BOTTOM(ptins->FIGNAME, s, sym);
}

/*******************************************************************************
* BUS allows the definition of a bus for logical operations                    *
*******************************************************************************/
char *genBUS(signame, from, to)
char *signame;
long from, to;
{
char sigid[100];

	if (signame == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nBUS with NULL signal name", stderr);
		(void)fprintf(stderr, ", indexes [%ld:%ld]\n", from, to);
		EXIT(-1);
	}
	(void)sprintf(sigid, "%s[%ld:%ld]", signame, from, to);
	return mbkstrdup(sigid); /* must allocate memory for that */
}

/*******************************************************************************
* ELM allows the definition of a bus for logical operations                    *
*******************************************************************************/
char *genELM(signame, number)
char *signame;
long number;
{
char sigid[100];

	if (signame == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\nELM with NULL signal name", stderr);
		(void)fprintf(stderr, ", index [%ld]\n", number);
		EXIT(-1);
	}
	(void)sprintf(sigid, "%s[%ld]", signame, number);
	return mbkstrdup(sigid); /* here also, allocation needed */
}

/*******************************************************************************
* function DEF_PHSC                                                            *
* loads the net-list description of a cell and create what's necessary to      *
* physically describe it                                                       *
*******************************************************************************/
void genDEF_PHSC(name)
char *name;
{
lofig_list *ptlofig;

	mbkenv();
	name = namealloc(name);
	for (ptlofig = HEAD_LOFIG; ptlofig; ptlofig = ptlofig->NEXT)
		if (ptlofig->NAME == name)
			break;
	if (ptlofig == NULL)
		WORK_LOFIG = getlofig(name, 'A');
	else
		WORK_LOFIG = ptlofig;

	genDEF_PHFIG(name);
}

/*******************************************************************************
* function SAVE_PHSC                                                           *
*******************************************************************************/
void genSAVE_PHSC()
{
loins_list *ptloins;
phins_list *ptphins;
chain_list *c, *loname = NULL, *phname = NULL;


	if (WORK_PHFIG == NULL || WORK_LOFIG == NULL) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fputs("Illegal SAVE_PHSC : missing DEF_PHSC\n", stderr);
		EXIT(1);
	}

	for (ptloins = WORK_LOFIG->LOINS; ptloins; ptloins = ptloins->NEXT) {
		for (ptphins = WORK_PHFIG->PHINS; ptphins; ptphins = ptphins->NEXT)
			if (ptloins->INSNAME == ptphins->INSNAME) {
				ptphins->USER = addptype(ptphins->USER, (long)CHECKFEED, (void *)0);
				break;
			}
		if(!ptphins) /* error : no physical instance called ptloins->INSNAME */
			loname = addchain(loname, (void *)ptloins->INSNAME);
	}

	for (ptphins = WORK_PHFIG->PHINS; ptphins; ptphins = ptphins->NEXT)
		if (!getptype(ptphins->USER, (long)CHECKFEED))
			if (!incatalogfeed(ptphins->FIGNAME)) /* error, not a feeding cell */
				phname = addchain(phname, (void *)ptphins->INSNAME);

	if (loname) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fprintf(stderr, "Logical instance%s :\n", loname->NEXT ? "s" : "");
		for (c = loname; c; c = c->NEXT)
			(void)fprintf(stderr, "                      `%s'\n", (char *)c->DATA);
		(void)fprintf(stderr, "%s not physicaly placed\n",
							loname->NEXT ? "are" : "is");
	}

	if (phname) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fprintf(stderr, "Physical instance%s :\n", phname->NEXT ? "s" : "");
		for (c = phname; c; c = c->NEXT)
			(void)fprintf(stderr, "                      `%s'\n", (char *)c->DATA);
		(void)fprintf(stderr, "%s no logical equivalent and %s not %sfeed%s\n",
							phname->NEXT ? "have" : "has",
							phname->NEXT ? "are" : "is",
							phname->NEXT ? "" : "a ",
							phname->NEXT ? "s" : "");
	}

	if (loname || phname) { /* free before quiting */
		if (loname)
			freechain(loname);
		if (phname)
			freechain(phname);
		EXIT(1);
	}

	genDEF_AB(0L, 0L, 0L, 0L);
	savephfig(WORK_PHFIG);
}

/*******************************************************************************
* function NAME                                                                *
*******************************************************************************/
char *genNAME(va_alist)
va_dcl
{
va_list stack;
char	*ret, *res, *p;
long	strsize = 0;
char	piece[BUFSIZ], *s;
int	d;

	va_start(stack);
	p = va_arg(stack, char *);
	ret = res = (char *)mbkalloc(BUFSIZ);
	while (*p != '\0') {
		if (*p != '%') {
			toolong(strsize ++);
			*res++ = *p++;
			continue;
		}
		switch (*++p) {
		case 'l':
			if (*++p != 'd') {
				(void)fflush(stdout);
				(void)fputs("*** genlib error ***\n", stderr);
				(void)fprintf(stderr, "NAME : bad argument %%l%c\n", *p);
				EXIT(1);
			}

		case 'd':
			d = va_arg(stack, long);
			(void)sprintf(piece, "%ld", d);
			s = piece;
			while (*res++ = *s++)
				toolong(strsize ++);
			res--;
			p++;
			break;

		case 'x':
			d = va_arg(stack, long);
			(void)sprintf(piece, "%lx", d);
			s = piece;
			while (*res++ = *s++)
				toolong(strsize ++);
			res--;
			p++;
			break;

		case 's':
			s = va_arg(stack, char *);
			while (*res++ = *s++)
				toolong(strsize ++);
			res--;
			p++;
			break;

		case 'c':
			*res++ = va_arg(stack, int);
			p++;
			break;

		default :
			(void)fflush(stdout);
			(void)fputs("*** genlib error ***\nNAME allows", stderr);
			(void)fprintf(stderr, " only %%d, %%c, %%x & %%s typed args\n");
			EXIT(1);
		}
	}
	*res = '\0';
	va_end(stack);
	return ret;
}

/*******************************************************************************
* internal use functions                                                       *
*******************************************************************************/
/*******************************************************************************
* function is_bus                                                              *
* check the validity of the syntax of a bussed signal                          *
* a bus is "abdc[123]" or "abcd[12:34]"                                        *
* something like "abcd[efgh]" will exit on a syntax error                      *
* return 1 if "abcd[23:45]" 0 if "abcd" or "abdc[12]"                          *
*******************************************************************************/
int is_bus(signame)
char *signame;
{
register char *t = signame, c;
register char is_a_bus = 0, flag = 0;
register char i, where = 0; /* used to say exactly where */

	while (c = *t++) {
		where++; /* increment the position to know where if an error occurs */
		if (c == '[')
			if (!flag) {
				flag = 1;
				continue; /* do not treat '[' as a part of the bus */
			} else {
				(void)fflush(stdout);
				(void)fputs("*** genlib error ***\n", stderr);
				(void)fprintf(stderr, "signal name %s is not legal\n", signame);
				for (i = 0; i < where + strlen("signal name"); i++)
					(void)fputs("_", stderr);
				(void)fputs("?\n", stderr);
				EXIT(1);
			}
		if ((c == ':' || c == ']') && !flag) {
			(void)fflush(stdout);
			(void)fputs("*** genlib error ***\n", stderr);
			(void)fprintf(stderr, "signal name %s is not legal\n", signame);
			for (i = 0; i < where + strlen("signal name"); i++)
				(void)fputs("_", stderr);
			(void)fputs("?\n", stderr);
			EXIT(1);
		}
		if (flag) {
			if (c == ':') {
				is_a_bus = 1; /* that's a bus, not an element */
				continue; /* do not read the dots but still check for digit */
			}
			if (c == ']') {
				flag = 0; /* do not check for digit anymore */
				continue;
			}
			if (!isdigit(c)) {
				(void)fflush(stdout);
				(void)fputs("*** genlib error ***\n", stderr);
				(void)fprintf(stderr, "signal name %s is not legal\n", signame);
				for (i = 0; i < where + strlen("signal name"); i++)
					(void)fputs("_", stderr);
				(void)fputs("?\n", stderr);
				EXIT(1);
			}
		}
	}
	return is_a_bus;
}

/*******************************************************************************
* function bus_decod                                                           *
* decods the bus name so buses can be used in LOINS & LOCON                    *
*******************************************************************************/
int bus_decod(busname, signame, first, last)
char *busname, *signame;
long *first, *last;
{
char	*space;
char *buffer = mbkstrdup(busname);

	if (!(space = strchr(buffer, '[')))
		return 0;
	*space = ' ';
	if (!(space = strchr(buffer, ':')))
		return 0;
	*space = ' ';
	if (!(space = strchr(buffer, ']')))
		return 0;
	*space = ' ';
	(void)sscanf(buffer, "%s %ld %ld", signame, first, last);
	mbkfree(buffer);
	return 1;
}

/*******************************************************************************
* function toolong                                                             *
* cheks the validity of the lentgh of a string                                 *
*******************************************************************************/
static void toolong(length)
long length;
{
	if (length > BUFSIZ) {
		(void)fflush(stdout);
		(void)fputs("*** genlib error ***\n", stderr);
		(void)fprintf(stderr, "NAME string too long(%d)\n", (int)BUFSIZ);
		EXIT(1);
	}
}

/*******************************************************************************
* checkname : check for busses with single index                               *
*******************************************************************************/
static char *checkname(name)
char *name;
{
static char str[256];
char *s, *t;

	strcpy(str, name); /* do not alter user strings */
	s = t = str;
	while (*t) {
		if (isspace(*t)) {
			(void)fflush(stdout);
			(void)fputs("*** genlib error ***\n", stderr);
			(void)fprintf(stderr, "checkname failed : space detected in '%s'\n",
								name);
			EXIT(1);
		}
		if (*t == '[')
			*t = ' ';
		else if (*t == ']')
			if (*(++t) == '\0') /* ok, it's finished */
				goto end;
			else if (*t == '[') /* multiple array */
				continue;
		*s++ = *t++;
	}
end:
	*s = '\0';
	return str;
}
