
/* contains the database functions that store the pin configurations
 *
 * $Header: c:\\cygwin\\cvsroot/Vert03/vertlib/database.c,v 1.1.1.1 2003/11/04 23:34:57 mjames
 * Exp $ $Log: database.c,v $ Revision 1.1.1.1  2003/11/04 23:34:57  mjames Imported into local
 * repositrory
 *
 * Revision 1.13  2003/01/02 21:37:15  mjames
 * Experiment on creating NOT_ROUTABLE_H and NOT_ROUTABLE_L
 * properties on the nets so that pin jumpers can be made without a problem.
 *
 * Still need to sort out pin assignments made to these not_routable nets
 * which will become legal in some cases so that pullups and pulldown
 * pins can be used on the FPGA.
 *
 * Revision 1.12  2002/09/30 13:26:49  MJAMES
 * Upgraded nets to include 'lhs_expression' being the range on the
 * left hand side of a signal connection to a port
 *
 * std_logic_vector (0) <= std_logic , on a port of a chip
 *
 * Revision 1.11  2002/08/06 12:52:54  mjames
 * Merge in from latest version
 *
 *
 * Revision 1.11  2002/03/21 17:13:05  mjames
 * Added search path to vertical file opening for read
 *
 * Revision 1.10  2002/01/15 12:32:42  mjames
 * DLL declarations put in,
 *
 * #ident used
 *
 * Revision 1.9  2001/11/19 09:45:25  mjames
 * Corrected some case statments with no default action
 *
 * Revision 1.8  2001/10/31 22:20:02  mjames
 * Tidying up problematical comments caused by CVS
 * 'intelligent' comment guessing
 *
 * Revision 1.7  2001/10/31 16:22:55  mjames
 * Added a datastructure to hide regular expression information from programs.
 * Changed call to regexec to indicate 0 subexpressions to be matched
 * rather than a number dependent on strlen(string) which was wrong.
 * Net disconnection works on routed and named nets
 *
 * Revision 1.6  2001/10/23 21:12:43  mjames
 * Created preliminary 'disconnect_node' function
 *
 * Revision 1.5  2001/10/10 20:18:24  mjames
 * Added a vert_regcomp function to compile regular expressions
 * with '^' (match start string) and  '$' (match end string) bracketing
 * this => wildcard must match entire string not just a part of it.
 *
 * Revision 1.4  2001/10/07 20:50:53  mjames
 * Added wildcard checking (warn user about
 * using wildcard '*' on the end of a string in stead of wildcard '.*')
 *
 * Revision 1.3  2001/09/25 23:15:24  mjames
 * Converted wildcards to use proper regexp pattern match library
 *
 * Revision 1.2  2001/06/06 12:10:24  mjames
 * Move from HPUX
 *
 * Revision 1.1.1.1  2000/10/19 21:58:35  mjames
 * Mike put it here
 *
 *
 * Revision 1.61  2000/10/04  10:37:03  10:37:03  mjames (Mike James)
 * COnversion to Vertical2, supports signals and components
 *
 * Revision 1.61  2000/10/04  10:37:03  10:37:03  mjames (Mike James)
 * Part of Release PSAVAT01
 *
 * Revision 1.60  2000/10/03  10:05:27  10:05:27  mjames (Mike James)
 * Added CONSTANTS and SIGNALS to architecture
 *
 * Revision 1.58  2000/09/27  14:42:11  14:42:11  mjames (Mike James)
 * Part of Release Sep_27_ST_2000
 *
 * Revision 1.57  2000/09/21  10:15:40  10:15:40  mjames (Mike James)
 * Part of Release Sep21Alpha
 *
 * Revision 1.56  2000/09/21  09:44:29  09:44:29  mjames (Mike James)
 * Added in code to deal with pin equivalents, and removed some
 * spurious diagnostic puts() calls .
 *
 * Revision 1.55  2000/08/25  09:57:09  09:57:09  mjames (Mike James)
 * Part of Release Aug25_alpha
 *
 * Revision 1.54  2000/08/16  08:57:26  08:57:26  mjames (Mike James)
 * Part of Release CD01_Aug2000
 *
 * Revision 1.53  2000/08/14  14:45:07  14:45:07  mjames (Mike James)
 * Part of Release Aug_14_2000
 *
 * Revision 1.52  2000/08/11  08:30:28  08:30:28  mjames (Mike James)
 * Part of Release Aug_11_2000
 *
 * Revision 1.51  2000/08/09  10:31:41  10:31:41  mjames (Mike James)
 * Part of Release Aug__9_2000
 *
 * Revision 1.50  2000/05/31  11:42:48  11:42:48  mjames (Mike James)
 * Part of Release May_31_2000
 *
 * Revision 1.49  2000/05/08  17:01:33  17:01:33  mjames (Mike James)
 * Part of Release May__8_2000
 *
 * Revision 1.48  2000/05/08  16:59:26  16:59:26  mjames (Mike James)
 * Part of Release May__8_2000
 *
 * Revision 1.47  2000/05/08  16:57:03  16:57:03  mjames (Mike James)
 * Part of Release May__8_2000
 *
 * Revision 1.46  2000/03/08  16:18:48  16:18:48  mjames (Mike James)
 * New version including PC
 *
 * Revision 1.43  2000/02/18  15:45:24  15:45:24  mjames (Mike James)
 * Amended to support PC
 *
 * Revision 1.42  2000/01/20  15:58:41  15:58:41  mjames (Mike James)
 * Part of Release R22
 *
 * Revision 1.41  99/12/22  11:15:22  11:15:22  mjames (Mike James)
 * Part of Release Dec_22_1999
 *
 * Revision 1.40  99/06/25  14:34:42  14:34:42  mjames (Mike James)
 * Added in reference to expression.h, but no changes made
 * to the function of acfread yet.
 *
 * Revision 1.39  99/06/18  09:23:19  09:23:19  mjames (Mike James)
 *
 * Revision 1.38  99/05/04  09:50:36  09:50:36  mjames (Mike James)
 * General checkin
 *
 * Revision 1.34  98/08/12  14:19:52  14:19:52  mjames (Mike James)
 * Changed pin definition code to work with VHDL
 * parsing
 * as well as include file list being updated
 *
 * Revision 1.33  98/06/15  14:17:51  14:17:51  mjames (Mike James)
 * Added socket templating pointers - reference to parent template
 * for child template.
 *
 * Revision 1.32  98/02/11  11:25:52  11:25:52  mjames (Mike James)
 * Checked in for version 6.2a
 *
 * Revision 1.31  98/01/13  11:33:35  11:33:35  mjames (Mike James)
 * Added the bility to use a VHDL template file
 * containing $ENT$ and $ARCH$ in the position where one
 * wants the entity and architecture to be given.
 *
 * Revision 1.30  97/04/23  08:42:49  08:42:49  mjames (Mike James)
 * CHecked in for release rel23041997
 *
 * Revision 1.29  96/12/23  15:13:48  15:13:48  mjames (Mike James)
 * Added reverse pointer to show which unrouted net was
 * responsible for the fixing of the pins.
 *
 * Revision 1.28  96/12/23  10:24:02  10:24:02  mjames (Mike James)
 * Altered to make it sort the results
 * of listing COMPONENTS and CHIP pins.
 * /
 *
 * Revision 1.27  96/12/13  08:43:08  08:43:08  mjames (Mike James)
 * Update to v5.1, added Write ID , exact routing
 *
 * Revision 1.26  96/08/06  13:38:51  13:38:51  mjames (Mike James)
 * Added FIX_LOCATION pin attribute to netlist
 *
 * Revision 1.25  96/07/19  14:38:43  14:38:43  mjames (Mike James)
 * Update to give to PRL
 *
 * Revision 1.24  1996/07/12  15:52:12  mjames
 * Sorted out things like Alias and Jumpers
 * Work Correctly
 * Print COrrectly
 *
 * Revision 1.23  96/07/09  15:53:59  15:53:59  mjames (Mike James)
 * Altered aliasing to make it hierarchical, also for jumpering
 *
 * Revision 1.22  96/06/17  11:02:43  11:02:43  mjames (Mike James)
 * Altered the printing of JUMPERED and ALIASED nets
 * ,
 *
 * Revision 1.21  96/06/11  14:11:44  14:11:44  mjames (Mike James)
 * Added hierarchical jumpering
 *
 * Revision 1.20  96/06/04  11:53:18  11:53:18  mjames (Mike James)
 * Added the ability to jumper nets by reference to a node on the nets
 *
 * Revision 1.19  96/05/29  10:52:29  10:52:29  mjames (Mike James)
 *  Added name suffixing to socket ID's and net ID's
 *
 * Revision 1.18  96/04/26  16:01:30  16:01:30  mjames (Mike James)
 * Added SET PORT to force ports on partition
 * ,
 *
 * Revision 1.17  96/04/15  14:19:24  14:19:24  mjames (Mike James)
 * Checkin before datatype printing
 * modifications
 *
 * Revision 1.16  96/03/29  14:46:05  14:46:05  mjames (Mike James)
 * Added VHDL netlist writing to the capabilities of ACFREAD
 *
 * Revision 1.14  96/03/18  13:50:28  13:50:28  mjames (Mike James)
 * Real Revision 2.1
 *
 * Revision 1.11  96/03/13  15:35:30  15:35:30  mjames (Mike James)
 * Changed the name_pref filed to reflect how a net has been routed
 *
 * Revision 1.10  96/02/13  09:13:28  09:13:28  mjames (Mike James)
 * Updated to be version 2.0 with net joining
 *
 * Revision 1.9  96/02/09  10:50:24  10:50:24  mjames (Mike James)
 * Added different behaviour for 'write id' and 'write name'
 * 'write id' now writes all pins including unused ones
 * 'write name' only writes used pins in the ACF file
 *
 *  .
 *
 *
 * Revision 1.8  96/02/08  15:28:29  15:28:29  mjames (Mike James)
 * First release
 *
 * Revision 1.7  96/02/07  16:01:34  16:01:34  mjames (Mike James)
 * Added correct RCS header
 *
 * Revision 1.6  96/02/07  15:50:44  15:50:44  mjames (Mike James)
 * Added RCS ident message
 *
 * Revision 1.5  96/02/07  11:04:07  11:04:07  mjames (Mike James)
 * Checkin before adding new command parsing to program
 *
 * Revision 1.4  96/01/10  13:14:11  13:14:11  mjames (Mike James)
 *  Works in debug mode with EPLD listings and PCB layout
 *
 * Revision 1.3  96/01/08  15:22:51  15:22:51  mjames (Mike James)
 * Managing to make sense of things now
 *
 * Revision 1.2  96/01/07  20:22:29  Mike_James
 * extending database routines
 *
 * Revision 1.1  96/01/07  12:38:12  Mike_James
 * Initial revision
 *
 * Revision 1.2  96/01/04  17:55:52  17:55:52  mjames (Mike James)
 * Correcly reading ACF
 *
 * Revision 1.1  96/01/04  11:37:22  11:37:22  mjames (Mike James)
 * Initial revision
 *
 */
