
/* ###--------------------------------------------------------------### */
/* 																		*/
/* file		: syf_bspec.c												*/
/* date		: Nouv 05 1992												*/
/* version	: v100														*/
/* authors	: M.HANAFI,Pirouz BAZARGAN SABET							*/
/* content	: contains all specific functions used to build				*/
/*		  behaviour data structures :									*/
/*		  syf_addgen   , syf_tobin , syf_stostr, syf_cpyabllst,			*/
/*		  syf_cpyablstr, syf_crtabl, syf_select							*/
/*																		*/
/* ###--------------------------------------------------------------### */

#include <stdio.h>
#include MUT_H
#include LOG_H
#include"../../beh104/beh104.h"

typedef struct syf_expr
  {
  char	 	*IDENT; 	/* identifier or constant name		*/
  struct chain	*LIST_ABL;	/* pointer on syf_abllst list		*/
  char 		 TYPE;
  short		 WIDTH;         /* width of bit vector			*/
  }
syf_ablstr;

#include "syf_bspec.h"
#include "syf_bedef.h"

/* ###--------------------------------------------------------------### */
/* function	: syf_addgen						*/
/* description	: create one or more BEGEN structures			*/
/*		  For a scalar a BEGEN is created at the head of	*/
/*		  existing BEGEN list.					*/
/*		  For an array (including arraies of one element) a set	*/
/*		  of BEGENs are created in a sorted list. BEGEN related	*/
/*		  to the index i of the array is named `name(i)`. The	*/
/*		  head of the list represents the right bound of the	*/
/*		  array. This list is then chained to the head of	*/
/*		  existing BEGEN list.					*/
/* called func.	: syf_beh_addbegen, namealloc				*/
/* ###--------------------------------------------------------------### */

struct syf_begen *syf_addgen (lastgeneric,nat_lst,nam_lst,type,left,right)

struct syf_begen *lastgeneric;	/* pointer on the last begen structure	*/
struct chain *nam_lst;		/* generic's name list			*/
struct chain *nat_lst;		/* generic's value list			*/
char         *type;		/* generic's type			*/
short         left;		/* array's left bound (= -1 if scalar)	*/
short         right;		/* array's right bound (= -1 if scalar)	*/

  {
  char          extname[100];
  char         *name;
  struct syf_begen *ptgen;
  struct chain *ptauxnam;
  struct chain *ptauxnat;
  int           i;
  int           inc = 1;

  ptgen    = lastgeneric;
  ptauxnam = nam_lst;
  ptauxnat = nat_lst;

  if ((left == -1) && (right == -1))
    if ((ptauxnat != NULL) && (ptauxnat->NEXT == NULL))
      while (ptauxnam != NULL)
        {
        name     = namealloc((char *)ptauxnam->DATA);
        ptgen    = syf_beh_addbegen (ptgen,name,type,(void *)ptauxnat->DATA);
        ptauxnam = ptauxnam->NEXT;
        }
    else
      syf_error(75,NULL);
  else
    {
    if (left >= right)
      inc = -1;
    while (ptauxnam != NULL)
      {
      for (i=left ; i!=(right+inc) ; i+=inc)
        {
        sprintf (extname,"%s %d",(char *)ptauxnam->DATA,i);
        name = namealloc(extname);
        if (ptauxnat != NULL)
          {
          ptgen    = syf_beh_addbegen (ptgen,name,type,(void *)ptauxnat->DATA);
	  ptauxnat = ptauxnat->NEXT;
          }
        else
          syf_error(75,NULL);
        }
      if (ptauxnat != NULL)
        syf_error (75,NULL);
      ptauxnat = nat_lst;
      ptauxnam = ptauxnam->NEXT;
      }
    }
  return (ptgen);
  }

/* ###--------------------------------------------------------------### */
/* function	: syf_stostr						*/
/* description	: purge double % (percent) or Quote (") from string	*/
/* called func.	: mbkalloc						*/
/* ###--------------------------------------------------------------### */

char *syf_stostr(str)

char *str;

  {
  char *resstr;
  int   i;
  int   j=0;

  resstr = (char *)mbkalloc(100);
  resstr[0] = '\0';

  for ( i=1;str[i+1]!='\0';i++)
    {
    resstr[j++]=str[i];
    if ((str[i]==str[0])&&(str[i+1]==str[0]))
      i++;
    }
    
  return( &resstr[0] );
  }

