
/* expression.h */
/* contains the type declarations for expression handling information  */
/*
 * $Id: expression.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $ 
 *
 * $Log: expression.c,v $
 * Revision 1.1.1.1  2003/11/04 23:34:57  mjames
 * Imported into local repositrory
 *
 * Revision 1.11  2002/09/30 13:22:38  MJAMES
 * Altered the use and creation of partition
 * generics (at evaluation time of expressions within the partition )
 * This still needs checking, as evaluation of the expression may well be
 * delayed until after when the partition generics need to be defined.
 *
 * Revision 1.10  2002/09/09 15:15:37  mjames
 * Altered expression to copy properly
 *
 * Revision 1.8  2001/11/30 22:19:27  mjames
 * Corrected some missing conversion of LBRK to '('.
 * Initialised a variable to satisfy GCC.
 * Enhanced an error message to give some context.
 *
 * Revision 1.7  2001/10/31 22:20:04  mjames
 * Tidying up problematical comments caused by CVS
 * 'intelligent' comment guessing
 *
 * Revision 1.6  2001/06/06 12:10:23  mjames
 * Move from HPUX
 *
 * Revision 1.5  2001/04/09 14:58:29  mjames
 * Added capability to delete generics from specific sockets.
 *
 * Revision 1.4  2001/04/06 22:47:02  mjames
 * Added doc2, the creator of documentation to Vertical scripts uses PERL
 *
 *
 * Also correcting generic behaviour and the printing of Verilog.
 *
 * Revision 1.3  2000/12/04 13:14:02  mjames
 * Imported all of the PCB syntax readers.
 *
 * Converted "a/b" to mean "a" divided by "b" insted of a single string
 * "a/b" in Verilog
 *
 * Revision 1.2  2000/11/29 21:51:18  mjames
 * Fine tuning of software
 *
 * Revision 1.1.1.1  2000/10/19 21:58:37  mjames
 * Mike put it here
 *
 *
 * Revision 1.20  2000/10/12  15:32:18  15:32:18  mjames (Mike James)
 * Removed <cr>
 * 
 * Revision 1.19  2000/10/04  10:37:04  10:37:04  mjames (Mike James)
 * Modified for Vertical2 : support COMPONENTS and SIGNALS
 * 
 * Revision 1.19  2000/10/04  10:37:04  10:37:04  mjames (Mike James)
 * Part of Release PSAVAT01
 * 
 * Revision 1.18  2000/10/02  11:04:12  11:04:12  mjames (Mike James)
 * new_vhdl
 * 
 * Revision 1.17  2000/09/27  14:42:12  14:42:12  mjames (Mike James)
 * Part of Release Sep_27_ST_2000
 * 
 * Revision 1.16  2000/09/21  10:15:42  10:15:42  mjames (Mike James)
 * Part of Release Sep21Alpha
 * 
 * Revision 1.15  2000/08/25  09:57:10  09:57:10  mjames (Mike James)
 * Part of Release Aug25_alpha
 * 
 * Revision 1.14  2000/08/16  08:57:27  08:57:27  mjames (Mike James)
 * Part of Release CD01_Aug2000
 * 
 * Revision 1.13  2000/08/14  14:45:08  14:45:08  mjames (Mike James)
 * Part of Release Aug_14_2000
 * 
 * Revision 1.12  2000/08/11  08:30:28  08:30:28  mjames (Mike James)
 * Part of Release Aug_11_2000
 * 
 * Revision 1.11  2000/08/09  10:31:42  10:31:42  mjames (Mike James)
 * Part of Release Aug__9_2000
 * 
 * Revision 1.10  2000/05/31  11:42:50  11:42:50  mjames (Mike James)
 * Part of Release May_31_2000
 * 
 * Revision 1.9  2000/05/08  17:01:34  17:01:34  mjames (Mike James)
 * Part of Release May__8_2000
 * 
 * Revision 1.8  2000/05/08  16:59:27  16:59:27  mjames (Mike James)
 * Part of Release May__8_2000
 * 
 * Revision 1.7  2000/05/08  16:57:03  16:57:03  mjames (Mike James)
 * Part of Release May__8_2000
 * 
 * Revision 1.6  2000/03/08  16:18:56  16:18:56  mjames (Mike James)
 * New version including PC
 * 
 * Revision 1.3  2000/01/20  15:58:42  15:58:42  mjames (Mike James)
 * Part of Release R22
 * 
 * Revision 1.2  99/12/22  11:15:23  11:15:23  mjames (Mike James)
 * Part of Release Dec_22_1999
 * 
 * Revision 1.1  99/06/25  14:34:45  14:34:45  mjames (Mike James)
 * Initial revision
 * 
 *  */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "vertcl_main.h" 