#include "database.h"

#include "acf_yacc.h"
#include "chck_names.h"
#include "cmdlog.h"
#include "cmdparse.h"
#include "expression.h"
#include "generic.h"
#include "lx_support.h"
#include "sorting.h"
#include "version.h"
#include "vertcl_main.h"

#include <ctype.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#ident                                                                                        \
    "@(#)$Header: c:\\cygwin\\cvsroot/Vert03/vertlib/database.c,v 1.1.1.1 2003/11/04 23:34:57 mjames Exp $"

vhdl_t *default_vhdl_datatype;
vhdl_t *default_vhdl_bustype;

/* string constants used around the place*/

char nullstr[] = "";

/* database pointers */
__declspec(dllexport) socket_t *socket_head = NULL;

__declspec(dllexport) socket_t *template_head = NULL;

net_t *routed_list = NULL;
net_t *named_list = NULL;
net_t *named_tail = NULL; /* as routed nets are moved to the named list */
net_t *unrouted_list = NULL;

/* these are ident counters. The first counts net identifiers */
static int n_idents = 1; /* net identifiers */
static int s_idents = 1; /* socket identifiers */
static int i_idents = 1; /* pin identifiers */

/* compares two strings case insensitive with a pointer sanity check */

int strcmp2 (char *s, char *t)
{
        if (!s || !t)
                return (-1);
        for (; tolower (*s) == tolower (*t); s++, t++)
                if (*s == 0)
                        return (0);
        return (tolower (*s) - tolower (*t));
}

