#include  <stdio.h>
#include  <string.h>
#include  <varargs.h>

#include   MUT_H
#include   MLO_H
#include   MPH_H

#include  "support.h"


/*          Alliance CAD System 2.0                               */
/*            FITPATH Package 0.0                                 */
/*                                                                */
/*  Copyright(c) 93-94, MASI, CAO-VLSI Team                       */
/*                                                                */
/*  Author      :          Jean-Paul CHAPUT                       */
/*  E-mail      :      cao-vlsi@masi.ibp.fr                       */
/* -------------------------------------------------------------- */
/*  Module      :      "support.c"                                */


/* Module internal structures. */
/* Structure holding an element of the logical stack. */
typedef struct {
	lofig_list *LoFigFather; /* The current model (lofig). */
	loins_list *LoInsSon;    /* The next instance (loins). */
	} TypeState;


/* Module internal constants. */
#define        IC_SUPP_MaxLoStack        256


/* Variables globales internes au module. */
static error_list *TABL_ERROR  = (error_list*)NULL;
static warng_list *TABL_WARNG  = (warng_list*)NULL;
static arglc_list *TABL_ARGLC  = (arglc_list*)NULL;
static       char *TABL_SIDE[] = {"DEFAULT",
								  "NORTH"  ,
								  "SOUTH"  ,
								  "EAST"   ,
								  "WEST"   };
static       char *TABL_TYPE[] = {"TERMINAL",
								  "BLOCK"   };
static       void *(*TabFcDupPhUser[C_SUPP_UserMaxTdupl])();
static       long    TabTpDupPhUser[C_SUPP_UserMaxTdupl];
static       long         DupPhUserNB = 0;
static       void *(*TabFcDupLoUser[C_SUPP_UserMaxTdupl])();
static       long    TabTpDupLoUser[C_SUPP_UserMaxTdupl];
static       long         DupLoUserNB = 0;
static       long     LoStackPoint;
static  TypeState     LoStackState[IC_SUPP_MaxLoStack];
static       char  Dut_StringBuffer[C_SUPP_MaxLenString];


/* Variables externes definies dans le module. */
       long  DP_WIDTH;
       long  DP_LGSIZE;
       char  DP_SEPAR = '_';
       char  DP_IC[C_SUPP_MBKSZNAME] = "_ic";


/* Fonctions d'interface du module :
   extern        void  Dut_AddError();
   extern        void  Dut_PrintError();
   extern        void  Dut_AddWarng();
   extern        void  Dut_PrintWarng();
   extern        void  Dut_WarngSupport();
   extern        void  Dut_ErrorArgLc();
   extern        void  Dut_AddArgLc();
   extern        void  Dut_SetArgLc();
   extern        long  Dut_GetArgLcFlag();
   extern        char *Dut_GetArgLcValue();
   extern        void  Dut_PrintArgLc();
   extern        void  Dut_InitSupport();   
   extern        long *Dut_XlAlloc();
   extern        void  Dut_XlSetLong();
   extern        void  Dut_XlFree();
   extern        long  Dut_XlGetBit();
   extern        long  Dut_XlStrCheck();
   extern        long  Dut_XlStrToXl();
   extern        char *Dut_XlToStr();
   extern        char *Dut_XlToStrVHDL();
   extern        char *Dut_ConcatName();
   extern        char *Dut_CheckName();
   extern char *Dut_DecodMBKSigName(char *aMBKSigName,
								    long *aPtSigIndex);
   extern        char *Dut_MakeImplicitConName();
   extern        char *Dut_MakeCrunchModelName();
   extern        long  Dut_TypeConName();
   extern        void  Dut_HierarchCheck();
   extern        void  Dut_HierarchFlatten();
   extern  lofig_list *Dut_LoadLoFig();
   extern  ptype_list *Dut_GetLoUser();
   extern  ptype_list *Dut_DelLoUser();
   extern        long  Dut_SetLoUser();
   extern        void  Dut_DupLoUser();
   extern  ptype_list *Dut_GetPhUser();
   extern  ptype_list *Dut_DelPhUser();
   extern        long  Dut_SetPhUser();
   extern        void  Dut_DupPhUser();
   extern udpdata     *Dut_AddUdpData();
   extern udpcon_list *Dut_AddUdpCon();
   extern        void  Dut_LoadUdp();
   extern        void  Dut_SaveUdp();
   extern        void  Dut_MovLsPhCon();
   extern  locon_list  Dut_GetLoConBySig(lofig_list *aLoFig,
                                         losig_list *aLoSig);
*/


/* Macros definitions of the module. */

/* Convert a long integer to an alphanumerical digit. */
#define  DutMC_LToDigit(vdigit)                  \
	( ((vdigit) > 9) ? ((char)((vdigit)-10)+'a') \
	                 : ((char)((vdigit)   )+'0') )
/* Convert a side in a string. */
#define  DutMC_SideToStr(aside)  ( TABL_SIDE[(int)(aside)] )

#define  DutMC_TypeToStr(atype)  ( TABL_TYPE[(int)(atype)] )


/* Definition of module internal functions. */
static       long  Dut_DigitToL();
static       void  Dut_ResetLoStack();
static       void  Dut_PushLoState();
static       void  Dut_PopLoState();
static       long  Dut_IsPhantom();
static       long  Dut_TypeModelName();
static       long  Dut_IsModelLeafCell();
static       long  Dut_IsModelColumn();
static       long  Dut_IsModelCluster();
static       char  Dut_StrToType();
static       char  Dut_StrToSide();
static phcon_list *Dut_MovPhCon();


/*  Fonction  :  'Dut_AddError'.                                  */
/* -------------------------------------------------------------- */
/*  Addition d'une nouvelle erreur.                               */

extern void  Dut_AddError(error_type,error_code,error_mess)
	long  error_type;
	long  error_code;
	char *error_mess;
{
	error_list *pNEW;

	/* Allocation de la nouvelle erreur. */
	pNEW = (error_list*)mbkalloc( sizeof(error_list));
	pNEW->MESS = (char*)mbkalloc( sizeof(char)*strlen(error_mess)+1);

	/* Remplissage de la nouvelle erreur. */
	pNEW->TYPE = error_type;
	pNEW->CODE = error_code;
	strcpy( pNEW->MESS, error_mess);

	/* Chainage de la nouvelle erreur. */
	pNEW->NEXT = TABL_ERROR;
	TABL_ERROR = pNEW;
}


/*  Function  :  'Dut_PrintError'.                                */
/* -------------------------------------------------------------- */
/*  Print error and exit.                                         */

extern void  Dut_PrintError(va_alist)
	va_dcl
{
		  long  error_type;
		  long  error_code;
	   va_list  args_f;
	error_list *pterror;

	/* Print all the "stdout" remainings messages. */
	fflush( stdout);

	fprintf( stderr, "Error: ");

	va_start( args_f);
	/* get arguments. */
	error_type = va_arg( args_f, long);
	error_code = va_arg( args_f, long);

	/* Recherche de l'erreur a partir de son code. */
	for(pterror=TABL_ERROR; pterror != (error_list*)NULL;
							pterror  = pterror->NEXT    )
		if (   (error_type == pterror->TYPE)
			&& (error_code == pterror->CODE))
			{
			/* Print error massage. */
			vfprintf( stderr, pterror->MESS, args_f);
			fputs( "\n", stderr);

			va_end( args_f);
			exit( error_code);
			}

	/* Le code d'erreur n'as pas ete trouve. */

	if (TABL_ERROR == (error_list*)NULL)
		{
		/* La table d'erreur est vide. */
		fputs( "Empty error table.", stderr);
		fputs( "\n"                , stderr);

		va_end( args_f);
		exit( E_SUPP_NOERR);
		}
	else
		{
		/* L'erreur n'est pas repertorie dans la table. */
		fprintf( stderr, "Unknow error code: %ld\n", error_code);
		fputs( "\n", stderr);

		va_end( args_f);
		exit( E_SUPP_UNKERR);
		}
}


/*  Fonction  :  'Dut_AddWarng'.                                  */
/* -------------------------------------------------------------- */
/*  Addition d'un nouvel avertissement.                           */

extern void  Dut_AddWarng(warng_type,warng_code,warng_mess)
	long  warng_type;
	long  warng_code;
	char *warng_mess;
{
	warng_list *pNEW;

	/* Allocation de la nouvelle erreur. */
	pNEW = (warng_list*)mbkalloc( sizeof(warng_list));
	pNEW->MESS = (char*)mbkalloc( sizeof(char)*strlen(warng_mess)+1);

	/* Remplissage de la nouvelle erreur. */
	pNEW->TYPE = warng_type;
	pNEW->CODE = warng_code;
	strcpy( pNEW->MESS, warng_mess);

	/* Chainage de la nouvelle erreur. */
	pNEW->NEXT = TABL_WARNG;
	TABL_WARNG = pNEW;
}


/*  Fonction  :  'Dut_PrintWarng'.                                */
/* -------------------------------------------------------------- */
/*  Affichage d'un avertissement.                                 */

extern void  Dut_PrintWarng(va_alist)
	va_dcl
{
		  long  warng_type;
		  long  warng_code;
	   va_list  args_f;
	warng_list *ptwarng;

	/* Print all the "stdout" remainings messages. */
	fflush( stdout);

	fprintf( stderr, "Warning: ");

	/* Recuperation des arguments. */
	va_start( args_f);

	/* Recuperation du premier argument. */
	warng_type = va_arg( args_f, long);
	warng_code = va_arg( args_f, long);

	/* Recherche de l'erreur a partir de son code. */
	for(ptwarng=TABL_WARNG; ptwarng != (warng_list*)NULL;
							ptwarng  = ptwarng->NEXT    )
		if (   (warng_type == ptwarng->TYPE)
			&& (warng_code == ptwarng->CODE))
		{
			/* Affichage de l'erreur. */
			vfprintf( stderr, ptwarng->MESS, args_f);
			fputs( "\n", stderr);

			va_end( args_f);
			return;
		}

	/* Le code d'erreur n'as pas ete trouve. */

	if (TABL_WARNG == (warng_list*)NULL)
	{
		/* La table d'avertissement est vide. */
		fputs( "Empty warning table.", stderr);
		fputs( "\n"                  , stderr);

		va_end( args_f);
		exit( W_SUPP_NOWARN);
	}
	else
	{
		/* L'erreur n'est pas repertorie dans la table. */
		fprintf( stderr, "Unknow warning code : %ld\n", warng_code);
		fputs( "\n", stderr);

		va_end( args_f);
		exit( W_SUPP_UNKWARN);
	}
}