/* ###--------------------------------------------------------------### */
/* function	: syf_cpyabllst						*/
/* description	: duplicate syf_abllst structure 			*/
/* called func.	: addchain, reverse, copyExpr				*/
/* ###--------------------------------------------------------------### */

struct chain *syf_cpyabllst (abllst)

struct chain *abllst;
  {
  struct chain *pt_abllst = NULL;

  while (abllst != NULL)
    {
    pt_abllst = addchain (pt_abllst,copyExpr((struct chain *)abllst->DATA));
    abllst    = abllst->NEXT;
    }
  pt_abllst = reverse (pt_abllst);
  return (pt_abllst);
  }

/* ###--------------------------------------------------------------### */
/* function	: syf_cpyablstr						*/
/* description	: duplicate syf_ablstr structure 			*/
/* called func.	: mbkalloc <mbk>, syf_cpyabllst				*/
/* ###--------------------------------------------------------------### */

syf_ablstr syf_cpyablstr (ablstr)

syf_ablstr ablstr;
  {
  syf_ablstr pt_ablstr;

  pt_ablstr.IDENT    = NULL;
  pt_ablstr.WIDTH    = ablstr.WIDTH;
  pt_ablstr.TYPE    = ablstr.TYPE;
  pt_ablstr.LIST_ABL = syf_cpyabllst (ablstr.LIST_ABL);
  return (pt_ablstr);
  }

/* ###--------------------------------------------------------------### */
/* function     : syf_crtabl                                            */
/* description  : combine at most two ABLs and build a new one          */
/*    		  The following operations can be performed :		*/
/*		    CONC    perform concatenation			*/
/*		    NOPI    initialize a structure for a signal (scalar	*/
/*		            or array)					*/
/*		    NOPS    initialize a structure for a literal	*/
/*		    NE      create a structure with an ABL representing	*/
/*		            the 'non equality' of two expressions	*/
/*		    EQ      create a structure with an ABL representing	*/
/*		            the 'equality' of two expressions		*/
/*		    NOT     perform logical not of an expression	*/
/*		    AND     perform logical and  between two expressions*/
/*		    OR      perform logical or   between two expressions*/
/*		    NAND    perform logical nand between two expressions*/
/*		    NOR     perform logical nor  between two expressions*/
/*		    XOR     perform logical xor  between two expressions*/
/*		    ANDM    perform logical and  between two expressions*/
/*		            (the second expression is a scalar)		*/
/* called func. : createAtom , createExpr, addQExpr , syf_toolbug,	*/
/*		  syf_error , addchain   , freechain			*/
/* ###--------------------------------------------------------------### */

syf_ablstr syf_crtabl ( oper, expr1, expr2, left, right )