/* allocates a space for a string */

#if !defined allocstr
/* we now use strdup.... */
char *allocstr (char *s)
{
        char *t;
        /* added a check for allocating null string
         *  (its strlen that bombs in CygWin) */
        if (!s)
                return NULL;

        t = malloc (strlen (s) + 1);
        strcpy (t, s);
        return t;
}
#endif

/* allocates a space for a string and a suffix dependent on property */

#if defined USE_ALLOCSTR_PROP
static char *allocstr_prop (char *s, property_t prop)
{
        char *t;
        switch (prop)
        {
        case Ident:
        case Type:
        case Name:
        case Value:
                t = strdup (s);
                break;
        }
        return t;
}
#endif

/* this is a check on a socket ident - if absent, generates one  */

__declspec(dllexport) void ensure_socket_ident (socket_t *chip)
{
        char id[10];
        if (chip->identifier == nullstr)
        {
                sprintf (id, "ID%d", s_idents++);
                set_socket (chip, Ident, id);
        };
}

/* set a socket property */
__declspec(dllexport) void set_socket (socket_t *chip, property_t prop, char *str)
{
        char *s;
        s = strdup (str);

        /*   printf("(Set socket prop%d to %s)",prop,s); */
        switch (prop)
        {
        case Ident:
                chip->identifier = s;
                break;
        case Type:
                chip->type = s;
                break;
        case Name:
                chip->name = s;
                break;
        case Value:
                chip->value = s;
                break;
        default:
                break;
        };
}