/*  Function  :  'Dut_WarngSupport'.                              */
/* -------------------------------------------------------------- */
/*  Add support module specific warnings.                         */

extern void  Dut_WarngSupport()
{
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_HiddenHLevel,
	"*** HCheck ***:There is a hidden level (model:%s/instance:%s).");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_ColumnEmpty,
	"*** HCheck ***:Column model \"%s\" has no instance.");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_ColumnMixed,
"*** HCheck ***:Instance \"%s\" of model \"%s\" in column \"%s\" is not a leaf cell.");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_ColumnUnexpectedLeafCell,
	"*** HCheck ***:Column expected as place of leaf cell model:%s.");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_FlattenLeafCell,
	"*** HFlatten ***:model \"%s\":A leaf cell cannot be flattened.");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_FlattenColumn,
	"*** HFlatten ***:model \"%s\":A column cannot be flattened.");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_XlStrNullPtr,
	"*** support ***:%s:NULL pointer passed as string argument.");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_XlStrOverflow,
	"*** support ***:XlStrCheck:Constant string overflow:\"%s\".");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_InvalidDigit,
	"*** support ***:DigitToL:Invalid digit \'%c\'.");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_IllegalDigit,
	"*** support ***:StrNumCheck:Illegal digit \'%c\' (string %s:base %ld).");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_MovConUnknow,
	"*** support ***:MovPhCon:No physical connector \"%s\" in model \"%s\".");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_ConSideIllegal,
"*** support ***:%s:Invalid side '%c' for connector \"%s\" in model \"%s\".");
	Dut_AddWarng( W_SUPP_WARNG, W_SUPP_MovPhConUnable,
"*** support ***:MovPhCon:Unable to move connector \"%s\" of model \"%s\".");
}


/*  Function  :  'Dut_ErrorSupport'.                              */
/* -------------------------------------------------------------- */
/*  Add support module specific warnings.                         */

extern void  Dut_ErrorSupport()
{
	Dut_AddError( E_SUPP_ERROR, E_SUPP_StackOverflow,
	"*** PushLoState ***:Stack overflow:more than %ld levels.");
	Dut_AddError( E_SUPP_ERROR, E_SUPP_StackUnderflow,
	"*** PopLoState ***:Stack underflow:less than 0 levels.");

	Dut_AddError( E_SUPP_ERROR, E_SUPP_ConDupName,
	"*** AddUdpCon ***:Duplicate connector name:\"%s\".");
	Dut_AddError( E_SUPP_ERROR, E_SUPP_ConGetLoFig,
	"*** %s ***:Logical figure \"%s\" not found.");
	Dut_AddError( E_SUPP_ERROR, E_SUPP_ConGetPhFig,
	"*** %s ***:Physical figure \"%s\" not found.");
	Dut_AddError( E_SUPP_ERROR, E_SUPP_OpenUdp,
	"*** %s ***:File \"%s.udp\" not found.");
	Dut_AddError( E_SUPP_ERROR, E_SUPP_ParserSyntax,
	"*** LoadUdp ***:Syntax error line %ld.\n(%s)");
}


/*  Fonction  :  'Dut_ErrorArgLc'.                                 */
/* -------------------------------------------------------------- */
/*  Addition des erreurs specifiques a la gestion des arguments.  */

extern void  Dut_ErrorArgLc()
{
	/* Inclusion des erreurs dans la table. */
	Dut_AddError( E_SUPP_ERROR, E_SUPP_ARGGET,
				  "Duplicate call of Dut_GetArg.");
	Dut_AddError( E_SUPP_ERROR, E_SUPP_BADARG,
				  "Invalid argument \"%s\".");
	Dut_AddError( E_SUPP_ERROR, E_SUPP_DUPARG,
				  "Duplicated argument \"%s\".");
	Dut_AddError( E_SUPP_ERROR, E_SUPP_MISSARG, 
				  "Missing argument.");
	Dut_AddError( E_SUPP_ERROR, E_SUPP_DUPNAMEARG, 
				  "Double definition of argument \"%s\".");
	Dut_AddError( E_SUPP_ERROR, E_SUPP_DUPPOSARG,
				  "Two arguments at the same position : %ld & %ld.");
}


/*  Fonction  :  'Dut_AddArgLc'.                                  */
/* -------------------------------------------------------------- */
/*  Addition d'un argument a la table des arguments.              */

extern void  Dut_AddArgLc(arglc_type,arglc_pos,arglc_name)
	long  arglc_type;
	long  arglc_pos ;
	char *arglc_name;
{
	arglc_list *pNEW, *pCURR;

	/* Verification de non-redondance des arguments. */
	for( pCURR  = TABL_ARGLC       ;
		 pCURR != (arglc_list*)NULL; 
		 pCURR  = pCURR->NEXT      )
		{
		if (   (         0 != arglc_pos)
			 &&(pCURR->POS == arglc_pos))
			Dut_PrintError( E_SUPP_ERROR, E_SUPP_DUPPOSARG,
						    arglc_pos, pCURR->POS);

		if (strcmp(pCURR->NAME,arglc_name) == 0)
			Dut_PrintError( E_SUPP_ERROR, E_SUPP_DUPNAMEARG,
						    arglc_name);
		}

	/* Allocation du nouvel element de la liste. */
	pNEW = (arglc_list*)mbkalloc( sizeof(arglc_list));
	pNEW->NAME = (char*)mbkalloc( sizeof(char)*strlen(arglc_name)+1);

	/* Affectation et initialisation des divers champs. */
	pNEW->TYPE  = arglc_type;
	pNEW->POS   = arglc_pos;
	pNEW->FLAG  = FALSE;
	pNEW->VALUE = (char*)NULL;
	strcpy( pNEW->NAME, arglc_name);

	/* Addition du nouvel element a la liste. */
	pNEW->NEXT = TABL_ARGLC;
	TABL_ARGLC = pNEW;
}


/*  Fonction  :  'Dut_SetArgLc'.                                  */
/* -------------------------------------------------------------- */
/*      Lecture des arguments de la ligne de commande et mise
	dans la table.
	*/

extern void  Dut_SetArgLc(largc,largv)
	 int  largc;
	char *largv[];
{
	static        int  recall = FALSE;

				  int  i, flag;
		   arglc_list *ptarglc;

	/* Lecture des arguments deja faite ? */
	if (recall == TRUE) Dut_PrintError( E_SUPP_ARGGET);

	recall = TRUE;

	/* Boucle sur les arguments de la ligne de commande. */
	for( i=1; i<largc; i++)
		{
		flag = FALSE;

		/* Acquisition des arguments a position fixes. */
		for( ptarglc = TABL_ARGLC; ptarglc != (arglc_list*)NULL;
								   ptarglc  = ptarglc->NEXT    )
			{
			/* Recherche de l'argument fixe. */
			if (ptarglc->POS != i) continue;

			switch( ptarglc->TYPE )
				{
				case C_SUPP_ARGLC_SW :
					if (largv[i][0] != '-')
						Dut_PrintError( E_SUPP_ERROR, E_SUPP_BADARG,
									    largv[i]);

					/* Reconnaissance des options. */
					if (!strcmp(ptarglc->NAME,largv[i]+1))
						{
						/* Detection des options dupliquees. */
						if (ptarglc->FLAG == TRUE)
							Dut_PrintError( E_SUPP_ERROR,
										    E_SUPP_DUPARG, largv[i]);

						/* Armement du drapeau indiquant la lecture. */
						ptarglc->FLAG = flag = TRUE;
						}
					break;
				case C_SUPP_ARGLC_VL :
					ptarglc->VALUE = &(largv[i][0]);

					/* Armement du drapeau indiquant la lecture. */
					ptarglc->FLAG = flag = TRUE;
					break;
				}
			}
		/* Si l'argument a ete reconnu, passage au suivant. */
		if (flag == TRUE) continue;
		
		/* Boucle sur la table des arguments a position flottante. */
		for( ptarglc = TABL_ARGLC; ptarglc != (arglc_list*)NULL;
								   ptarglc  = ptarglc->NEXT    )
			{
			/* Elimination des arguments a position fixe. */
			if (ptarglc->POS != C_SUPP_ARGLC_FLOATPOS) continue;

			if (largv[i][0] != '-')
				Dut_PrintError( E_SUPP_ERROR, E_SUPP_BADARG, largv[i]);

			/* Reconnaissance des options. */
			if (!strcmp(ptarglc->NAME,largv[i]+1))
				{
				/* Detection des options dupliquees. */
				if (ptarglc->FLAG == TRUE)
					Dut_PrintError( E_SUPP_ERROR,
								    E_SUPP_DUPARG, largv[i]);

				/* Armement du drapeau indiquant la lecture. */
				ptarglc->FLAG = flag = TRUE;

				/* Enregistrement des options. */
				switch( ptarglc->TYPE )
					{
					case C_SUPP_ARGLC_SW :
						break;
					case C_SUPP_ARGLC_VL :
						/* Lecture de l'argument suivant. */
						if (largc == i+1)
							Dut_PrintError( E_SUPP_ERROR,
										    E_SUPP_MISSARG);

						ptarglc->VALUE = &(largv[++i][0]);
						break;
					}

				break;
				}
			}

		/* L'argument n'est pas dans le table. */
		if (flag == FALSE)
			Dut_PrintError( E_SUPP_ERROR ,
						    E_SUPP_BADARG, largv[i]);
		}
}


/*  Fonction  :  'Dut_GetArgLcFlag'.                              */
/* -------------------------------------------------------------- */
/*  Recuperation du flag (lu/non-lu) d'un argument.               */