short      oper;
syf_ablstr expr1;
syf_ablstr expr2;
int        left;
int        right;

  {
  char            name[256];
  char           *name2;
  struct chain   *pt_abl1;
  struct chain   *pt_abl2;
  struct chain   *pt_aux1;
  struct chain   *pt_aux2;
  syf_ablstr      result;
  char            lcl_buffer[256];
  short           inc;
  short           i;

  result.IDENT    = NULL;
  result.LIST_ABL = NULL;
  result.WIDTH    = 0;
  result.TYPE    = 0;

  switch (oper)
    {
    case CONC :
      if ((expr1.LIST_ABL == NULL) || (expr2.LIST_ABL == NULL))
        syf_toolbug (4,"syf_crtabl","CONC",0);
      else
        {
        if (expr1.LIST_ABL == expr2.LIST_ABL)
          syf_toolbug (16,"syf_crtabl",NULL,0);
        else
          {
          pt_aux2 = expr2.LIST_ABL;
          while (pt_aux2->NEXT != NULL)
            pt_aux2 = pt_aux2->NEXT;

          pt_aux2->NEXT = expr1.LIST_ABL;

          result.LIST_ABL = expr2.LIST_ABL;
          result.WIDTH    = expr1.WIDTH + expr2.WIDTH;
	  result.TYPE    = expr1.TYPE;
          expr1.LIST_ABL  = NULL;
          expr2.LIST_ABL  = NULL;
          }
        }
      break;

      case SUBVAR :
        if ( expr1.LIST_ABL == NULL )
          syf_toolbug (2,"syf_crtabl",NULL,0);
        else
          {
          if ((left == -1) && (right == -1))
            {
	    result.IDENT    = NULL;
            result.LIST_ABL = addchain (result.LIST_ABL,copyExpr((struct chain*)(expr1.LIST_ABL->DATA)));
            result.WIDTH    = 1;
	    result.TYPE     = expr1.TYPE;
            }
          else
            {
		struct chain *  abl = expr1.LIST_ABL ;
		
            for (i=0 ; i< left ; i++)
              {
		if( abl )
	       abl = abl->NEXT ;	
		else 
          syf_toolbug (2,"syf_crtabl",NULL,0);
              }
            for (i=left ; i<= right ; i++)
              {
		if( abl )
		{
              result.LIST_ABL = addchain (result.LIST_ABL,copyExpr((struct chain*)(abl->DATA)));
	       abl = abl->NEXT ;	
		}
		else 
          syf_toolbug (2,"syf_crtabl",NULL,0);
              }
            }
	  result.IDENT    = NULL;
	  result.TYPE    = expr1.TYPE;
          result.WIDTH = right - left + 1;
          }
        break;

      case NOPI :
        if ( expr1.IDENT == NULL )
          syf_toolbug (2,"syf_crtabl",NULL,0);
        else
          {
          if ((left == -1) && (right == -1))
            {
            result.LIST_ABL = addchain(result.LIST_ABL,createAtom(expr1.IDENT));
            result.WIDTH    = 1;
	  result.TYPE    = expr1.TYPE;
            }
          else
            {
            if (left <= right)
              {
              inc = 1;
              result.WIDTH = right - left + 1;
              }
            else
              {
              inc = -1;
              result.WIDTH = left - right + 1;
              }

            for (i=left ; i!=(right+inc) ; i+=inc)
              {
              sprintf (name,"%s %i",expr1.IDENT,i);
              name2           = namealloc (name);
              result.LIST_ABL = addchain (result.LIST_ABL,createAtom(name2));
              }
            }
	  result.TYPE    = expr1.TYPE;
          expr1.IDENT = NULL;
          }
        break;

      case NOPS :
        if ( expr1.IDENT == NULL )
          syf_toolbug (2,"syf_crtabl",NULL,0);
        else
          {
          syf_tobin (lcl_buffer,expr1.IDENT,-1,-1);
          if ((left == -1) && (right == -1))
            {
            left = 0;
            right = strlen (lcl_buffer) - 1;
            }

          for (i=left ; i<=right ; i++)
            {
            switch ( lcl_buffer[i] )
              {
              case '0' :
                result.LIST_ABL = addchain (result.LIST_ABL,createAtom("'0'"));
                break;
              case '1' :
                result.LIST_ABL = addchain (result.LIST_ABL,createAtom("'1'"));
                break;
/*-----------        Beware Not VHDL        -------------*/
              case 'd' :
                result.LIST_ABL = addchain (result.LIST_ABL,createAtom("'D'"));
                break;
              default  :
                syf_toolbug (15,"syf_crtabl",NULL,expr1.IDENT[i]);
              }
            }
          result.WIDTH = right - left + 1;
          }
	  result.TYPE    = expr1.TYPE;
        break;

      case STABLE :
        if (expr1.LIST_ABL == NULL)
	  syf_toolbug (3,"syf_crtabl",NULL,0);
        else
          {
	  pt_aux1  = expr1.LIST_ABL;
          while (pt_aux1 != NULL)
            {
            pt_abl1  = createExpr (STABLE);
            addQExpr (pt_abl1, (struct chain *)pt_aux1->DATA);
            pt_aux1->DATA = (void *)pt_abl1;
            pt_aux1  = pt_aux1->NEXT;
            }

          result.LIST_ABL = expr1.LIST_ABL;
          result.WIDTH    = expr1.WIDTH;
          result.TYPE    = expr1.TYPE;

          expr1.LIST_ABL  = NULL;
          }
        break;

      case NOT :
        if (expr1.LIST_ABL == NULL)
	  syf_toolbug (3,"syf_crtabl",NULL,0);
        else
          {
	  pt_aux1  = expr1.LIST_ABL;
          while (pt_aux1 != NULL)
            {
            pt_abl1  = createExpr (NOT);
            addQExpr (pt_abl1, (struct chain *)pt_aux1->DATA);
            pt_aux1->DATA = (void *)pt_abl1;
            pt_aux1  = pt_aux1->NEXT;
            }

          result.LIST_ABL = expr1.LIST_ABL;
          result.WIDTH    = expr1.WIDTH;
	  result.TYPE    = expr1.TYPE;

          expr1.LIST_ABL  = NULL;
          }
        break;

      case EQ :
        if ((expr1.LIST_ABL == NULL) || (expr2.LIST_ABL == NULL))
	  syf_toolbug (4,"syf_crtabl","EQ",0);
        else
          {
	  result.TYPE    = expr1.TYPE;
          if (expr1.WIDTH != expr2.WIDTH  || (expr1.TYPE != expr2.TYPE && expr2.TYPE !=-1))
            {
            syf_error (38,NULL);
            pt_abl2 = createAtom ("'1'");

	    pt_aux1 = expr1.LIST_ABL;
            while (pt_aux1 != NULL)
              {
              freeExpr (pt_aux1->DATA);
              pt_aux1 = pt_aux1->NEXT;
              }
	    pt_aux2 = expr2.LIST_ABL;
            while (pt_aux2 != NULL)
              {
              freeExpr (pt_aux2->DATA);
              pt_aux2 = pt_aux2->NEXT;
              }
            }
          else
            {
	    pt_aux1 = expr1.LIST_ABL;
	    pt_aux2 = expr2.LIST_ABL;

            pt_abl1 = createExpr (XOR);
            addQExpr (pt_abl1, (struct chain *)pt_aux1->DATA);
            addQExpr (pt_abl1, (struct chain *)pt_aux2->DATA);

            pt_aux1 = pt_aux1->NEXT;
            pt_aux2 = pt_aux2->NEXT;

	    while (pt_aux1 != NULL)
	      {
              pt_abl2 = createExpr (OR);
              addQExpr (pt_abl2,pt_abl1);

              pt_abl1 = createExpr (XOR);
              addQExpr (pt_abl1, (struct chain *)pt_aux1->DATA);
              addQExpr (pt_abl1, (struct chain *)pt_aux2->DATA);

              addQExpr (pt_abl2, pt_abl1);
              pt_abl1 = pt_abl2;

	      pt_aux1 = pt_aux1->NEXT;
	      pt_aux2 = pt_aux2->NEXT;
	      }
            pt_abl2 = createExpr (NOT);
            addQExpr (pt_abl2, pt_abl1);

            }
          result.LIST_ABL = addchain (result.LIST_ABL,pt_abl2);
          result.WIDTH    = 1;
	  result.TYPE    = expr1.TYPE;
          freechain (expr1.LIST_ABL);
          freechain (expr2.LIST_ABL);
          expr1.LIST_ABL = NULL;
          expr2.LIST_ABL = NULL;
          }
        break;

      case NE :

        if ((expr1.LIST_ABL == NULL) || (expr2.LIST_ABL == NULL))
	  syf_toolbug (4,"syf_crtabl",NULL,0);
        else
          {
	  result.TYPE    = expr1.TYPE;
          if (expr1.WIDTH != expr2.WIDTH  || (expr1.TYPE != expr2.TYPE && expr2.TYPE !=-1))
            {
            syf_error(38,NULL);
            pt_abl1 = createAtom ("'1'");

	    pt_aux1 = expr1.LIST_ABL;
            while (pt_aux1 != NULL)
              {
              freeExpr (pt_aux1->DATA);
              pt_aux1 = pt_aux1->NEXT;
              }
	    pt_aux2 = expr2.LIST_ABL;
            while (pt_aux2 != NULL)
              {
              freeExpr (pt_aux2->DATA);
              pt_aux2 = pt_aux2->NEXT;
              }
            }
          else
            {
	    pt_aux1 = expr1.LIST_ABL;
	    pt_aux2 = expr2.LIST_ABL;

            pt_abl1 = createExpr (XOR);
            addQExpr (pt_abl1, (struct chain *)pt_aux1->DATA);
            addQExpr (pt_abl1, (struct chain *)pt_aux2->DATA);

            pt_aux1 = pt_aux1->NEXT;
            pt_aux2 = pt_aux2->NEXT;

	    for (i=2 ; i<=expr1.WIDTH ; i++)
	      {
              pt_abl2 = createExpr (OR);
              addQExpr (pt_abl2, pt_abl1);

              pt_abl1 = createExpr (XOR);
              addQExpr (pt_abl1, (struct chain *)pt_aux1->DATA);
              addQExpr (pt_abl1, (struct chain *)pt_aux2->DATA);

              addQExpr (pt_abl2, pt_abl1);
              pt_abl1 = pt_abl2;

	      pt_aux1 = pt_aux1->NEXT;
	      pt_aux2 = pt_aux2->NEXT;
	      }

            }
          result.LIST_ABL = addchain(result.LIST_ABL,pt_abl1);
	  result.TYPE    = expr1.TYPE;
          result.WIDTH    = 1;
          freechain (expr1.LIST_ABL);
          freechain (expr2.LIST_ABL);
          expr1.LIST_ABL = NULL;
          expr2.LIST_ABL = NULL;
          }
        break;

      case AND  :
      case NAND :
      case OR   :
      case NOR  :
      case XOR  :

        if (expr1.LIST_ABL == NULL)
          {
          if (expr2.LIST_ABL == NULL)
	    syf_toolbug (4,"syf_crtabl",NULL,0);
          else
            {
            result.LIST_ABL = expr2.LIST_ABL;
            result.WIDTH    = expr2.WIDTH;
	  result.TYPE    = expr2.TYPE;
            expr2.LIST_ABL  = NULL;
            }
          }
        else
          {
          if (expr2.LIST_ABL == NULL)
            {
            result.LIST_ABL = expr1.LIST_ABL;
            result.WIDTH    = expr1.WIDTH;
	  result.TYPE    = expr1.TYPE;
            expr1.LIST_ABL  = NULL;
            }
          else
            {
            if (expr1.LIST_ABL == expr2.LIST_ABL)
              syf_toolbug (16,"syf_crtabl",NULL,0);
            else
              {
              if ((expr1.WIDTH != expr2.WIDTH)
		 || (expr1.TYPE != expr2.TYPE && expr2.TYPE !=-1))
                syf_error(38,NULL);
              else
                {
	        pt_aux1 = expr1.LIST_ABL;
	        pt_aux2 = expr2.LIST_ABL;

	        for (i=1 ; i<=expr1.WIDTH ; i++)
	          {
                  pt_abl1 = createExpr (oper);
                  addQExpr (pt_abl1, (struct chain *)pt_aux1->DATA);
                  addQExpr (pt_abl1, (struct chain *)pt_aux2->DATA);
                  pt_aux1->DATA = (void *)pt_abl1;

	          pt_aux1       = pt_aux1->NEXT;
	          pt_aux2       = pt_aux2->NEXT;
		  }
                }
              result.LIST_ABL = expr1.LIST_ABL;
              result.WIDTH    = expr1.WIDTH;
              result.TYPE    = expr1.TYPE;
              freechain (expr2.LIST_ABL);
              expr1.LIST_ABL  = NULL;
              expr2.LIST_ABL  = NULL;
              }
            }
          }
        break;

      case ANDM :
        if ((expr1.LIST_ABL == NULL) || (expr2.LIST_ABL == NULL))
	    syf_toolbug (4,"syf_crtabl",NULL,0);
        else
          {
          if (expr2.WIDTH != 1)
            syf_error(38,NULL);
          else
            {
            pt_aux1 = expr1.LIST_ABL;
            pt_aux2 = expr2.LIST_ABL;
            while (pt_aux1 != NULL)
              {
              pt_abl1 = createExpr (AND);
              addQExpr (pt_abl1,          (struct chain *)pt_aux1->DATA);
              addQExpr (pt_abl1, copyExpr((struct chain *)pt_aux2->DATA));
              pt_aux1->DATA = (void *)pt_abl1;

              pt_aux1       = pt_aux1->NEXT;
              }
            }
          result.LIST_ABL = expr1.LIST_ABL;
          result.WIDTH    = expr1.WIDTH;
          result.TYPE    = expr1.TYPE;
	  pt_aux2 = expr2.LIST_ABL;
          while (pt_aux2 != NULL)
            {
            freeExpr (pt_aux2->DATA);
            pt_aux2 = pt_aux2->NEXT;
            }
          freechain (expr2.LIST_ABL);
          expr2.LIST_ABL  = NULL;
          expr1.LIST_ABL  = NULL;
          }
        break;

      default :
	syf_toolbug (1,"syf_crtabl",NULL,0);
      }

    return (result);
    }