#include "expression.h"
#include "generic.h"
#include "database.h"
#include "cmdparse.h"
#include "cmdlog.h"
#include "acf_yacc.h"


/* place reference to a 'C' variable at the end of the tree branch */
expression_t * compile_variable_reference(int *v,char * s ) {
  expression_t * p;
  p = calloc(1,sizeof(expression_t));
  
  if(p) {
    p->opcode = EXP_VAR_REF;
    p->left.ip  = v;
    p->right.s = s;
    }
  return p;
  }



/* place an integer  constant at the end of the tree branch */
expression_t * compile_constant(int k ) {
  expression_t * p;
  p = calloc(1,sizeof(expression_t));
  
  if(p) {
    p->opcode = EXP_CONSTANT;
    p->left.i  = k;
    p->right.s = NULL;
    }
  return p;
  }
/* place a boolean constant at the end of the tree branch */
expression_t * compile_boolean_constant(int k ) {
  expression_t * p;
  p = calloc(1,sizeof(expression_t));
  
  if(p) {
    p->opcode = EXP_BOOLEAN;
    p->left.i  = k;
    p->right.s = NULL;
    }
  return p;
  }

/* this is where the user types some arbitrary string which is a numeric constant */
expression_t * compile_constant_string(int k,char * s ) {
  expression_t * p;
  p = calloc(1,sizeof(expression_t));
  
  if(p) {
    p->opcode = EXP_CONSTANT;
    p->left.i  = k;
    p->right.s = ISNULLSTR(s)?NULL:strdup(s);
    }
  return p;
  }
/* this is where the user types some arbitrary string which is a boolean constant */
expression_t * compile_boolean_constant_string(int k,char * s ) {
  expression_t * p;
  p = calloc(1,sizeof(expression_t));
  
  if(p) {
    p->opcode = EXP_BOOLEAN;
    p->left.i  = k;
    p->right.s = ISNULLSTR(s)?NULL:strdup(s);
    }
  return p;
  }

/* this compiles a reference to the variable */  
expression_t * compile_variable(generic_info_t * generic , char * valname) {
  expression_t * p;
  p = calloc(1,sizeof(expression_t));
  
  if(p) {
    p->opcode   = EXP_VARIABLE;
    p->left.g   = generic;
    p->right.s  = valname;
    }
  return p;
  }


expression_t * compile_string(char * s) {
  expression_t * p;
  p = (expression_t *)calloc(1,sizeof(expression_t));
  
  if(p) {
    p->opcode = EXP_STRING;
    p->left.s = ISNULLSTR(s)?NULL:strdup(s);
    }
  return p;
  }


expression_t * compile_char(char c) {
  expression_t * p;
  p = (expression_t *)calloc(1,sizeof(expression_t));
  
  if(p) {
    p->opcode = EXP_CHAR;
    p->left.i = c;
    }
  return p;
  }

  
expression_t * compile_reference(char * s) {
  expression_t * p;
  p = (expression_t *)calloc(1,sizeof(expression_t));
  
  if(p) {
    p->opcode = EXP_UNDEF_VAR;
    p->right.s = ISNULLSTR(s)?NULL:strdup(s);
    }
  return p;
  }


  
expression_t * compile_expression(int opcode, 
       expression_t * l,
       expression_t * r ) {
  expression_t * p;
  p = (expression_t *)calloc(1,sizeof(expression_t));
  if(p) {
    p->opcode = opcode;
    p->left.e  = l;
    p->right.e = r;
    }
  return p;
  }