extern long  Dut_GetArgLcFlag(arglc_name)
	char *arglc_name;
{
	arglc_list *ptarglc;

	/* Recherche de l'argument. */
	for( ptarglc=TABL_ARGLC; ptarglc != (arglc_list*)NULL;
							 ptarglc  = ptarglc->NEXT    )
		if (!strcmp(ptarglc->NAME,arglc_name))
			return( ptarglc->FLAG);

	/* Si l'argument n'est pas trouve, on renvoi FALSE. */
	return( FALSE);
}


/*  Fonction  :  'Dut_GetArgLcValue'.                             */
/* -------------------------------------------------------------- */
/*  Recuperation du flag (lu/non-lu) d'un argument.               */

extern char *Dut_GetArgLcValue(arglc_name)
	char *arglc_name;
{
	arglc_list *ptarglc;

	/* Recherche de l'argument. */
	for( ptarglc=TABL_ARGLC; ptarglc != (arglc_list*)NULL;
							 ptarglc  = ptarglc->NEXT    )
		if (!strcmp(ptarglc->NAME,arglc_name))
			return( ptarglc->VALUE);

	/* Si l'argument n'est pas trouve, on renvoi NULL. */
	return( (char*)NULL);
}


/*  Fonction  :  'Dut_PrintArgLc'.                                */
/* -------------------------------------------------------------- */
/*  Affichage de l'etat d'un argument.                            */

extern void  Dut_PrintArgLc(arglc_name)
	char *arglc_name;
{
	arglc_list *ptarglc;

	/* Recherche de l'argument dans la table (par son nom). */
	for( ptarglc=TABL_ARGLC; ptarglc != (arglc_list*)NULL;
							 ptarglc  = ptarglc->NEXT    )
		if (!strcmp(ptarglc->NAME, arglc_name))
			{
			/* Affichage du nom de l'argument. */
			printf( "Argument:%10s:", ptarglc->NAME);

			/* Affichage du type. */
			switch( ptarglc->TYPE )
				{
				case C_SUPP_ARGLC_SW :
					printf( "switch:");
					break;
				case C_SUPP_ARGLC_VL :
					printf( "option:");
					break;
				default :
					printf( "unknow:");
				}

			/* Affichage de l'etat du flag. */
			switch( ptarglc->FLAG )
				{
				case TRUE :
					printf( "    read:");
					break;
				case FALSE :
					printf( "not read:");
					break;
				}

			/* Dans le cas des options, affichage de la valeur. */
			if (ptarglc->VALUE != (char*)NULL)
				printf( "%s\n", ptarglc->VALUE);
			else
				puts( "NULL");

			return;
			}

	/* L'argument n'as pas ete trouve. */
	printf( "Argument:%10s:inconnu.\n", arglc_name);
}


/*  Function  :  'Dut_InitSupport'.                               */
/* -------------------------------------------------------------- */
/*  Sets alls "supports" module internals variables and tables.   */

extern void  Dut_InitSupport()
{
	static  FirstCall = TRUE;

	if (FirstCall)
	{
	    /* Detect the size of a long integer. */
	    DP_LGSIZE = sizeof( long);

		/* Load internal module errors and warnings tables. */
		Dut_ErrorSupport();
		Dut_WarngSupport();

		FirstCall = FALSE;
	}
}


/*  Function  : 'Dut_DigitToL'                                    */
/* -------------------------------------------------------------- */

static long  Dut_DigitToL(cdigit)
	char  cdigit;
{
	if ((cdigit >= '0') && (cdigit <= '9')) return( (long)(cdigit-'0'   ));
	if ((cdigit >= 'a') && (cdigit <= 'f')) return( (long)(cdigit-'a'+10));
	if ((cdigit >= 'A') && (cdigit <= 'F')) return( (long)(cdigit-'A'+10));

	/* Unrecognized digit case. */
	Dut_PrintWarng( W_SUPP_WARNG, W_SUPP_InvalidDigit, cdigit);

	return( 0);
}


/*  Function  : 'Dut_XlAlloc'                                     */
/* -------------------------------------------------------------- */
/*  Allocate an extended long integer.                            */

extern long *Dut_XlAlloc()
{
	long *Xlong;
	long  Offset;

	Xlong = (long*)mbkalloc(sizeof(long)*C_SUPP_XLSIZE);
	for(Offset=0; Offset < C_SUPP_XLSIZE; Offset++)
		Dut_XlSetLong(Xlong, Offset, 0L);

	return(Xlong);
}


/*  Function  : 'Dut_XlFree'                                      */
/* -------------------------------------------------------------- */
/*  Free memory allocated to an extended long integer.            */

extern void  Dut_XlFree(aPtXlong)
	long *aPtXlong;
{ mbkfree( (void*)aPtXlong ); }


/*  Function  : 'Dut_XlSetLong'                                   */
/* -------------------------------------------------------------- */
/*  Set one long inside an extended long.                         */

extern void  Dut_XlSetLong(aPtXlong,aLong,aValue)
	long *aPtXlong;
	long  aLong;
	long  aValue;
{
	/* Check if the long is whithin the correct range. */
	if (  (aLong >= C_SUPP_XLSIZE)
		||(aLong <  0)           )
		return;

	aPtXlong[aLong] = aValue;
}


/*  Function  : 'Dut_XlGetBit'                                    */
/* -------------------------------------------------------------- */
/*  Return the value of the specified bit of an extended long.    */

extern long  Dut_XlGetBit(aPtXlong,aBit)
	long *aPtXlong;
	long  aBit;
{
	/* Check if the bit is whitin the valid range. */
	if (aBit > C_SUPP_XLSIZE*DP_LGSIZE*8) return( 0L);

	return( ( aPtXlong[aBit/(DP_LGSIZE*8)]
			 &(1L  << (aBit%(DP_LGSIZE*8))) ) ? 1L : 0L);
}


/*  Function  : 'Dut_XlStrCheck'                                  */
/* -------------------------------------------------------------- */

extern long  Dut_XlStrCheck(aStringNumber)
	char *aStringNumber;
{
	long  BaseValue;
	long  BaseDigitMax;
	long  StringIndex;
	long  StringStart;
	long  CheckFlag;

	/* Detect NULL pointer passed as argument. */
	if (aStringNumber == (char*)NULL)
	{
		Dut_PrintWarng( W_SUPP_WARNG, W_SUPP_XlStrNullPtr,
					    "Dut_XlStrCheck");

		return( 0);
	}

	/* Recognize the base number, depending on the first two */
	/* digits :                                              */
	/*         -  "0nnnn" : Octal.                           */
	/*         - "0Bnnnn" : Binary.                          */
	/*         - "0Xnnnn" : Hexadecimal.                     */
	if (   (aStringNumber[0] != (char)0 )
		 &&(aStringNumber[1] != (char)0 )
		 &&(aStringNumber[0] ==      '0'))
		switch( aStringNumber[1] )
		{
			case 'b':
		    case 'B': 
			      BaseValue = C_SUPP_BaseBinary;
				StringStart = 2;
				break;
			case 'x':
		    case 'X':
				  BaseValue = C_SUPP_BaseHexadecimal;
				StringStart = 2;
				break;
			default:
				  BaseValue = C_SUPP_BaseOctal;
				StringStart = 1;
		}
	else
	{
		  BaseValue = C_SUPP_BaseHexadecimal;
		StringStart = 0;
	}

	/* Set the of the maximum digit value. */
	BaseDigitMax = 1L << BaseValue;

	/* Get the end of the string. */
	StringIndex = strlen(aStringNumber)-1;

	/* Check the digits of the string number (from rigth to left). */
	for(CheckFlag=TRUE; StringIndex >= StringStart; StringIndex--)
		if (Dut_DigitToL(aStringNumber[StringIndex]) >= BaseDigitMax)
		{
			Dut_PrintWarng( W_SUPP_WARNG, W_SUPP_IllegalDigit,
						           aStringNumber[StringIndex],
						           aStringNumber             ,
						           BaseDigitMax              );

			CheckFlag = FALSE;
		}

	/* Compute the number of long neededs to encode the      */
	/* string and check if it is less than an extended long. */
	if (   (strlen(aStringNumber)-StringStart)*BaseValue
		 > (C_SUPP_XLSIZE*DP_LGSIZE*8)                  )
		Dut_PrintWarng( W_SUPP_WARNG, W_SUPP_XlStrOverflow,
					    aStringNumber);

	return( CheckFlag);
}


/*  Function  : 'Dut_XlStrtToXl'                                  */
/* -------------------------------------------------------------- */

extern void  Dut_XlStrToXl(aStringNumber,aPtXlong)
	char *aStringNumber;
	long *aPtXlong;
{
	long  BaseValue;
	long  StringIndex;
	long  NumberWidth;
	long  DigitValue;

	/* Detect NULL pointer passed as argument. */
	if (aStringNumber == (char*)NULL)
		Dut_PrintWarng( W_SUPP_WARNG, W_SUPP_XlStrNullPtr,
					    "Dut_XlStrToLl");

	/* Recognize the base number, depending on the first two */
	/* digits :                                              */
	/*         -  "0nnnn" : Octal.                           */
	/*         - "0Bnnnn" : Binary.                          */
	/*         - "0Xnnnn" : Hexadecimal.                     */
	if (   (aStringNumber[0] != (char)0 )
		 &&(aStringNumber[1] != (char)0 )
		 &&(aStringNumber[0] ==      '0'))
		switch( aStringNumber[1] )
		{
			case 'b':
		    case 'B': 
			      BaseValue = C_SUPP_BaseBinary;
				StringIndex = 2;
				break;
			case 'x':
		    case 'X':
				  BaseValue = C_SUPP_BaseHexadecimal;
				StringIndex = 2;
				break;
			default:
				  BaseValue = C_SUPP_BaseOctal;
				StringIndex = 1;
		}
	else
	{
		  BaseValue = C_SUPP_BaseHexadecimal;
		StringIndex = 0;
	}


	/* Read the string digit by digit from left to right. */
	for( NumberWidth = 0;   (aStringNumber[StringIndex] != (char)0)
		                  &&(NumberWidth < DP_LGSIZE*8*C_SUPP_XLSIZE);
		 StringIndex += 1,
		 NumberWidth += BaseValue)
	{
		/* Convert the digit. */
		DigitValue = Dut_DigitToL(aStringNumber[StringIndex]);

		/* Shift the sum then add the digit value. */
		aPtXlong[NumberWidth/(DP_LGSIZE*8)] <<=  BaseValue;
		aPtXlong[NumberWidth/(DP_LGSIZE*8)]  |= DigitValue;
	}
}