/* ###--------------------------------------------------------------### */
/* function	: syf_select						*/
/* description	: create an abl representing the choice in a selected	*/
/*		  signal assignment and perform unicity verification	*/
/*		  using BDDs.						*/
/* called func.	: syf_tobin						*/
/* ###--------------------------------------------------------------### */

syf_ablstr syf_select (pt_str, pt_bdd, pt_ablstr)

struct chain *pt_str;		/* pointer on a list of choices		*/
pNode        *pt_bdd;		/* used to check if a choice is legal	*/
syf_ablstr   pt_ablstr;		/* tested expression			*/

  {
  char             binstr[256];
  int              i;
  syf_ablstr       final;
  struct chain    *pt_auxabl;
  pNode            pt_bddres;
  pNode            pt_bddnew;
  pNode            pt_bddtmp;
  pNode            pt_bddaux;
  char             nomvar[6];
  struct chain    *pt_newabl;
  static int       oth_flg=0;
  static int       last_width=0;
  static pCircuit  pC = NULL;

  final = SYF_EMPSTR;
  pt_bddtmp = zero;

  if (pC == NULL)
    pC = initializeCct ("-select-",200,0);

  if (*pt_bdd == NULL)
    {
    if (last_width < pt_ablstr.WIDTH)
      {
      for (; last_width<pt_ablstr.WIDTH ; last_width++)
        {
        sprintf (nomvar,"(%d)",last_width);
        createNodeTermBdd (addInputCct(pC,nomvar));
        }
      }
    *pt_bdd = zero;
    oth_flg = 0;
    }

  while (pt_str)
    {
    syf_tobin (binstr, (char *)pt_str->DATA,-1,-1);
    if (oth_flg != 0)
      {
      syf_error(30,NULL);
      }

    if (strcmp("others", (char *)pt_str->DATA))
      {
      pt_bddres = one;

      if (strlen (binstr) != pt_ablstr.WIDTH)
        {
        syf_error(38,NULL);
        }
      for (i=0 ; binstr[i]!='\0' ; i++)
        {
        pt_bddaux = createNodeTermBdd (i+2);
        if (binstr[i] == '0')
          pt_bddaux = notBdd (pt_bddaux);
        pt_bddres = applyBinBdd (AND, pt_bddaux, pt_bddres);
        }
      pt_bddnew = applyBinBdd (OR,*pt_bdd,pt_bddres);

      if (*pt_bdd == pt_bddnew)
         {
         syf_error(28,NULL);
         }

      *pt_bdd = pt_bddnew;
      }
    else
      {
      oth_flg   = 1;
      pt_bddres = notBdd (*pt_bdd);
      *pt_bdd   = one;
      }
    pt_bddtmp = applyBinBdd (OR,pt_bddtmp,pt_bddres);
    pt_str = delchain  (pt_str,pt_str);
    }

  pt_newabl = bddToAbl (pt_bddtmp, pC->pNameI);

  pt_auxabl = pt_ablstr.LIST_ABL;
  i         = pt_ablstr.WIDTH - 1;
  while (pt_auxabl != NULL)
    {
    sprintf (nomvar,"(%i)",i);
    pt_newabl = substExpr (pt_newabl, namealloc(nomvar),
                           (struct chain *)pt_auxabl->DATA);
    i--;
    pt_auxabl = pt_auxabl->NEXT;
    }
  final.LIST_ABL = addchain (final.LIST_ABL, pt_newabl);
  final.WIDTH    = 1;

  return (final);
  }