/* find a socket property */
__declspec(dllexport) socket_t *find_socket (
    property_t prop, char *str, int srchonly, socket_t **headref)
{
        socket_t *c = *headref, *p = NULL;
        int f = 0;
        /* printf("-- Socket %s : prop %d pointer=%p\n",str,prop,c); */

        while (c)
        {
                switch (prop)
                {
                case Ident:
                        f = strcmp2 (c->identifier, str) == 0; /*puts(c->identifier); */
                        break;
                case Type:
                        f = strcmp2 (c->type, str) == 0;
                        break;
                case Name:
                        f = strcmp2 (c->name, str) == 0; /*puts(c->name);*/
                        break;
                case Value:
                        f = strcmp2 (c->value, str) == 0;
                        break;
                default:
                        break; /* never find if wrong field specified */
                };
                if (f)
                        break;
                p = c;
                c = c->next;
        };

        if (srchonly || f)
                return (c);

        c = calloc (1, sizeof (socket_t)); /* all pointers are set to be null */

        c->identifier = nullstr;
        c->type = nullstr;
        c->name = nullstr;
        c->value = nullstr;

        set_socket (c, prop, allocstr (str));

        /* link in otherwise */
        if (p)
                p->next = c;
        if (!(*headref))
                *headref = c;
        return c;
}

/* matches s into a table of n strings r[], default value is d */
int str_to_int (char *s, char *r[], int n, int d)
{
        int i;
        for (i = 0; i < n; i++)
                if (strcmp2 (s, r[i]) == 0)
                {
                        d = i;
                        break;
                };
        return d;
}

char *decode_how_routed[] = {"FREE_NAME",
                             "MATCHED_NAME",
                             "USED_WIRES",
                             "USED_FIXED_WIRES",
                             "USED_EXACT_WIRES",
                             "CREATED_NET",
                             "CREATED_JUMPER",
                             "FIXED_PINS",
                             "NOT_ROUTABLE",
                             "NOT_ROUTABLE_L", /* additions V16.5 onward */
                             "NOT_ROUTABLE_H"};