/*  Function  : 'Dut_XlToStr'                                     */
/* -------------------------------------------------------------- */
/*  Convert an extended long into an hexadecimal constant string. */

extern char *Dut_XlToStr(aPtXlong,aConstWidth,aBaseValue)
	long *aPtXlong;
	long  aConstWidth;
	long  aBaseValue;
{
	long  StringIndex;
	long  NumberIndex;

	for( NumberIndex  = aConstWidth + 4
		             - (  (aConstWidth%C_SUPP_BaseHexadecimal)
					    ? (aConstWidth%C_SUPP_BaseHexadecimal) : 4),
		 StringIndex  = 0;
		 NumberIndex >  0;
		 NumberIndex -= C_SUPP_BaseHexadecimal,
		 StringIndex += 1)
		Dut_StringBuffer[StringIndex] = DutMC_LToDigit(
			(    aPtXlong[(NumberIndex-4)/(DP_LGSIZE*8)]
			  >>         ((NumberIndex-4)%(DP_LGSIZE*8)) ) & 15L);

	Dut_StringBuffer[StringIndex] = (char)0;

	return( Dut_StringBuffer);
}


/*  Function  : 'Dut_XlToStrVHDL'                                 */
/* -------------------------------------------------------------- */
/*  Convert an extended long into a VHDL constant string.         */

extern char *Dut_XlToStrVHDL(aPtXlong,aConstWidth)
	long *aPtXlong;
	long  aConstWidth;
{
	long  StringIndex;
	long  NumberIndex;
	long    FlagBinary;

	  FlagBinary = FALSE;
	StringIndex  = 0;
	NumberIndex  = (aConstWidth > 128) ? 128 : aConstWidth;

	/* Convert the head of the constant, no more than 3 bits. */
	if (NumberIndex%C_SUPP_BaseHexadecimal)
	{
	    strcpy( Dut_StringBuffer+StringIndex, "B\"");

		for( StringIndex                        += 2;
			 NumberIndex%C_SUPP_BaseHexadecimal >= C_SUPP_BaseBinary;
			 NumberIndex                        -= C_SUPP_BaseBinary,
			 StringIndex                        += 1)
		    Dut_StringBuffer[StringIndex] = DutMC_LToDigit(
				(    aPtXlong[NumberIndex/(DP_LGSIZE*8)]
				 >>          (NumberIndex%(DP_LGSIZE*8)) ) & 1L);

		FlagBinary = TRUE;
	}
		
	/* Convert the first digits into an hexadecimal constant. */
	if (NumberIndex >= C_SUPP_BaseHexadecimal)
	{
	    if (FlagBinary)
		{
	        strcpy( Dut_StringBuffer+StringIndex, "\" & ");
			StringIndex += 4;
		}

	    strcpy( Dut_StringBuffer+StringIndex, "X\"");

		for( StringIndex += 2;
			 NumberIndex >= C_SUPP_BaseHexadecimal;
			 NumberIndex -= C_SUPP_BaseHexadecimal,
			 StringIndex += 1)
		{
		    Dut_StringBuffer[StringIndex] = DutMC_LToDigit(
			   (    aPtXlong[(NumberIndex-4)/(DP_LGSIZE*8)]
				 >>         ((NumberIndex-4)%(DP_LGSIZE*8)) ) & 15L);

		    puts( Dut_StringBuffer);
		}
	}

	/* Write the end of the constant. */
	strcpy( Dut_StringBuffer+StringIndex, "\"");

	puts( Dut_StringBuffer);

	/* Return the generated string. */
	return( Dut_StringBuffer);
}


/*  Function  : 'Dut_ResetLoStack'                                */
/* -------------------------------------------------------------- */
/*  Reset the logical state by setting his pointer to zero.       */

static void  Dut_ResetLoStack()
{ LoStackPoint = 0L; }


/*  Function  : 'Dut_PushLoState'                                 */
/* -------------------------------------------------------------- */
/*  Push a logical state to the (logical) stack.                  */

static void  Dut_PushLoState(LoFigFather,
							 LoInsSon   )
	lofig_list *LoFigFather; /* The current logical model. */
	loins_list *LoInsSon;    /* The next logical instance. */
{
	/* Test stack overflow. */
	if (LoStackPoint == IC_SUPP_MaxLoStack)
		Dut_PrintError( E_SUPP_ERROR        ,
					    E_SUPP_StackOverflow,
					    LoStackPoint        );

	LoStackState[LoStackPoint].LoFigFather = LoFigFather;
	LoStackState[LoStackPoint].LoInsSon    = LoInsSon;

	LoStackPoint++;
}


/*  Function  : 'Dut_PopLoState'                                  */
/* -------------------------------------------------------------- */
/*  Pop a logical state from the (logical) stack.                 */

static void  Dut_PopLoState(PtLoFigFather,
							PtLoInsSon   )
	lofig_list  **PtLoFigFather; /* Pointer to the current logical model. */
	loins_list  **PtLoInsSon;    /* Pointer to the next logical instance. */
{
	/* Test stack underflow. */
	if (LoStackPoint == 0)
		Dut_PrintError( E_SUPP_ERROR         ,
					    E_SUPP_StackUnderflow);

	LoStackPoint--;

	*PtLoFigFather = LoStackState[LoStackPoint].LoFigFather;
	*PtLoInsSon    = LoStackState[LoStackPoint].LoInsSon;
}


/*  Fonction  : 'Dut_ConcatName'                                  */
/* -------------------------------------------------------------- */
/*      Concatene deux chaines de caracteres, en utilisant le 
	separateur specifique aux chemins de donnes (construction
	des noms des connecteurs implicites.
		En sus, elle effectue un "namealloc".
	*/

extern char *Dut_ConcatName(name1,name2)
	char *name1;
	char *name2;
{
	static char  StringBuffer[C_SUPP_MBKSZNAME];

	/* Concatenation, utilisant DP_SEPAR (variable globale). */
	sprintf( StringBuffer, "%s%c%s", name1, DP_SEPAR, name2);

	/* Allocation et retour. */
	return( namealloc(StringBuffer));
}


/*  Fonction  : 'Dut_CheckName'                                   */
/* -------------------------------------------------------------- */

extern char *Dut_CheckName(pin_name)
	char *pin_name;
{
	static char  StringBuffer[C_SUPP_MBKSZNAME];
	static long  FirstCall = TRUE;

		   char *pt;
		   long   OpenBracket = FALSE;
		   long  CloseBracket = FALSE;

	/* Au premier appel, initialisation des erreurs. */
	if (FirstCall == TRUE)
		{
		Dut_AddError( E_SUPP_ERROR, E_SUPP_CHECKNAMESpace,
	"Dut_CheckName:invalid signal name, space detect:%s\n");
		Dut_AddError( E_SUPP_ERROR, E_SUPP_CHECKNAMEOpenBracket,
	"Dut_CheckName:invalid signal name, [ unmatched:%s\n");
		Dut_AddError( E_SUPP_ERROR, E_SUPP_CHECKNAMECloseBracket,
	"Dut_CheckName:invalid signal name, ] unmatched:%s\n");

		FirstCall = FALSE;
		}

	/* Recopie de la chaine dans le tampon.       */
	/* (on ne touche pas aux chaines utilisateur) */
	strcpy( StringBuffer, pin_name);

	for( pt=StringBuffer; *pt!=(char)0; pt++)
		{
		/* Verification : recherche des espaces. */
		if (*pt == ' ')
			Dut_PrintError(
					E_SUPP_ERROR,
					E_SUPP_CHECKNAMESpace,
					pin_name
					);

		/* Elimination des crochets ouvrants. */
		if (*pt == '[')
			{
			/* Verification des crochets ouvrants. */
			if (OpenBracket == TRUE)
				Dut_PrintError(
						E_SUPP_ERROR               ,
						E_SUPP_CHECKNAMEOpenBracket,
						pin_name
						);
			else
				OpenBracket = TRUE;

			*pt = ' ';
			}

		/* Elimination des crochets fermants. */
		if (*pt == ']')
			{
			/* Verification des crochets ouvrants. */
			if (CloseBracket == TRUE)
				Dut_PrintError(
						E_SUPP_ERROR                ,
						E_SUPP_CHECKNAMECloseBracket,
						pin_name
						);
			else
				CloseBracket = TRUE;

			*pt = (char)0;
			}
		}

	/* Renvoi de la chaine 'nettoyee'. */
	return( StringBuffer);
}


/*  Function  : 'Dut_DecodMBKSigName'                             */
/* -------------------------------------------------------------- */

extern char *Dut_DecodMBKSigName(aMBKSigName,
								 aPtSigIndex)
	char *aMBKSigName;
	long *aPtSigIndex;
{
	char *PtChar;
	char *PtIndexSepar;
	char  StringBuffer[C_SUPP_MaxLenString];


	strcpy( StringBuffer, aMBKSigName);

	/* Search the last space in the signal name. */
	PtIndexSepar = (char*)NULL;
	for(PtChar = StringBuffer; *PtChar != (char)0; PtChar++)
		if (*PtChar == ' ') PtIndexSepar = PtChar;

	/* Read, if detected, the bus index. */
	if (PtIndexSepar != (char*)NULL)
	{
	     *PtIndexSepar = (char)0;
		*aPtSigIndex   = atol(PtIndexSepar+1);
	}
	else
		*aPtSigIndex = C_SUPP_ImplicitConNoIndex;

	return( StringBuffer);
}