void print_expression(FILE * f,expression_t * e ,
                      generic_print_style recurse_generics) {
  if (!e) {
     fprintf(f,"(NULL)");
     return;
     }
  switch (e->opcode) {
    case EXP_UNDEF_VAR :
      if (e->right.s) 
        fprintf(f,"%s",e->right.s);
      break;
    case EXP_STRING :
      if (e->left.s) 
        fprintf(f,"\"%s\"",e->left.s);
      break;
    case EXP_CHAR :
        fprintf(f,"\'%c\'",e->left.i);
      break;
    case EXP_CONSTANT :
      if (e->right.s)
        fprintf(f,"%s",e->right.s);
      else
        fprintf(f,"%d",e->left.i);
      break;
    case EXP_VAR_REF :
/*      if (e->right.s)
        fprintf(f,"%s",e->right.s);
      else */
        fprintf(f,"%d",*(e->left.ip));
      break;
    case EXP_BOOLEAN :
      if (e->right.s)
        fprintf(f,"%s",e->right.s);
      else
        fprintf(f,"%s",e->left.i?"true":"false");
      break;
    case EXP_VARIABLE :
      if (e->left.g) {
        if(recurse_generics!=NO_RECURSE && 
           e->left.g->expr  &&
           (recurse_generics==RECURSE_NUMBER || e->left.g->expr->opcode != EXP_CONSTANT)) {
          fprintf(f,"(");
          print_expression(f, e->left.g->expr,recurse_generics);
          fprintf(f,")");
          }
        else
          fprintf(f,"%s",e->right.s);
        }
      else
        fprintf(f,"((%s))",e->right.s);

      break;
    case UMINUS:
      fprintf(f,"(-");
      if(e->left.e->opcode != EXP_CONSTANT)
         fprintf(f,"(");
      print_expression(f,e->left.e,recurse_generics);
      if(e->left.e->opcode != EXP_CONSTANT)
         fprintf(f,")");
      fprintf(f,")");
      break;
    case '~':
      fprintf(f,"(~");
      if(e->left.e->opcode != EXP_CONSTANT)
         fprintf(f,"(");
      print_expression(f,e->left.e,recurse_generics);
      if(e->left.e->opcode != EXP_CONSTANT)
         fprintf(f,")");
      fprintf(f,")");
      break;
    case '!':
      fprintf(f,"(!");
      if(e->left.e->opcode != EXP_CONSTANT)
         fprintf(f,"(");
      print_expression(f,e->left.e,recurse_generics);
      if(e->left.e->opcode != EXP_CONSTANT)
         fprintf(f,")");
      fprintf(f,")");
      break;
    case '(' :
      fprintf(f,"(");
      print_expression(f,e->left.e,recurse_generics);
      fprintf(f,")");
      break;
    case '+' :
    case '-' :
    case '*' :
    case '/' :
    case '%' :
    case '^' :
    case '?' :
    case ':' :
    case '>' :
    case '<' :
    case '&' :
    case '|' :
    
      print_expression(f,e->left.e,recurse_generics);
      fprintf(f,"%c",e->opcode);
      print_expression(f,e->right.e,recurse_generics);
      
      break;
    case SHL :  
      print_expression(f,e->left.e,recurse_generics);
      fprintf(f,"<<");
      print_expression(f,e->right.e,recurse_generics);
      break;
    case SHR :  
      print_expression(f,e->left.e,recurse_generics);
      fprintf(f,">>");
      print_expression(f,e->right.e,recurse_generics);
      break;
    case EQ_EQ :  
      print_expression(f,e->left.e,recurse_generics);
      fprintf(f,"==");
      print_expression(f,e->right.e,recurse_generics);
      break;
    case N_EQ :  
      print_expression(f,e->left.e,recurse_generics);
      fprintf(f,"!=");
      print_expression(f,e->right.e,recurse_generics);
      break;
    case LOG_AND :  
      print_expression(f,e->left.e,recurse_generics);
      fprintf(f,"&&");
      print_expression(f,e->right.e,recurse_generics);
      break;
    case LOG_OR :  
      print_expression(f,e->left.e,recurse_generics);
      fprintf(f,"||");
      print_expression(f,e->right.e,recurse_generics);
      break;
    case TO_POW :  
      print_expression(f,e->left.e,recurse_generics);
      fprintf(f,"**");
      print_expression(f,e->right.e,recurse_generics);
      break;
    default : 
      fprintf(f,"(?? expression ERROR : OPCODE 0x%X)",e->opcode);
   
      }

  }
  
  
  