/* set a net property */
__declspec(dllexport) void set_net (net_t *net, property_t prop, char *str)
{
        char *s;
        s = strdup (str);
        switch (prop)
        {
        case Ident:
                net->identifier = s;
                break;
        case Name:
                net->name = s;
                break;
                /*
                    case Datatype:  net->datatype   = s; break;
                */
        case How_Routed:
                net->how_routed = (HowRouted_t) str_to_int (
                    str, decode_how_routed, sizeof (decode_how_routed) / sizeof (char *), 0);
                break;
        default:
                break;
        };
}

/* find a net by property, in a list pointed to by a pointer referred to
   by net_head  */
__declspec(dllexport) net_t *find_net (
    net_t **net_head, property_t prop, char *str, int srchonly)
{
        net_t *c, *p;
        int f = 0;
        c = *net_head;
        p = NULL;
        while (c)
        {
                switch (prop)
                {
                case Ident:
                        f = strcmp2 (c->identifier, str) == 0;
                        break;
                case Name:
                        f = strcmp2 (c->name, str) == 0;
                        break;
                default:
                        break;
                };
                if (f)
                        break;
                p = c;
                c = c->next;
        };
        if (srchonly || f)
                return (c);

        c = calloc (1, sizeof (net_t)); /* all pointers are set to be null */
        c->name = nullstr;
        c->identifier = nullstr;
        c->list_ref = net_head; /* record which list this net is a member of */

        c->nodecount = 0; /* calloc does this :  put here for readability : Oct 2000 */

        c->type_defined = 0;
        set_net (c, prop, str);

        c->list_ref = net_head; /* which list does this net begin life on */

        /* link at end of list otherwise */
        if (p)
                p->next = c;
        c->prev = p; /* and refer back to it */
        if (!(*net_head))
                *net_head = c;

        return c;
}

/* set a node property */
__declspec(dllexport) void set_node (node_t *node, property_t prop, char *str)
{
        char *s;
        s = strdup (str);
        switch (prop)
        {
        case Ident:
                node->identifier = s;
                break;
        case Name:
                node->name = s;
                break;
                /*
                    case Datatype:  node->datatype    = s; break;
                */
        default:
                break;
        };
}

/* locate a node on a chip by a property */
__declspec(dllexport) node_t *find_node (
    socket_t *socket, property_t prop, char *str, int srchonly)
{
        node_t *c, *p;
        int f = 0;

        /* catch null pointer reference 23 May 2001 */
        if (!socket)
                return NULL;

        c = socket->nodes;

        p = NULL;
        while (c)
        {
                switch (prop)
                {
                case Ident:
                        f = strcmp2 (c->identifier, str) == 0;
                        break;
                case Name:
                        f = strcmp2 (c->name, str) == 0;
                        break;
                        /*      case Datatype:  f=strcmp2(c->datatype,str)==0;       break; */
                default:
                        break;
                };
                if (f)
                        break;
                p = c;
                c = c->sktnext;
        };
        if (srchonly || f)
                return (c);

        c = calloc (1, sizeof (node_t)); /* all pointers are set to be null */
        c->name = nullstr;
        c->identifier = nullstr;
        c->socket = socket;

        set_node (c, prop, str);
        /* link at end of list otherwise */
        if (p)
                p->sktnext = c;

        if (!socket->nodes)
                socket->nodes = c;

        socket->lastnode = c;
        return c;
}

/* this connects the node to the list of node references on the net and
   connects the net to the list of net references on the node */