/*  Fonction  :  'Dut_MakeImplicitConName'                        */
/* -------------------------------------------------------------- */
/*      Generation automatique et normalisee des noms de connec-
    teurs implicites. 
	    Les noms sont generes en concatenant dans l'ordre :
		    - le nom d'instance "instname".
			- le separateur MBK : MBK_SEPAR.
			- le nom specifique du connecteur : "conname".
			- l'extention reservee aux connecteurs : DP_IC.
	*/

extern char *Dut_MakeImplicitConName(instname,conname,index)
	char *instname;
	char *conname;
	long  index;
{
	if (index == C_SUPP_ImplicitConNoIndex)
		sprintf( Dut_StringBuffer, "%s%s"    , conname, DP_IC);
	else
		sprintf( Dut_StringBuffer, "%s%s %ld", conname, DP_IC, index);

	return( concatname(instname,Dut_StringBuffer) );			
}


/*  Function  :  'Dut_MakeCrunchModelName'                        */
/* -------------------------------------------------------------- */

extern char *Dut_MakeCrunchModelName(va_alist)
	va_dcl
{
	static char  ModelName[10];

	       char *ArgModelPrefix;
	       long  ArgParamFieldWidth;
	       long  ArgParamFieldValue;
	       long  ArgParamFlags;

	       long     ParamAccuValue;
	       long     ParamAccuWidth;
	       long  BitWeigth;
	    va_list  args_f;

	/* Argument recovery. */
	va_start( args_f);

	/* Get the prefix of the model name. */
	ArgModelPrefix = va_arg( args_f, char*);

	ParamAccuValue = 0;
	ParamAccuWidth = 0;

	/* Reading loop for numericals fields.        */
	/* (encoding all seperate fields in one LONG) */
	while( (ArgParamFieldWidth=va_arg(args_f,long)) )
	{
	    /* Shift the previous sum. */
		ParamAccuValue    <<= ArgParamFieldWidth;

	    /* Get the current parameter value. */
	    ArgParamFieldValue  = va_arg( args_f, long);

		/* Merge the parameter value whith the previous. */
		ParamAccuValue     += ArgParamFieldValue;
		ParamAccuWidth     += ArgParamFieldWidth;
	}
	/* Get the optionnals flags (maximum three bits). */
	ArgParamFlags = va_arg( args_f, long);

	/* Terminate with the argument recovery. */
	va_end( args_f);

	/* Copy the model prefix name. */
	strncpy( ModelName, ArgModelPrefix, 2);

	/* Add the suffix that encode parameters in base 32. */
	/* (digits are '0-9' and 'a-v', they takes 5 bits)   */

	/* First digit : 3 bits of flags plus 2 first bits. */
	ModelName[8] = DutMC_LToDigit(   ((   ParamAccuValue & 3) << 3)
								   |  (ArgParamFlags     & 7)      );
	ParamAccuValue >>= 2;
	/* The next six digits. */
	for( BitWeigth=1; BitWeigth < 7; BitWeigth++)
	{
	    ModelName[8-BitWeigth] = 
			DutMC_LToDigit(ParamAccuValue & 31);
		
		ParamAccuValue >>= 5;
	}

	/* The newly generated model name is returned. */
	return( ModelName);
}


/*  Function  :  'Dut_TypeConName'                                */
/* -------------------------------------------------------------- */
/*  Return the type of connector, according to is name :          */
/*              -  '*_ic' : C_SUPP_TypeConImplicit.               */
/*              - '*vdd*' : C_SUPP_TypeConVdd.                    */
/*              - '*vss*' : C_SUPP_TypeConVss.                    */
/*              - others  : C_SUPP_TypeConNormal.                 */

extern long Dut_TypeConName(conname)
	char *conname; /* Connector name to analys. */
{
	char *PtSuffix = (char)NULL;
	char *PtUnderScore;

	/* First recognize power supplies. */
	if (isvdd(conname)) return( C_SUPP_TypeConVdd);
	if (isvss(conname)) return( C_SUPP_TypeConVss);

	/* Search the last '_' in the name. */
	for( PtUnderScore  =  conname; 
		*PtUnderScore != (char)NULL; PtUnderScore++)
		if (*PtUnderScore == '_') PtSuffix = PtUnderScore+1;

	/* If no underscore found then return the default type. */
	if (PtSuffix == (char*)NULL) return( C_SUPP_TypeConNormal);

	/* Try to match the suffix of an implicit connector. */
	if (!strncmp(PtSuffix,S_SUPP_TypeConImplicit,2))
		return(           C_SUPP_TypeConImplicit);

	/* Default. */
	return( C_SUPP_TypeConNormal);
}


/*  Function  :  'Dut_IsPhantom'                                  */
/* -------------------------------------------------------------- */
/*  Attempt to find on disk the file named "file_name".vst, using
 *  the MBK search path "MBK_CATA_LIB".
 */

static long  Dut_IsPhantom(file_name)
	char *file_name;
{ 
	FILE *StreamPhantom;

	StreamPhantom = mbkfopen(file_name, IN_LO, READ_TEXT);

	if (StreamPhantom == NULL)
		return(1);
	else
	{
	    fclose(StreamPhantom);
		return(0);
	}
}



/*  Function  :  'Dut_TypeModelName'                           */
/* -------------------------------------------------------------- */
/*  Return the type of model, according to is name :              */
/*              -   '*_c' : C_SUPP_TypeModelGenerator.            */
/*              -  '*_fp' : C_SUPP_TypeModelFplib.                */
/*              -  '*_dp' : C_SUPP_TypeModelDplib.                */
/*              -  others : C_SUPP_TypeModelDefault.              */

static long  Dut_TypeModelName(ModelName)
	char *ModelName; /* Connector name to analys. */
{
	char *PtSuffix = (char)NULL;
	char *PtUnderScore;

	/* Search the last '_' in the name. */
	for( PtUnderScore  =  ModelName; 
		*PtUnderScore != (char)NULL; PtUnderScore++)
		if (*PtUnderScore == '_') PtSuffix = PtUnderScore+1;

	/* If no underscore found then return the default type. */
	if (PtSuffix == (char*)NULL) return( C_SUPP_TypeModelDefault);


	/* **** Try to match the suffix of a leaf cell **** */

	/* Suffix of (big) generators such as 'rsa', 'rfg' and 'bsg'. */
	if (!strcmp(PtSuffix,S_SUPP_TypeModelGenerator))
		return(          C_SUPP_TypeModelGenerator);

	/* Suffix of dedicated generator leaf cell. */
	if (!strcmp(PtSuffix,S_SUPP_TypeModelFplib))
		return(          C_SUPP_TypeModelFplib);

	/* Suffix of user and SL leaf cell. */
	if (!strcmp(PtSuffix,S_SUPP_TypeModelDplib))
		return(          C_SUPP_TypeModelDplib);

	/* Default. */
	return( C_SUPP_TypeModelDefault);
}


/*  Function  :  'Dut_IsModelLeafCell'                            */
/* -------------------------------------------------------------- */
/*  Check if a model is a leaf cell.                              */

static long  Dut_IsModelLeafCell(PtLoFig)
	lofig_list *PtLoFig;
{
	/* Check the name and if the LOINS list is empty. */
	switch( Dut_TypeModelName(PtLoFig->NAME) )
	{
	    case C_SUPP_TypeModelGenerator:
	        return( 1);
	    case C_SUPP_TypeModelFplib:
	    case C_SUPP_TypeModelDplib:
			/* Detect instances under leaf cells. */
			if (PtLoFig->LOINS != (loins_list*)NULL)
				Dut_PrintWarng( W_SUPP_WARNG         ,
							    W_SUPP_HiddenHLevel  ,
							    PtLoFig->NAME        ,
							    "\"Under leaf cell\"");
			return( 1);
	    case C_SUPP_TypeModelDefault:
	    default:
	        return( 0);
	}
}


/*  Function  :  'Dut_IsModelColumn'                              */
/* -------------------------------------------------------------- */
/*  Check if a model is a column.                                 */

static long  Dut_IsModelColumn(PtLoFig)
	lofig_list *PtLoFig;
{
	lofig_list *LoFigLeaf;
	loins_list *LoInsLeaf;
	      long  LoFigMode;
	      long  TypeModel;
	      long  ModelLeafFlag;
	      long  ConsistencyFlag;

	/* Check the name of the column. */
	if ((TypeModel=Dut_TypeModelName(PtLoFig->NAME))
		                  != C_SUPP_TypeModelDefault)
		Dut_PrintWarng( W_SUPP_WARNG                   ,
					    W_SUPP_ColumnUnexpectedLeafCell,
					    PtLoFig->NAME                  );

	/* Check if there is some instances. */
	if (PtLoFig->LOINS == (loins_list*)NULL)
	{
	    if (TypeModel == C_SUPP_TypeModelDefault)
			Dut_PrintWarng(W_SUPP_WARNG      ,
						   W_SUPP_ColumnEmpty,
						   PtLoFig->NAME     );

		return( 0);
	}

	/* Check if all the instance models are leaf cells. */
	for(LoInsLeaf=PtLoFig->LOINS; LoInsLeaf != (  loins_list*)NULL;
		                          LoInsLeaf  =    LoInsLeaf->NEXT )
	{
	    /* Get the model of the instance. */
		LoFigMode = (Dut_IsPhantom(LoInsLeaf->FIGNAME)) ? 'P' : 'A';
	    LoFigLeaf = getlofig(LoInsLeaf->FIGNAME,
							 LoFigMode         );

		/* Check if the model is a leaf cell. */
		ModelLeafFlag = Dut_IsModelLeafCell(LoFigLeaf);

		/* Check if there is only one type of models. */
		if (LoInsLeaf == PtLoFig->LOINS)
			ConsistencyFlag = ModelLeafFlag;
		else
			if (ConsistencyFlag != ModelLeafFlag)
			{
			    puts( "Good Mess.");
				Dut_PrintWarng(W_SUPP_WARNG      ,
							   W_SUPP_ColumnMixed,
							   LoInsLeaf->INSNAME,
							   LoInsLeaf->FIGNAME,
							     PtLoFig->NAME   );
				return( 0);
			}
	}

	/* If "ConsistencyFlag" is set to one, this is a column. */
	return( ConsistencyFlag );
}