/* a range is permitted at the top level of an expression */  
/* if there is no expression return */
void print_range_expression(FILE * f, expression_t * e,generic_print_style recurse_generics) {
  if (!e) return;
  switch (e->opcode) { 
    case TO : 
      fprintf(f,"(");
      print_expression(f,e->left.e,recurse_generics);
      fprintf(f," TO ");
      print_expression(f,e->right.e,recurse_generics);
      fprintf(f,")");
    break;
    
    case DOWNTO : 
      fprintf(f,"(");
      print_expression(f,e->left.e,recurse_generics);
      fprintf(f," DOWNTO ");
      print_expression(f,e->right.e,recurse_generics);
      fprintf(f,")");
    break;

    case EXP_VARIABLE :
      if (e->left.g) {
        if(recurse_generics != NO_RECURSE)
          print_range_expression(f, e->left.g->expr,recurse_generics);
        else
          fprintf(f,"(%s)",e->right.s);
        }
      else
        fprintf(f,"((??%s))",e->right.s);

      break;

        
        
    default :
      /* handle the expressions down each level of the hierarchy */
/*      fprintf(f,"("); */
      print_expression(f,e,recurse_generics);
/*      fprintf(f,")"); */
    }
  }           
    
    
 
void print_msg_expression(FILE * f,char * s, expression_t *e) {
  fprintf(f,"%s '",s);
  print_range_expression(f,e,NO_RECURSE);
  fprintf(f,"'\n");
  }


    