__declspec(dllexport) void connect_node_net (
    char *orig_name,
    node_t *cnode,
    net_t *cnet,
    pindir_t pintype,
    vhdl_t *vhdl,
    vhdl_t *orig_vhdl,
    expression_t *lhs_expr)
{
        noderef_t *noderef;
        cnet->nodecount++; /* one more node on this net */

        cnode->net = cnet; /* refer back to net this node is on */
        cnode->refcount++; /* and count references */

        noderef = calloc (1, sizeof (noderef_t));

        noderef->net = cnet; /* this node reference refers back to its parent net */

        noderef->pindir = pintype; /* the reference has the pin direction _wanted_ */

        noderef->orig_name = orig_name; /* copy any alias over */

        /* remeved reference to datatype */
        noderef->vhdltype = vhdl;

        noderef->orig_vhdltype = orig_vhdl;

        noderef->base_noderef = noderef; /* its original reference is itself */

        noderef->lhs_expr = lhs_expr;

        /* link node  reference to the net */
        noderef->next = cnet->nodes;
        cnet->nodes = noderef; /* place reference on head of list */
        noderef->node = cnode;
}

/* disconnect a node from the netlist */
/* this intends to remove chip node from net in the routed list. If anyone has made a reference
   to the node in a manner which results in this node reappearing then there will be a problem
   as it will reappear (some route algorithms eg. create will do this) */

__declspec(dllexport) void disconnect_node (socket_t *chip, node_t *node)
{
        noderef_t *ref, *last_ref;
        /* locate the net on the routed or named list */
        if (node->net &&
            (node->net->list_ref == &routed_list || node->net->list_ref == &named_list))
        {
                net_t *net;
                net = node->net;
                ref = net->nodes;
                last_ref = NULL;
                /* locate the reference made */
                while (ref)
                {
                        if (ref->node == node)
                                break;
                        last_ref = ref;
                        ref = ref->next;
                }
                /* reference is located. Remove from list of node references,
                   also patch up list head if needed */
                if (ref)
                {
                        if (last_ref == NULL)
                        {
                                net->nodes = ref->next;
                        }
                        else
                        {
                                last_ref->next = ref->next;
                        }
                        free (ref);
                        node->net = NULL; /* disconnect the ned from the node */
                        node->refcount = node->refcount ? node->refcount-- : 0;
                }
        }
}

__declspec(dllexport) void define_pin (
    net_t **net_head,
    socket_t *chip,
    char *i_name,
    int pin_type,
    int pin_group,
    char *i_identifier,
    vhdl_t *vhdl,
    expression_t *lhs_expr)
{
        unrouted_ref_t *ref, *ptr;

        int null_name;
        char name[MAXIDLEN];
        char identifier[MAXIDLEN];

        /* actions here are :
        1: find a new node;
        2: attach a reference to it to the socket pin list;
        3: find the net it is joined to by name;
        */

        null_name = ISNULLSTR (i_name);

        /* if the name is not given, then dont create a net for it as it
           is a waste of time */
        if (null_name)
                /* count another ident for posisble use */
                sprintf (name, "NE%d", n_idents++);
        else
                strcpy (name, i_name);

        if (ISNULLSTR (i_identifier))
                /* count another ident for posisble use */
                sprintf (identifier, "ID%d", i_idents++);
        else
                strcpy (identifier, i_identifier);

        /*   printf("-- Joining name %s to pin %s\n",name,identifier );
         */

        /* at this stage, simply create a potential reference */

        ref = calloc (1, sizeof (unrouted_ref_t));

        ref->pindir = pin_type; /* the reference has the pin direction _wanted_ */
        ref->pin_group = pin_group;
        /* removed reference to datatype */

        ref->vhdltype = copy_vhdl (vhdl, chip);
        ref->orig_vhdltype = NULL;
        ref->identifier = allocstr (identifier);
        ref->name = allocstr (name);
        ref->orig_name = NULL;
        ref->listref = net_head; /* identify the list context */
        ref->lhs_expr = lhs_expr;
        ref->next = NULL;
        if (!chip->unrouted_refs)
                chip->unrouted_refs = ref;
        else
        {
                ptr = chip->unrouted_refs;
                while (ptr->next)
                        ptr = ptr->next;
                ptr->next = ref;
        }

        /* splice the unrouted reference on */
        ref->next = NULL;
}