/*  Function  :  'Dut_IsModelCluster'                             */
/* -------------------------------------------------------------- */
/*  Check if a model is a cluster, by searching an associated
	layout file.
	*/

static long  Dut_IsModelCluster(PtLoFig)
	lofig_list *PtLoFig;
{
	FILE *StreamLayout;

	StreamLayout = mbkfopen( PtLoFig->NAME, IN_PH, READ_TEXT);

	if (StreamLayout == NULL)
		return( 0);
	else
	{
	    fclose( StreamLayout);
		return( 1);
	}
}


/*  Function  :  'Dut_HierarchCheck'                              */
/* -------------------------------------------------------------- */
/*  Check the hierarchical consistency of a data-path.            */

extern void  Dut_HierarchCheck(ptlofig)
	lofig_list *ptlofig;
{
	lofig_list *LoFigFather;
	lofig_list *LoFigSon;
	loins_list *LoInsSon;
	      char  LoFigSonMode;

	LoFigFather = ptlofig;
	LoInsSon    =   LoFigFather->LOINS;

	/* Reset logical stack and push the stop value. */
	Dut_ResetLoStack();
	Dut_PushLoState( (lofig_list*)NULL, (loins_list*)NULL );

	/* Perform the first check of the reccursion.      */

	/* If a cluster is detect, do not attempt to check
	   the hierarchy. */
	if (Dut_IsModelCluster(LoFigFather)) return;

	/* (if a column is detect, terminate the function) */
	if (Dut_IsModelColumn(LoFigFather)) return;

	/* Recursion main loop. */
	while(LoFigFather != (lofig_list*)NULL)
	{
	    /* If all instances have been checked, return to
		   the upper levels. */
		if ( LoInsSon == (loins_list*)NULL )
		{
			Dut_PopLoState( &LoFigFather, &LoInsSon);
			continue;
		}

		/* Check file type on the disk. */
		LoFigSonMode = (Dut_IsPhantom(LoInsSon->FIGNAME)) ? 'P' : 'A';

		/* Get the model of the instance. */
		LoFigSon = getlofig( LoInsSon->FIGNAME, LoFigSonMode);

		/* Analisys of instance model type. */
		if (   !Dut_IsModelCluster(LoFigSon)
			&& !Dut_IsModelColumn( LoFigSon)
			&& (LoFigSon->LOINS != (loins_list*)NULL))
		{
			Dut_PushLoState( LoFigFather, LoInsSon->NEXT);

			LoFigFather = LoFigSon;
			LoInsSon    = LoFigSon->LOINS;
		}
		else
			LoInsSon = LoInsSon->NEXT;
		}
}


/*  Function  :  'Dut_HierarchFlatten'                            */
/* -------------------------------------------------------------- */
/*  Normalize a data-path hierarchy from 'n' levels down to 2.
 *      The order of the instances is significant for the initial
 *  placement step of DPR. The flattening function 'flattenlofig'
 *  add the new instances in end of the LOINS list. So, we must
 *  re-order this list after each flattenning operation.
 *      The MBK separator is temporarily set to '_'. It is neces-
 *  sary for hiding the flattened levels to the placer (the
 *  placer recognize only two levels of hierarchy, with the def-
 *  fault MBK separator '.').
 */

extern void  Dut_HierarchFlatten(ptlofig)
	lofig_list *ptlofig;
{
	lofig_list     *LoFigFather;
	lofig_list     *LoFigSon;
	loins_list **PPtLoInsSon;
	loins_list **PPtLoInsLast;
/*	loins_list   *PtLoInsRot;  */
	loins_list   *PtLoInsTmp;
		  char      LoFigSonMode;
		  char      OldSepar;

	LoFigFather = ptlofig;

	/* For the sub-data-path flattens, the separator to use is '_'. */
	/* This constraints belong to the DPR placer.                   */
	OldSepar = SEPAR; SEPAR = '_';

	/* if a leaf cell is detect, terminate the function. */
	if (Dut_IsModelLeafCell(LoFigFather)) 
	{
		Dut_PrintWarng(W_SUPP_WARNG          ,
					   W_SUPP_FlattenLeafCell,
					   LoFigFather->NAME     );
		return;
	}

	/* if a column is detect, terminate the function. */
	if (Dut_IsModelColumn(LoFigFather))
	{
		Dut_PrintWarng(W_SUPP_WARNG        ,
					   W_SUPP_FlattenColumn,
					   LoFigFather->NAME   );
		return;
	}


	/* Process the complete list of LOINS. */
	for( PPtLoInsSon  = &LoFigFather->LOINS;
		*PPtLoInsSon !=   (loins_list*)NULL;
		 PPtLoInsSon  = &((*PPtLoInsSon)->NEXT))
	{
		/* Looking for the last instance. */
		for( PPtLoInsLast  = &LoFigFather->LOINS;
			*PPtLoInsLast !=   (loins_list*)NULL;
			 PPtLoInsLast  = &((*PPtLoInsLast)->NEXT));

	    /* Check file type on the disk. */
		LoFigSonMode = (Dut_IsPhantom((*PPtLoInsSon)->FIGNAME)) ? 'P' : 'A';

		/* Get the model of the instance. */
		LoFigSon = getlofig((*PPtLoInsSon)->FIGNAME, LoFigSonMode);

		/* Flatten all instance that are not recognized */
		/* as columns or clusters.                      */
		if (      !Dut_IsModelCluster(LoFigSon)
			 &&   !Dut_IsModelColumn( LoFigSon)
			 && ((loins_list*)NULL != LoFigSon->LOINS))
		{
			if ((*PPtLoInsSon)->NEXT == *PPtLoInsLast)
			{
				/* The flattened instance is itself the head of list, */
				/* thus no reordering is necessary.                   */
				flattenlofig(LoFigFather, (*PPtLoInsSon)->INSNAME, YES);
			}
			else
			{
				flattenlofig(LoFigFather, (*PPtLoInsSon)->INSNAME, YES);

				/* Searching the end of the newly inserted instances. */
				/* (done by retrieving the previous loins list head ) */
				for(PtLoInsTmp        = *PPtLoInsLast    ;
					PtLoInsTmp->NEXT != (loins_list*)NULL;
					PtLoInsTmp        =  PtLoInsTmp->NEXT);

				/* Moving the new instances at the rigth place. */
				/* (by swapping some next pointer of the list)  */
				  PtLoInsTmp->NEXT  = *PPtLoInsSon;
				*PPtLoInsSon        = *PPtLoInsLast;
				*PPtLoInsLast       = (loins_list*)NULL;
			}
		}
	}

	/* Restoring the previous value of the MBK separator. */
	SEPAR = OldSepar;
}


/*  Function  :  'Dut_LoadLoFig'                                  */
/* -------------------------------------------------------------- */

extern lofig_list *Dut_LoadLoFig(aModelName)
	char *aModelName;
{
	lofig_list *PtLoFig;
	      char    LoFigMode;

	/* Check file type on the disk. */
	LoFigMode = (Dut_IsPhantom(aModelName)) ? 'P' : 'A';

	/* Get the model of the instance. */
	PtLoFig = getlofig(aModelName, LoFigMode);

	/* Check the specific data-path hierarchy consistency. */
	Dut_HierarchCheck(PtLoFig);

	return(PtLoFig);
}


/*  Function  :  'Dut_GetLoUser'                                  */
/* -------------------------------------------------------------- */

extern ptype_list *Dut_GetLoUser(aPtFig,aType,aFlags)
    lofig_list *aPtFig;
          long  aType;
		  long  aFlags;
{
    ptype_list *pt;


    /* Search the element of type "aType" in USER ptype list. */
    if ((pt=getptype(aPtFig->USER,aType)) != (ptype_list*)NULL)
        return( pt);

	/* If not found, create it if asked. */ 
    if ( aFlags & F_SUPP_UCREAT ) 
	{
        aPtFig->USER = addptype(aPtFig->USER,aType,(void*)NULL);

        return(aPtFig->USER);
    }
    else
        return((ptype_list*)NULL);
}


/*  Function  :  'Dut_DelLoUser'                                  */
/* -------------------------------------------------------------- */

extern ptype_list *Dut_DelLoUser( aPtFig, aType, aFlags)
    lofig_list *aPtFig;
          long  aType;
		  long  aFlags;
{
    /* Destruction of element that match "aType". */
    return(aPtFig->USER = delptype(aPtFig->USER,aType));
}


/*  Function  :  'Dut_SetDupLoUser'                               */
/* -------------------------------------------------------------- */

extern long  Dut_SetDupLoUser(aType,aFunc)
    long    aType;
    void *(*aFunc)();
{
    if (DupLoUserNB < C_SUPP_UserMaxTdupl) 
	{
        TabFcDupLoUser[DupLoUserNB  ] = aFunc;
        TabTpDupLoUser[DupLoUserNB++] = aType;
    }

    return(DupLoUserNB);
}


/*  Function  :  'Dut_DupLoUser'                                  */
/* -------------------------------------------------------------- */

extern void  Dut_DupLoUser(aPtFigSrc,aPtFigDup)
    lofig_list *aPtFigSrc,
               *aPtFigDup;
{
    ptype_list *PtUser;
          long  i;

    for( PtUser  =   aPtFigSrc->USER;
		 PtUser != (ptype_list*)NULL;
		 PtUser  = PtUser->NEXT     )
        for( i=0; i<DupLoUserNB; i++)
            if (PtUser->TYPE == TabTpDupLoUser[i])
                aPtFigDup->USER = addptype( aPtFigDup->USER,
                                               PtUser->TYPE,
                       (TabFcDupLoUser[i])( aPtFigSrc,
                                            aPtFigDup)     );
}


/*  Fonction  :  'Dut_GetPhUser'                                  */
/* -------------------------------------------------------------- */
/*      Recherche dans la liste pointee par "pthead" ( ptype ) le
    type specifie par "type".
        Dans le cas ou "C_SUPP_UCREAT" est en combinaison logique
    avec "a_flags", si l'element n'existait pas, il est ajoute a
    la liste.
    */