/* evaluate an integer expression : checking local generics if they are available  */     
int eval_expression(expression_t * e,generic_info_t ** chip_generics ) {
  int r = 0;
  if (!e) return 0;

  switch (e->opcode) {
    case EXP_CONSTANT :
    case EXP_BOOLEAN:
      r = e->left.i;
      break;
    case EXP_VAR_REF :
      r = *(e->left.ip);
      break;
    /* when evaluating expression, if a generic in scope is found then the 
       generic will be updated : ends up creating and cross-linking a
       partition generic */
    case EXP_UNDEF_VAR : 
      {
      generic_info_t * gen;
      gen = NULL;
      if (chip_generics)
        {
        gen = get_generic_ref(chip_generics,e->right.s);
        }
        /* search outwards */
      if (!gen)
        {
        gen = get_generic_ref(&global_generics,e->right.s);
        }
      if (!gen) 
        {/* scope is external not local */
        expr_ref_t * link;
        gen = get_generic_ref(&partition_generics,e->right.s);
        /* if no partition generic appears, make one */ 
        if(!gen)
          {
          generic_info_t newgen;
          newgen.typename  = "integer";
          newgen.name = e->right.s; 

          newgen.valid     = 1;
          newgen.expr      = compile_constant(0);
          newgen.g_type    = IS_INTEGER;
          newgen.g_class   = DEFINED;

          gen = set_generic_value(&partition_generics, &newgen);
          }
        if(gen)
          {  
          link = calloc(1,sizeof(expr_ref_t));
          }
        if(gen && link)
          {
          link -> expr_ref = gen -> expr_ref;
          gen  -> expr_ref = link;
          link -> expr     = e;
          }     
        }                                                      
      if(gen)
        {
        e->opcode = EXP_VARIABLE;
        e->left.g = gen;
/* having located a valid generic then try to link it up */

        
/* duplicate code borrowed from below. Avoiding 'goto' !! */
        eval_gen_expression(gen);
        if( gen->g_type==IS_ATTRIBUTE || gen->g_type==IS_INTEGER) {
          r = eval_expression(gen->expr,chip_generics);
#if defined DEBUG_EXPRESSION
          printf("eval %s = %d\n",gen->name,r);
#endif
          }
        else {
          Log(LOG_ERROR,"#Error : generic %s has non integer type (code %d)\n",gen->name,gen->g_type);
          r= 0;
          }
        }
      else
        {

        Log(LOG_ERROR,"# symbol '%s' is not defined\n",e->right.s);    
        }    
      
      }
      break;
    case EXP_VARIABLE :
      { 
      generic_info_t * gen;
      gen = e->left.g;
        
      if (gen) {
        eval_gen_expression(gen);
        if( gen->g_type==IS_ATTRIBUTE || gen->g_type==IS_INTEGER) {
          r = eval_expression(gen->expr,chip_generics);
#if defined DEBUG_EXPRESSION
          printf("eval %s = %d\n",gen->name,r);
#endif
          }
        else {
          Log(LOG_ERROR,"#Error : generic %s has non integer type (code %d)\n",gen->name,gen->g_type);
          r= 0;
          }
        }

      else
         Log(LOG_ERROR,"#Error : generic '%s' not found\n",e->right.s);
      }
      break;
    case EXP_CHAR   :
      r= e->left.i;
      break;
    case EXP_STRING :
      r= 0;
      break;
    case '(' :
      r= eval_expression(e->left.e,chip_generics);
      break;
    case UMINUS :
      r= 0-eval_expression(e->left.e,chip_generics);
      break;
    case '~' :
      r= ~eval_expression(e->left.e,chip_generics);
      break;
    case '!' :
      r= !eval_expression(e->left.e,chip_generics);
      break;
    case '+' :
      r= eval_expression(e->left.e,chip_generics)+eval_expression(e->right.e,chip_generics);
      break;
    case '-' :
      r= eval_expression(e->left.e,chip_generics)-eval_expression(e->right.e,chip_generics);
      break;
     case '*' :
      r= eval_expression(e->left.e,chip_generics)*eval_expression(e->right.e,chip_generics);
      break;
     case '/' :
      {
      int rhs;
      rhs = eval_expression(e->right.e,chip_generics);
      if(rhs)
        {
        r= eval_expression(e->left.e,chip_generics)/rhs;
        }
      else
        {
        Log(LOG_ERROR,"# ERROR: Division by 0\n");
        r=0;
        };
      }
      break;
     case '%' :
      {
      int rhs;
      rhs = eval_expression(e->right.e,chip_generics);
      if(rhs)
        {
        r= eval_expression(e->left.e,chip_generics)%rhs;
        }
      else
        {
        Log(LOG_ERROR,"# ERROR: Modulus by 0\n");
        r=0;
        };
      }
      break;
     case '^' :
      r= eval_expression(e->left.e,chip_generics)^eval_expression(e->right.e,chip_generics);
      break;
     case '|' :
      r= eval_expression(e->left.e,chip_generics)|eval_expression(e->right.e,chip_generics);
      break;
     case '&' :
      r= eval_expression(e->left.e,chip_generics)&eval_expression(e->right.e,chip_generics);
      break;
     case '>' :
      r= eval_expression(e->left.e,chip_generics)>eval_expression(e->right.e,chip_generics);
      break;
     case '<' :
      r= eval_expression(e->left.e,chip_generics)<eval_expression(e->right.e,chip_generics);
      break;
     case EQ_EQ :
      r= eval_expression(e->left.e,chip_generics)==eval_expression(e->right.e,chip_generics);
      break;
     case N_EQ:
      r= eval_expression(e->left.e,chip_generics)!=eval_expression(e->right.e,chip_generics);
      break;
     case LOG_OR:
      r= eval_expression(e->left.e,chip_generics)||eval_expression(e->right.e,chip_generics);
      break;
     case LOG_AND:
      r= eval_expression(e->left.e,chip_generics)&&eval_expression(e->right.e,chip_generics);
      break;      
     case SHL :
      r= eval_expression(e->left.e,chip_generics)<<eval_expression(e->right.e,chip_generics);
      break;
     case SHR :
      r= eval_expression(e->left.e,chip_generics)>>eval_expression(e->right.e,chip_generics);
      break;      
     case '?' :
      r= eval_expression(e->left.e,chip_generics) ? eval_expression(e->right.e->left.e,chip_generics) :
                                                    eval_expression(e->right.e->right.e,chip_generics) ;
      break;
     case TO_POW : {
       int i,y,x;
       x = eval_expression(e->left.e,chip_generics);
       y = eval_expression(e->right.e,chip_generics);
       if (y==0)  /* x**0 = 1 */
         r=1; 
       else if (y<0 ) /* negative powers */
         r=0;
       else {
         i = y; /* limit power */
         if (i > 32) {
           Log(LOG_ERROR,"arithmetic power of: %d ** %d : %d > 32: limited to 32\n",x,y,y);
           i = 32; }
         r = x;
         while(--i)
           r *= x;
         }
       }
    break;
     default :
       Log(LOG_ERROR,"#Error : expression : illegal operator (%d)\n",e->opcode);
      }
/*  printf("(%d)",r); */
   return r;
  }



