
/* 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 "expression.h"

#include "acf_yacc.h"
#include "cmdlog.h"
#include "cmdparse.h"
#include "database.h"
#include "generic.h"
#include "vertcl_main.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.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;
}