/* ###--------------------------------------------------------------### */
/* function	: syf_numtobin						*/
/* description	: transform a ENUMERATE 		*/
/*		  in a string of '0' and '1's				*/
/* ###--------------------------------------------------------------### */
int syf_bintonum(str)
char* str;

  {
	int res,i=0;

   res = 0; 
	while(str[i])
	{
	if(str[i] <'0' || str[i] > '1')
		return(-1);
     	  res = res*2 + str[i] -'0';
	  i++;
	}
  return(res);
  }
/* ###--------------------------------------------------------------### */
/* function	: syf_numtobin						*/
/* description	: transform a ENUMERATE 		*/
/*		  in a string of '0' and '1's				*/
/* ###--------------------------------------------------------------### */
char *syf_numtobin(num)
int num;

  {
   char val[256]; 
   char *str;
	int res,i=1;

   val[255] = '\0';
   res = num; 
	while(res)
	{
          val[255 - i] = res%2 + '0';
	  res = (res / 2);
	  i++;
	}
   val[255 - i] = '0';
    str = namealloc((char *)(val + 255-i));
  return(str);
  }
/* ###--------------------------------------------------------------### */
/* function	: syf_tobin						*/
/* description	: transform a StringLit, BitStringLit or CharacterLit	*/
/*		  in a string of '0' and '1's				*/
/* ###--------------------------------------------------------------### */