int eval_vhdl_expression(expression_t * expr,
                         int * high,
                         int * low ) {
  int rc;

  generic_info_t ** chip_generics = NULL; /* no local search scope, order of declaration should ensure that
                                           generics are defined before use */

  if (!expr) return 0;
/* my be range at top level in variable */
  if(expr->opcode == EXP_VARIABLE)
    expr = expr->left.g->expr;

  if (!expr) return 0;
  
  switch (expr->opcode) { 
   


    case TO: 
      *high = eval_expression(expr->left.e,chip_generics);
      *low  = eval_expression(expr->right.e,chip_generics);
      rc = TO;
    break;
    
    case DOWNTO: 
      *high = eval_expression(expr->left.e,chip_generics);
      *low  = eval_expression(expr->right.e,chip_generics);
      rc = DOWNTO;
    break;
    
    
    default:
      /* handle the expressions down each level of the hierarchy */
      *high = eval_expression(expr,chip_generics);
      *low  = *high;
      rc = IS_INTEGER;
    break;
    }
#if defined DEBUG_EXPRESSION
  print_msg_expression(stdout,"eval vhdl ",expr);
  printf("high %d low %d rc %d\n",
      *high,*low,
      rc );
#endif
  return rc;
  }


int eval_gen_expression(
       generic_info_t * gen) {
#if defined NEED_EVAL_GEN
  expression_t * exp;
  if (gen) {
    exp = gen->expr;
/*    printf("Ptr %p: ",exp); */
    if (exp) {
      switch (exp->opcode) {
        case EXP_STRING :
          gen->valuename = exp->left.s;
          gen->g_type    = IS_STRING;
          gen->valid     = 1;
          break;
        case TO : 
          gen->valid = 1;
          gen->g_type = TO;   
   
          break;
    
        case DOWNTO : 
          gen->valid = 1;
          gen->g_type = DOWNTO;   
        break;
        default :
      /* handle the expressions down each level of the hierarchy */
          gen->valid = 1;
          gen->g_type = IS_INTEGER;   
        }
      gen->g_class = DEFINED; 
      return gen->g_type;
      }
    }

  return NO_VALUE;
#else
  return gen->g_type;
#endif
  }

/* delete any expression pointed to */
void free_expression(expression_t * ptr) {

  if (!ptr)
    return;
  switch(ptr->opcode) {
    case EXP_STRING:
      if(ptr->left.s)
        free(ptr->left.s); 
    case EXP_CONSTANT:
    case EXP_BOOLEAN:
    case EXP_VARIABLE:
    case EXP_VAR_REF:
      if(ptr->right.s)
        free(ptr->right.s); /* remove string */
      break;
    default:
      if (ptr->left.e) 
        free_expression(ptr->left.e);
      if (ptr->right.e)
        free_expression(ptr->right.e);
      break;

    }
  free(ptr);
  }
/* copy the expression, fixing up the references to local generic constants
   at the same time . Need to */
expression_t * copy_expression(expression_t * ptr,socket_t * skt) {
  expression_t * copy;
  if(!ptr)
    return NULL;
  switch(ptr->opcode) {
    case EXP_CONSTANT :
    case EXP_BOOLEAN :
    case EXP_STRING :
    case EXP_VAR_REF:
    case EXP_VARIABLE:
    case EXP_CHAR:
      return ptr;  /* no copy needed as this is a terminal node that cannot change */
      break;
/* duplicate undefined references so each induvidual expression is fixed up */
    case EXP_UNDEF_VAR:
        copy = calloc(1,sizeof(expression_t));
        *copy = *ptr;
      return copy;
      break;
    default:
      return compile_expression(ptr->opcode,
        copy_expression(ptr->left.e,skt),
        copy_expression(ptr->right.e,skt));
      break;
      }
    return NULL;
    }


struct vhdl * copy_vhdl(vhdl_t * vhdl,socket_t * skt) {
  vhdl_t * new_vhdl;
  if(!vhdl)
    return NULL;
  new_vhdl = calloc(1,sizeof(vhdl_t));
  *new_vhdl = *vhdl;
  new_vhdl->expr = copy_expression(vhdl->expr,skt);
  new_vhdl->default_expr = copy_expression(vhdl->default_expr,skt);
#if defined DEBUG_EXPRESSION
  printf("Type = %s\n",vhdl->basetype);
  print_msg_expression(stdout,"Copied expr",new_vhdl->expr);
  print_msg_expression(stdout,"Copied default",new_vhdl->default_expr);
#endif
  return new_vhdl;
  }