/* this function clears the name fields on identified nets */
static void del_list_net_names (net_t *list, char *template)
{
        int rc, found;
        char *pattern;
        /* compile regular expression */
        vert_regex_t *preg;

        if (template)
        {
                pattern = template;
        }
        else
        {
                pattern = ".*";
        }

        rc = vert_regcomp (&preg, pattern);

        if (rc != 0)
        {
                char errbuff[100];
                regerror (rc, preg->preg, errbuff, 100);
                Log (
                    LOG_ERROR,
                    "-- Problem (rc=%d) %s with '%s' as regular expression\n",
                    rc,
                    errbuff,
                    pattern);

                return /*TCL_ERROR*/;
        }

        Log (
            LOG_GENERAL,
            "-- Beginning clearing name fields : net ID prefix '%s' --\n",
            template ? template : "[ALL ID's]");
        while (list)
        {
                found = regexec (preg->preg, list->identifier, 0, preg->regpatt, 0);
                if (!found)
                {
                        Log (
                            LOG_GENERAL,
                            "-- Cleared name field for net ID '%s'\n",
                            list->identifier);
                        list->name = nullstr;
                }
                list = list->next;
        }
        Log (LOG_GENERAL, "-- Finished clearing name fields --\n");
        vert_regfree (&preg);
}

__declspec(dllexport) void del_net_names (char *template)
{
        del_list_net_names (routed_list, template);
}

/* added 8 March 2000 for PC support */

__declspec(dllexport) void ensure_env_var (char *name, char *defval)
{
        generic_info_t gen[1];
        if (get_generic_value (&global_generics, name, gen) != IS_STRING)
        {
                char sbuff[MAXIDLEN];
                gen->name = name;
                gen->typename = "env_string";
                /* cannot use $(1) type command line variables as
                 *they are not passed here :  argc = 0 , argv = NULL*/
                expand_string (defval, sbuff, 0, NULL);
                gen->expr = compile_string (sbuff);
                gen->g_type = IS_ENV_VAL;
                gen->g_class = DEFAULT;

                set_generic_value (&global_generics, gen);
        };
}

/* initialise default information used around the design database */
__declspec(dllexport) void InitialiseData (void)
{
        generic_info_t gen[1];
        InitialiseVersionStrings ();

        if (!default_vhdl_datatype)
                default_vhdl_datatype = calloc (1, sizeof (vhdl_t));
        if (!default_vhdl_bustype)
                default_vhdl_bustype = calloc (1, sizeof (vhdl_t));

        /* if we are using VHDL then look at the VHDL bus formatting tail*/
        if (get_generic_value (&global_generics, "vhdl_bit_type", gen) == IS_STRING)
        {
                default_vhdl_datatype->basetype = strdup (gen->expr->left.s);
        }
        else
                default_vhdl_datatype->basetype = "std_logic";

        /* if we are using VHDL then look at the VHDL bus formatting tail*/
        if (get_generic_value (&global_generics, "vhdl_bus_type", gen) == IS_STRING)
        {
                default_vhdl_bustype->basetype = strdup (gen->expr->left.s);
        }
        else
                default_vhdl_bustype->basetype = "std_logic_vector";

        default_vhdl_bustype->expr =
            compile_expression (TO, compile_constant (0), compile_constant (0));
        default_vhdl_bustype->is_vector = 1; /* is this port a vector */
        default_vhdl_bustype->is_downto = 1; /* is the vector X TO Y or X DOWNTO Y  */

        /* look up VERTICAL_INIT and give it a default value if unknown */
        ensure_env_var ("VERTICAL_INIT", VERTICAL_INI_PATH);

        ensure_env_var ("VERTICAL_PATH", VERTICAL_PATH);
}

__declspec(dllexport) char *decode_which_list (net_t **list_head)
{
        if (list_head == NULL)
                return "No List";
        if (list_head == &routed_list)
                return "routed list";
        if (list_head == &named_list)
                return "named list";
        if (list_head == &unrouted_list)
                return "unrouted list";
        return "ERROR : unknown";
}