extern ptype_list *GetPhUser(ptfig,a_type,a_flags)
    phfig_list *ptfig;
          long  a_type;
		  long  a_flags;
{
    ptype_list *pt;


    /* Recherche de l'element. */
    if ( (pt=getptype(ptfig->USER,a_type))!=(ptype_list*)NULL )
        return( pt);

    /* Element inexistant : creation si demande. */
    if ( a_flags & F_SUPP_UCREAT ) 
	{
        ptfig->USER = addptype(ptfig->USER,a_type,(void*)NULL);

        return( ptfig->USER);
    }
    else
        return( (ptype_list*)NULL );
}


/*  Fonction  :  'Dut_DelPhUser'                                  */
/* -------------------------------------------------------------- */
/*      Recherche dans la liste pointee par "pthead" ( ptype ) le
    type specifie par "type" et le detruit.
    */

extern ptype_list *Dut_DelPhUser( ptfig, a_type, a_flags)
    phfig_list *ptfig;
          long  a_type;
		  long  a_flags;
{
    /* Destruction de l'element. */
    return( ptfig->USER = delptype(ptfig->USER,a_type) );
}


/*  Fonction  :  'Dut_SetDupPhUser'                               */
/* -------------------------------------------------------------- */
/*      Initialise le tableau permettant la duplication des 
    structures de pointees par une chaine ptype.

    AT : nombre maximal d'elements du tableau : C_SUPP_UserMaxTdupl.
    */

extern long  Dut_SetDupPhUser(a_type,funct)
    long  a_type;
    void *(*funct)();
{
    if (DupPhUserNB < C_SUPP_UserMaxTdupl) 
	{
        TabFcDupPhUser[DupPhUserNB  ] = funct;
        TabTpDupPhUser[DupPhUserNB++] = a_type;
    }

    return( DupPhUserNB);
}


/*  Fonction  :  'Dut_DupPhUser'                                  */
/* -------------------------------------------------------------- */
/*      Duplication de la chaine USER d'une figure physique. 
        Seules sont dupliquees les chaines dont le TYPE et la 
    fonction de duplication ont ete precisees grace a la fonction
    'set_user_dup'.
    */

extern void  Dut_DupPhUser(a_ptfig_src,a_ptfig_dest)
    phfig_list *a_ptfig_src,
               *a_ptfig_dest;
{
    ptype_list *ptuser;
          long  i;

    for( ptuser  = a_ptfig_src->USER;
		 ptuser !=(ptype_list*)NULL ;
		 ptuser  = ptuser->NEXT     )
        for( i=0; i<DupPhUserNB; i++)
            if (ptuser->TYPE == TabTpDupPhUser[i])
                a_ptfig_dest->USER = addptype( a_ptfig_dest->USER,
                                                     ptuser->TYPE,
                          (TabFcDupPhUser[i])( a_ptfig_src ,
                                               a_ptfig_dest));
}


/*  Function  :  'Dut_StrToType'                                  */
/* -------------------------------------------------------------- */

static char  Dut_StrToType(aStrType)
	char *aStrType;
{
	if (!strcmp(TABL_TYPE[(int)C_SUPP_DataTypeTerminal],aStrType))
		return(C_SUPP_DataTypeTerminal);
	if (!strcmp(TABL_TYPE[(int)C_SUPP_DataTypeBlock   ],aStrType))
		return(C_SUPP_DataTypeBlock);

	return( C_SUPP_DataTypeUnknow);
}


/*  Function  :  'Dut_AddUdpData'                                 */
/* -------------------------------------------------------------- */

udpdata *Dut_AddUdpData(aPtLoFig,aDpType)
	phfig_list *aPtLoFig;
	      char  aDpType;
{
	ptype_list *PtUdpData;

	PtUdpData = Dut_GetLoUser(aPtLoFig         , 
							  C_SUPP_UserDPData,
							  F_SUPP_UCREAT    );

	if (PtUdpData->DATA == (void*)NULL)
		PtUdpData->DATA = (void*)mbkalloc(sizeof(udpdata));

	((udpdata*)(PtUdpData->DATA))->TYPE = aDpType;

	return( (udpdata*)(PtUdpData->DATA));
}


/*  Function  :  'Dut_StrToSide'                                  */
/* -------------------------------------------------------------- */

static char  Dut_StrToSide(aStrSide)
	char *aStrSide;
{
	if (!strcmp(TABL_SIDE[(int)C_SUPP_ConSideDefault],aStrSide))
		return(C_SUPP_ConSideDefault);
	if (!strcmp(TABL_SIDE[(int)C_SUPP_ConSideNorth  ],aStrSide))
		return(C_SUPP_ConSideNorth  );
	if (!strcmp(TABL_SIDE[(int)C_SUPP_ConSideSouth  ],aStrSide))
		return(C_SUPP_ConSideSouth  );
	if (!strcmp(TABL_SIDE[(int)C_SUPP_ConSideEast   ],aStrSide))
		return(C_SUPP_ConSideEast   );
	if (!strcmp(TABL_SIDE[(int)C_SUPP_ConSideWest   ],aStrSide))
		return(C_SUPP_ConSideWest   );

	return( C_SUPP_ConSideUnknow);
}


/*  Function  :  'Dut_AddUdpCon'                                  */
/* -------------------------------------------------------------- */

udpcon_list *Dut_AddUdpCon(aPtLoFig,aConName,aConSide)
	lofig_list *aPtLoFig;
	      char *aConName;
	      char  aConSide;
{
	 ptype_list *PtUdpConHead;
	udpcon_list *PtNew, *PtCurr;

	PtUdpConHead = Dut_GetLoUser(aPtLoFig        , 
								 C_SUPP_UserDPCon,
								 F_SUPP_UCREAT   );

	PtNew = mbkalloc(sizeof(udpcon_list));

	PtNew->NAME = namealloc(aConName);
	PtNew->SIDE =           aConSide;

	for( PtCurr  = (udpcon_list*)(PtUdpConHead->DATA);
		 PtCurr != (udpcon_list*)NULL;
		 PtCurr  = PtCurr->NEXT)
		if (PtNew->NAME == PtCurr->NAME)
			Dut_PrintError(E_SUPP_ERROR     ,
						   E_SUPP_ConDupName,
						   PtNew->NAME      );

	PtNew->NEXT = (udpcon_list*)(PtUdpConHead->DATA);
	PtUdpConHead->DATA = (void*)PtNew;

	return(PtNew);
}


/*  Function  :  'Dut_LoadUdp'                                    */
/* -------------------------------------------------------------- */

extern void  Dut_LoadUdp(aLoFigName)
	char *aLoFigName;
{
#define  DutMC_ParserNextToken(ptstart,ptnext)             \
             if (((ptnext)=strchr((ptstart),',')) == NULL) \
				 Dut_PrintError(E_SUPP_ERROR       ,       \
								E_SUPP_ParserSyntax,       \
								ParserCurrLine     ,       \
								Dut_StringBuffer   );      \
             *((ptnext)++) = (char)0;

#define  DutMC_ParserLastToken(ptstart,ptend)              \
             if (((ptend)=strchr((ptstart),'\n')) == NULL) \
				 Dut_PrintError(E_SUPP_ERROR       ,       \
								E_SUPP_ParserSyntax,       \
								ParserCurrLine     ,       \
								Dut_StringBuffer   );      \
             *ptend = (char)0;


	      FILE *UdpFile;
	lofig_list *PtLoFig;
		   
		  long  ParserCurrLine;
		  long  ParserExitLoop;
		  char *PtName, *PtSide, *PtType, *PtEnd;
		  char           VlSide,  VlType;


	if ((PtLoFig=getlofig(aLoFigName,'A')) == (lofig_list*)NULL)
		Dut_PrintError(E_SUPP_ERROR      ,
					   E_SUPP_ConGetLoFig,
					   "SaveUdp"         ,
					   aLoFigName        );

	/* *** Opening the file holding user datas. *** */
	if ((UdpFile=mbkfopen(PtLoFig->NAME,
						          "dpr",
						      READ_TEXT)) == (FILE*)NULL)
		Dut_PrintError(E_SUPP_ERROR  ,
					   E_SUPP_OpenUdp,
					   "LoadUdp"     ,
					   PtLoFig->NAME );

    for( ParserCurrLine=1    ,
		 ParserExitLoop=FALSE;
        fgets(Dut_StringBuffer,C_SUPP_MaxLenString-1,UdpFile)!=NULL;
		 ParserCurrLine++    ) 
	{
        if (strncmp(Dut_StringBuffer,"EOF",3) == 0)
            {ParserExitLoop = TRUE; break;}

        if (Dut_StringBuffer[1] != ' ')
			Dut_PrintError(E_SUPP_ERROR       ,
						   E_SUPP_ParserSyntax,
						   ParserCurrLine     ,
						   Dut_StringBuffer   );

        switch( Dut_StringBuffer[0] )
		{
        /* Connector placement data record. */
            case 'C' :
				PtName = Dut_StringBuffer+2;
				DutMC_ParserNextToken( PtName, PtSide);
				DutMC_ParserLastToken( PtSide, PtEnd );

				if ((VlSide=Dut_StrToSide(PtSide))
					       == C_SUPP_ConSideUnknow)
					Dut_PrintError(E_SUPP_ERROR       ,
								   E_SUPP_ParserSyntax,
								   ParserCurrLine     ,
								   Dut_StringBuffer   );

				(void)Dut_AddUdpCon(PtLoFig,PtName,VlSide);
				break;
			case 'D' :
				PtType = Dut_StringBuffer+2;
				DutMC_ParserLastToken( PtType, PtEnd );

				if ((VlType=Dut_StrToType(PtType))
					       == C_SUPP_DataTypeUnknow)
					Dut_PrintError(E_SUPP_ERROR       ,
								   E_SUPP_ParserSyntax,
								   ParserCurrLine     ,
								   Dut_StringBuffer   );

				(void)Dut_AddUdpData(PtLoFig,VlType);
				break;
		}
	}
	
	/* Check if the EOF has been read. */
	if (ParserExitLoop == FALSE)
			Dut_PrintError(E_SUPP_ERROR       ,
						   E_SUPP_ParserSyntax,
						   ParserCurrLine     ,
						   "<EOF>"            );


#undef  DutMC_ParserLastToken
#undef  DutMC_ParserNextToken
}