int syf_tobin (trg,src,left,right)

char *trg;
char *src;
int   left;
int   right;

  {
  char base;
  int  indx;
  int  j = 0;
  int  errflg = 0;
  char lcl_trg[256];

  lcl_trg[0] = '\0';

  if (src == NULL)
    {
    strcpy (trg,"0");
    }
  else
    {
    if (!strcmp (src,"others"))
      {
      strcpy(trg,src);
      }
    else
      {
      if ((src[0] != '\'') && (src[0] != '"') && (src[0] != '%'))
        {
        base = src[0];
        indx = 2;
        }
      else
        {
        base = 'B';
        indx = 1;
        }

      switch (base)
        {
        case 'B' :
        case 'b' :
          while ((lcl_trg[j] = src[indx]) != '\0')
            {
            switch (src[indx])
              {
              case '0':
              case '1':
              case 'd':				/* Beware Not VHDL	*/
                j++; break;

              case '%' :
              case '"' :
              case '\'':
              case '_' :
                break;

	    default :
	      errflg = 1; syf_error(73,src);
              }
            indx++;
            }
          break;

        case 'O' :
        case 'o' :
          while (src[indx] != '\0')
            {
            j += 3;
            switch (src[indx])
              {
              case '0' :
                strcat (lcl_trg,"000"); break;
              case '1' :
                strcat (lcl_trg,"001"); break;
              case '2' :
                strcat (lcl_trg,"010"); break;
              case '3' :
                strcat (lcl_trg,"011"); break;
              case '4' :
                strcat (lcl_trg,"100"); break;
              case '5' :
                strcat (lcl_trg,"101"); break;
              case '6' :
                strcat (lcl_trg,"110"); break;
              case '7' :
                strcat (lcl_trg,"111"); break;
              case '"' :
              case '%' :
              case '_' :
                j -= 3; break;
	      default :
	        j -= 3; errflg = 1; syf_error(73,src);
              }
            indx++;
            }
          break;

        case 'X' :
        case 'x' :
          while (src[indx] != '\0')
            {
            j += 4;
            switch (src[indx])
              {
              case '0' :
                strcat (lcl_trg,"0000"); break;
              case '1' :
                strcat (lcl_trg,"0001"); break;
              case '2' :
                strcat (lcl_trg,"0010"); break;
              case '3' :
                strcat (lcl_trg,"0011"); break;
              case '4' :
                strcat (lcl_trg,"0100"); break;
              case '5' :
                strcat (lcl_trg,"0101"); break;
              case '6' :
                strcat (lcl_trg,"0110"); break;
              case '7' :
                strcat (lcl_trg,"0111"); break;
              case '8' :
                strcat (lcl_trg,"1000"); break;
              case '9' :
                strcat (lcl_trg,"1001"); break;
              case 'a' :
              case 'A' :
                strcat (lcl_trg,"1010"); break;
              case 'b' :
              case 'B' :
                strcat (lcl_trg,"1011"); break;
              case 'c' :
              case 'C' :
                strcat (lcl_trg,"1100"); break;
              case 'd' :
              case 'D' :
                strcat (lcl_trg,"1101"); break;
              case 'e' :
              case 'E' :
                strcat (lcl_trg,"1110"); break;
              case 'f' :
              case 'F' :
                strcat (lcl_trg,"1111"); break;
              case '%' :
              case '"' :
              case '_' :
                j -= 4; break;
	      default :
	        j -= 4; errflg = 1; syf_error(73,src);
              }
            indx++;
            }
          break;

        default :
          syf_toolbug (17,"syf_tobin",NULL,base);
        }

      if ((j == 0) || (j <= right))
        {
        trg[0] = '0';
        trg[1] = '\0';
        }
      else
        {
        if (left != -1)
          {
          strcpy (trg, &lcl_trg[left]);
          trg[right - left + 1] = '\0';
          }
        else
          strcpy (trg, lcl_trg);
        }
      }
    }

  return (errflg);
  }