/*  Function  :  'Dut_SaveUdp'                                    */
/* -------------------------------------------------------------- */

extern void  Dut_SaveUdp(aLoFigName)
	char *aLoFigName;
{
	       FILE *UdpFile;
	 lofig_list *PtLoFig;
	 ptype_list *PtUdpConHead;
	 ptype_list *PtUdpData;
	udpcon_list *PtCurr;

	if ((PtLoFig=getlofig(aLoFigName,'A')) == (lofig_list*)NULL)
		Dut_PrintError(E_SUPP_ERROR      ,
					   E_SUPP_ConGetLoFig,
					   "SaveUdp"         ,
					   aLoFigName        );

	/* *** Creating the file holding user datas. *** */
	if ((UdpFile=mbkfopen(PtLoFig->NAME,
						          "dpr",
						     WRITE_TEXT)) == (FILE*)NULL)
		Dut_PrintError(E_SUPP_ERROR  ,
					   E_SUPP_OpenUdp,
					   "SaveUdp"     ,
					   PtLoFig->NAME );

	PtUdpData = Dut_GetLoUser(PtLoFig          , 
							  C_SUPP_UserDPData,
							  F_SUPP_UCREAT    );

	if (PtUdpData->DATA != (void*)NULL)
		fprintf( UdpFile, "D %s\n",
			DutMC_TypeToStr(((udpdata*)(PtUdpData->DATA))->TYPE));		

	PtUdpConHead = Dut_GetLoUser(PtLoFig         , 
								 C_SUPP_UserDPCon,
								 F_SUPP_UCREAT   );

	for( PtCurr  = (udpcon_list*)(PtUdpConHead->DATA);
		 PtCurr != (udpcon_list*)NULL;
		 PtCurr  = PtCurr->NEXT)
		fprintf( UdpFile, "C %s,%s\n", PtCurr->NAME,
				       DutMC_SideToStr(PtCurr->SIDE));

	fprintf( UdpFile, "EOF\n");

	fclose(UdpFile);
}


/*  Function  :  'Dut_MovPhCon'                                   */
/* -------------------------------------------------------------- */

static phcon_list *Dut_MovPhCon(aPtPhFig,aConSide,aConName)
	phfig_list *aPtPhFig;
	      char  aConSide;
	      char *aConName;
{
	phcon_list *PtPhCon;

	for( PtPhCon  =  aPtPhFig->PHCON ;
		 PtPhCon != (phcon_list*)NULL;
		 PtPhCon  = PtPhCon->NEXT    )
		if (PtPhCon->NAME == aConName)
		{
		    if (aConSide == C_SUPP_ConSideDefault)
				return( PtPhCon);

			if (  (PtPhCon->XCON != aPtPhFig->XAB1)
				&&(PtPhCon->XCON != aPtPhFig->XAB2))
			{
				Dut_PrintWarng(W_SUPP_WARNG         ,
							   W_SUPP_MovPhConUnable,
							           PtPhCon->NAME,
							          aPtPhFig->NAME);
				return( PtPhCon);
			}

		    switch( aConSide )
			{
			    case C_SUPP_ConSideNorth:
					PtPhCon->ORIENT = NORTH;
					PtPhCon->LAYER  = ALU1;
					PtPhCon->WIDTH  = 1*SCALE_X;
					PtPhCon->XCON   = aPtPhFig->XAB1;
					PtPhCon->YCON   = aPtPhFig->YAB2;

					return( PtPhCon);
			    case C_SUPP_ConSideSouth:
			        PtPhCon->ORIENT = SOUTH;
					PtPhCon->LAYER  = ALU1;
					PtPhCon->WIDTH  = 1*SCALE_X;
					PtPhCon->XCON   = aPtPhFig->XAB1;
					PtPhCon->YCON   = aPtPhFig->YAB1;

					return( PtPhCon);
			    case C_SUPP_ConSideEast:
			        PtPhCon->ORIENT = EAST;
					PtPhCon->LAYER  = ALU2;
					PtPhCon->WIDTH  = 2*SCALE_X;
					PtPhCon->XCON   = aPtPhFig->XAB2;
				 /* PtPhCon->YCON   = aPtPhFig->YAB1; */

					return( PtPhCon);
			    case C_SUPP_ConSideWest:
			        PtPhCon->ORIENT = WEST;
					PtPhCon->LAYER  = ALU2;
					PtPhCon->WIDTH  = 2*SCALE_X;
					PtPhCon->XCON   = aPtPhFig->XAB1;
				 /* PtPhCon->YCON   = aPtPhFig->YAB2; */

					return( PtPhCon);
				default:
					Dut_PrintWarng(W_SUPP_WARNG         ,
								   W_SUPP_ConSideIllegal,
								   "MovPhCon"           ,
								   aConSide             ,
								   aConName             ,
					               aPtPhFig->NAME       );
					return( (phcon_list*)NULL);
			}
		}

	Dut_PrintWarng(W_SUPP_WARNG       ,
				   W_SUPP_MovConUnknow,
				   aConName           ,
				   aPtPhFig->NAME     );

	return( (phcon_list*)NULL);
}


/*  Function  :  'Dut_MovLsPhCon'                                 */
/* -------------------------------------------------------------- */

extern void  Dut_MovLsPhCon(aFigName)
	char *aFigName;
{
	 lofig_list *PtLoFig;
	 phfig_list *PtPhFig;
	udpcon_list *PtCurr;
	 ptype_list *PtUdpConHead;

	if ((PtLoFig=getlofig(aFigName,'A')) == (lofig_list*)NULL)
		Dut_PrintError(E_SUPP_ERROR      ,
					   E_SUPP_ConGetLoFig,
					   "MovLsPhCon"      ,
					   aFigName          );

	if ((PtPhFig=getphfig(aFigName,'A')) == (phfig_list*)NULL)
		Dut_PrintError(E_SUPP_ERROR      ,
					   E_SUPP_ConGetPhFig,
					   "MovLsPhCon"      ,
					   aFigName          );

	PtUdpConHead = Dut_GetLoUser(PtLoFig         , 
								 C_SUPP_UserDPCon, 0L);

	for( PtCurr  = (udpcon_list*)(PtUdpConHead->DATA);
		 PtCurr != (udpcon_list*)NULL;
		 PtCurr  = PtCurr->NEXT)
		(void)Dut_MovPhCon(PtPhFig,PtCurr->SIDE,
						           PtCurr->NAME);
}


/*  Function  :  'Dut_SetABTerminal'                              */
/* -------------------------------------------------------------- */

extern void  Dut_SetABTerminal(aFigName)
	char *aFigName;
{
	phfig_list *PtPhFig;
	lofig_list *PtLoFig;
	phcon_list *PtPhCon;
	ptype_list *PtUdpData;

	if ((PtLoFig=getlofig(aFigName,'A')) == (lofig_list*)NULL)
		Dut_PrintError(E_SUPP_ERROR      ,
					   E_SUPP_ConGetLoFig,
					   "SetABTerminal"   ,
					   aFigName          );

	if ((PtPhFig=getphfig(aFigName,'A')) == (phfig_list*)NULL)
		Dut_PrintError(E_SUPP_ERROR      ,
					   E_SUPP_ConGetPhFig,
					   "SetABTerminal"   ,
					   aFigName          );

	PtUdpData = Dut_GetLoUser(PtLoFig          , 
							  C_SUPP_UserDPData, 0L);

	if (PtUdpData == (void*)NULL) return;
	if (((udpdata*)(PtUdpData->DATA))->TYPE 
		         != C_SUPP_DataTypeTerminal)
		return;

	printf( "Streching AB.\n");

	for( PtPhCon  =  PtPhFig->PHCON  ;
		 PtPhCon != (phcon_list*)NULL;
		 PtPhCon  = PtPhCon->NEXT    )
		switch( PtPhCon->ORIENT )
		{
		    case NORTH:
		        PtPhCon->YCON += 10*SCALE_X;
				break;
		    case SOUTH:
		        PtPhCon->YCON -= 10*SCALE_X;
				break;
			case EAST:
			case WEST:
/* 				if (PtPhCon->YCON == PtPhFig->YAB1) */
/* 					PtPhCon->YCON -= 10*SCALE_X;    */
					
/* 				if (PtPhCon->YCON == PtPhFig->YAB2) */
/* 					PtPhCon->YCON += 10*SCALE_X;    */
					
				break;
		}

	PtPhFig->YAB1 -= 10*SCALE_X;
	PtPhFig->YAB2 += 10*SCALE_X;

	(void)addphcon( PtPhFig      ,
				    SOUTH        ,
				    "vdd"        , 
				    PtPhFig->XAB1,
				    PtPhFig->YAB1,
				    ALU1         ,	
				    8*SCALE_X    );
	(void)addphcon( PtPhFig      ,
				    SOUTH        ,
				    "vss"        , 
				    PtPhFig->XAB1,
				    PtPhFig->YAB1,
				    ALU1         ,	
				    10*SCALE_X   );

}


/*  Function  :  'Dut_GetLoConBySig'                              */
/* -------------------------------------------------------------- */
/*  Search the logical connector associated to the signal
 *  "aLoSig" in the logical figure "aLoFig", if any.
 *    The function will return a NULL pointer if the search fail.
 */

extern locon_list *Dut_GetLoConBySig(aLoFig,aLoSig)
	lofig_list *aLoFig;
	losig_list *aLoSig;
{
	locon_list *TmpLoCon;

	for(TmpLoCon  =     aLoFig->LOCON;
		TmpLoCon != (locon_list*)NULL;
		TmpLoCon  =    TmpLoCon->NEXT)
		if (TmpLoCon->SIG == aLoSig)
			return(TmpLoCon);

	return((locon_list*)NULL);
}
