
/*
 *  $Id: rename.c,v 1.2 2003/11/06 04:36:03 mjames Exp $
 *
 * $Log: rename.c,v $
 * Revision 1.2  2003/11/06 04:36:03  mjames
 * Checkin : builds but has problems with object renaming
 *
 * Revision 1.1.1.1  2003/11/04 23:34:57  mjames
 * Imported into local repositrory
 *
 * Revision 1.24  2003/01/02 21:37:17  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.23  2002/10/02 18:41:24  MJAMES
 * Dont print '&a' if the pin_column is expression is less than or equal to zero
 *
 * Revision 1.22  2002/09/18 08:50:10  mjames
 * Removed further sidefects of redefining pin 'a' as 1 in place of '0'
 *
 * Revision 1.21  2002/09/16 14:41:43  mjames
 * Merge back pin indexing bug that meant
 * pin AZ12 was indistinguishable from pin Z12 in
 * rename ident/name commands
 *
 * Revision 1.19  2002/08/23 14:17:29  mjames
 * Regular expressions extended to
 * &a, &n &d , &i as special replacement patterns
 *
 * Revision 1.18  2002/01/21 09:33:30  mjames
 * Appended a null character when copying regular expression
 * matched pattern.
 *
 * Revision 1.17  2001/12/24 20:07:18  mjames
 * Added &D for device identifier in the replacement string in edit_pin as well
 * as &0 .. &9
 *
 * Revision 1.16  2001/12/11 20:30:26  mjames
 * Implemented  regular expression pin  name editing
 *
 * Revision 1.15  2001/11/19 10:21:04  mjames
 * Fixed errors
 *
 * Revision 1.14  2001/11/19 10:02:23  mjames
 * Merge back
 *
 * Revision 1.13.2.1  2001/11/15 22:03:52  mjames
 * Altered the 'alter' command to use two arguments rather than one
 * after TH suggestion.
 *
 * Revision 1.13  2001/10/31 22:28:27  mjames
 * Problems with regular expression argument lists.
 *
 * Revision 1.12  2001/10/31 22:20:14  mjames
 * Tidying up problematical comments caused by CVS
 * 'intelligent' comment guessing
 *
 * Revision 1.11  2001/10/31 16:18:05  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.
 *
 * Revision 1.10  2001/10/18 21:36:17  mjames
 * Added modify pins command : nets inherit identifier from selected socket and pin on that
 * socket to ease cross referencing.
 *
 * Revision 1.9  2001/10/11 16:10:16  mjames
 * Corrections to the SWAP command, and printout so that
 * WRITE net now outputs all chips in the design so that their generics
 * can be passed forward to the next phase.
 *
 * Revision 1.8  2001/10/10 20:18:21  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.7  2001/10/07 20:50:52  mjames
 * Added wildcard checking (warn user about
 * using wildcard '*' on the end of a string in stead of wildcard '.*')
 *
 * Revision 1.6  2001/09/25 23:15:23  mjames
 * Converted wildcards to use proper regexp pattern match library
 *
 * Revision 1.5  2001/08/31 09:37:42  mjames
 * modified rename rules so that un-named objects do not get
 * name suffixes appended.
 *
 * Revision 1.4  2001/07/20 14:49:42  mjames
 * Corrected reading names in on multiple boards : if present in a database file
 * when reading in a suffixed design
 * e.g. CHIP fred
 * Will also get its name suffixed.
 *
 * Revision 1.3  2001/06/06 12:10:18  mjames
 * Move from HPUX
 *
 * Revision 1.2  2001/01/26 21:50:10  mjames
 * Managed to get vertical non TCL to compile again
 *
 * Conversion to argv, argc[] mode of operation continues
 *
 * Revision 1.1.1.1  2000/10/19 21:58:39  mjames
 * Mike put it here
 *
 *
 * Revision 1.26  2000/08/25  09:57:15  09:57:15  mjames (Mike James)
 * Modified for Vertical2 : support COMPONENTS and SIGNALS
 *
 * Revision 1.26  2000/08/25  09:57:15  09:57:15  mjames (Mike James)
 * Part of Release Aug25_alpha
 *
 * Revision 1.25  2000/08/16  08:57:31  08:57:31  mjames (Mike James)
 * Part of Release CD01_Aug2000
 *
 * Revision 1.24  2000/08/14  14:45:12  14:45:12  mjames (Mike James)
 * Part of Release Aug_14_2000
 *
 * Revision 1.23  2000/08/11  08:30:33  08:30:33  mjames (Mike James)
 * Part of Release Aug_11_2000
 *
 * Revision 1.22  2000/08/09  10:31:48  10:31:48  mjames (Mike James)
 * Part of Release Aug__9_2000
 *
 * Revision 1.21  2000/05/31  11:42:58  11:42:58  mjames (Mike James)
 * Part of Release May_31_2000
 *
 * Revision 1.20  2000/05/08  17:01:38  17:01:38  mjames (Mike James)
 * Part of Release May__8_2000
 *
 * Revision 1.19  2000/05/08  16:59:31  16:59:31  mjames (Mike James)
 * Part of Release May__8_2000
 *
 * Revision 1.18  2000/05/08  16:57:08  16:57:08  mjames (Mike James)
 * Part of Release May__8_2000
 *
 * Revision 1.17  2000/03/08  16:19:26  16:19:26  mjames (Mike James)
 * New version including PC
 *
 * Revision 1.14  2000/01/20  15:58:48  15:58:48  mjames (Mike James)
 * Part of Release R22
 *
 * Revision 1.13  99/12/22  11:15:29  11:15:29  mjames (Mike James)
 * Part of Release Dec_22_1999
 *
 * Revision 1.12  99/06/25  14:35:49  14:35:49  mjames (Mike James)
 * Added in reference to expression.h, but no changes made
 * to the function of acfread yet.
 *
 * Revision 1.11  99/05/04  09:52:43  09:52:43  mjames (Mike James)
 * General checkin
 *
 * Revision 1.10  98/08/12  14:22:18  14:22:18  mjames (Mike James)
 * Corrected include file list
 *
 * Revision 1.9  98/04/24  14:07:51  14:07:51  mjames (Mike James)
 *  Added pin name swapping code
 *
 * Revision 1.8  98/03/16  11:38:24  11:38:24  mjames (Mike James)
 * Removed an old bug - suffixing of PCB names has been broken for about
 * a year. If a pcb were read in non-suffixed and then another with a suffix,
 * the suffix would be applied over all of the sockets and nets, not just the new ones.
 *
 * Revision 1.7  98/02/11  11:27:06  11:27:06  mjames (Mike James)
 * Checked in for version 6.2a
 *
 * Revision 1.6  97/04/23  08:43:22  08:43:22  mjames (Mike James)
 * CHecked in for release rel23041997
 *
 * Revision 1.5  96/07/19  14:38:51  14:38:51  mjames (Mike James)
 * Update to give to PRL
 *
 * Revision 1.4  1996/07/12  15:52:12  mjames
 * Sorted out things like Alias and Jumpers
 * Work Correctly
 * Print COrrectly
 *
 * Revision 1.4  1996/07/12  15:52:12  mjames
 * Sorted out things like Alias and Jumpers
 * Work Correctly
 * Print COrrectly
 *
 * Revision 1.3  96/06/04  11:53:28  11:53:28  mjames (Mike James)
 * Corrected the operation of the renaming function
 *
 * Revision 1.2  96/05/29  11:00:10  11:00:10  mjames (Mike James)
 * Added explanatory comments
 *
 * Revision 1.1  96/05/29  10:53:13  10:53:13  mjames (Mike James)
 * Initial revision
 *  */

#include "rename.h"

#include "chck_names.h"
#include "cmdlog.h"
#include "cmdparse.h"
#include "database.h"
#include "expression.h"
#include "generic.h"
#include "lx_support.h"
#include "sorting.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/rename.c,v 1.2 2003/11/06 04:36:03 mjames Exp $"

/* added on to suffix all signal names */
/* all new objects will appear after the 'mark'. Only
   these new objects need to be renamed by adding a suffix.
   Older objects have already been renamed. */

static net_t *mark_nets = NULL;
static socket_t *mark_skts = NULL;

/* record the last known net and socket before
   reading in new nets and sockets */

void mark_board_objects (void)
{
        net_t *net = routed_list;
        socket_t *skt = socket_head;
        while (net && net->next)
        {
                net = net->next;
        }
        mark_nets = net;
        while (skt && skt->next)
        {
                skt = skt->next;
        }
        mark_skts = skt;
        /*
          printf("Mark at net=%p and skt=%p\n",mark_nets,mark_skts);
        */
}

/* only name nets that are not null names */
static char *alter_id (char *id, char *suffix)
{
        if (!ISNULLSTR (id) && !ISNULLSTR (suffix))
        {
                id = realloc (id, strlen (id) + strlen (suffix) + 1);
                strcat (id, suffix);
                return (id);
        }
        return NULL;
}

/* suffixes all net and component identifiers
   since the last 'mark_board_objects' call with the string s */

void set_board_suffix (char *s)
{
        net_t *net = mark_nets;
        socket_t *skt = mark_skts;

        /*
          printf("Mark at net=%p and skt=%p\n",mark_nets,mark_skts);
        */
        /* flag the nets and sockets as having been renamed */
        mark_nets = NULL;
        mark_skts = NULL;

        if (net)
                net = net->next; /* move to next one (new one) */
        else
                net = routed_list;
        if (skt)
                skt = skt->next; /* ditto */
        else
                skt = socket_head;

        /* rename all of the net identifiers */
        while (net)
        {
                struct net *sub_n = net->subnets;

                /* jumpered nets have their subnets renamed */
                if (sub_n && net->how_joined == Jumpered)
                        while (sub_n)
                        {
                                sub_n->identifier = alter_id (sub_n->identifier, s);
                                sub_n = sub_n->subnets;
                        }
                else
                        net->identifier = alter_id (net->identifier, s);
                net = net->next;
        }
        /* rename all of the socket identifiers */
        while (skt)
        {
                skt->identifier = alter_id (skt->identifier, s);
                if (skt->name) /* mod MDJ July 2001 */
                        skt->name = alter_id (skt->name, s);
                skt = skt->next;
        }
}

/*********************************************************************/
/* Pin_swapping : reverse A23 to 23a                                 */
/* allow up to lead_chars before digits to permit pin swap           */
/* lead_chars = 2  -> aa23 maps to 23aa but pin23 remains unswapped  */
/*********************************************************************/
/* modified from the original, now allows swapping 1a to a1 if
 * AlphaSwap_t == Want_A1
 * or allows swapping a1 to 1a if
 * AlphaSwap_t == Want_1A
 * probably better using the renaming command below.
 */
void pin_id_swap (char *template, int lead_chars, AlphaSwap_t lead_alpha)
{
        enum
        {
                First_Char,
                Leading_Chars,
                Trailing_Digits,
                Leading_Digits,
                Trailing_Chars,
                No_Swap
        } SwapState;
        int rc;
        socket_t *chip;
        node_t *nodes;
        /* compile regular expression */
        vert_regex_t *preg;

        if (ISNULLSTR (template))
        {
                template = ".*";
        }
        rc = vert_regcomp (&preg, template);
        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,
                    template);

                /*    return TCL_ERROR;
                 */
                return;
        }
        else
        {
                Log (LOG_GENERAL, "-- Using '%s' as match pattern\n", template);
        }

        if (lead_alpha == Want_A1)
        {
                Log (
                    LOG_GENERAL,
                    "-- Swapping pin identifiers with up to %d leading letters\n",
                    lead_chars);
        }
        else
        {
                Log (
                    LOG_GENERAL,
                    "-- Swapping pin identifiers with up to %d trailing letters\n",
                    lead_chars);
        }
        Log (
            LOG_GENERAL,
            "-- for sockets matching template '%s' --\n",
            template ? template : "[ALL Sockets]");

        chip = socket_head;
        while (chip)
        {
                int found;

                found = regexec (preg->preg, chip->identifier, 0, preg->regpatt, 0);

                if (!found)
                {
                        Log (LOG_GENERAL, "-- Processing socket '%s' --\n", chip->identifier);

                        nodes = chip->nodes;
                        while (nodes)
                        {
                                int lead_count = 0;
                                int done = 0;
                                char new_id[MAXIDLEN];
                                char *pos = nodes->identifier;
                                SwapState = First_Char;
                                while (pos && *pos && !done)
                                {
                                        /*
                                                  printf("%s (%c) State
                                           %d\n",nodes->identifier,*pos,SwapState);
                                        */
                                        switch (SwapState)
                                        {
                                        case First_Char:

                                                if (lead_alpha == Want_A1 && isdigit (*pos) &&
                                                    lead_chars > 0)
                                                {
                                                        SwapState = Leading_Digits;
                                                        lead_count = 1;
                                                        break;
                                                }
                                                if (lead_alpha == Want_1A && isalpha (*pos) &&
                                                    lead_chars > 0)
                                                {
                                                        SwapState = Leading_Chars;
                                                        lead_count = 1;
                                                        break;
                                                }
                                                /* no action needed, so continue */
                                                SwapState = No_Swap;
                                                done = 1;
                                                break;

                                        case Leading_Chars:

                                                if (isdigit (*pos))
                                                {
                                                        if (lead_count <= lead_chars)
                                                        { /* encountered a digit after a
                                                             character success so far */
                                                                SwapState = Trailing_Digits;
                                                                break;
                                                        }
                                                        else
                                                        {
                                                                SwapState = No_Swap;
                                                                done = 1;
                                                                break;
                                                        }
                                                }
                                                if (isalpha (*pos))
                                                {
                                                        lead_count++;
                                                        break;
                                                }
                                                SwapState = No_Swap;
                                                done = 1;
                                                break;

                                        case Leading_Digits:

                                                if (isalpha (*pos))
                                                {
                                                        if (lead_count <= lead_chars)
                                                        { /* encountered a character after a
                                                             number success so far */
                                                                SwapState = Trailing_Chars;
                                                                break;
                                                        }
                                                        else
                                                        {
                                                                SwapState = No_Swap;
                                                                done = 1;
                                                                break;
                                                        }
                                                }
                                                if (isdigit (*pos))
                                                { /* continue ok */
                                                        lead_count++;
                                                        break;
                                                }
                                                SwapState = No_Swap;
                                                done = 1;
                                                break;

                                        case Trailing_Digits:

                                                if (!isdigit (*pos))
                                                {
                                                        SwapState = No_Swap;
                                                        done = 1;
                                                }
                                                break;
                                        case Trailing_Chars:

                                                if (!isalpha (*pos))
                                                {
                                                        SwapState = No_Swap;
                                                        done = 1;
                                                }
                                                break;
                                        default:
                                                break;
                                        }
                                        pos++;
                                }
                                /* on arrival here in either state we can swap the two parts of
                                 * the ident */
                                if (SwapState == Trailing_Digits ||
                                    SwapState == Trailing_Chars)
                                {
                                        int i, l;
                                        strcpy (new_id, (nodes->identifier) + lead_count);
                                        strncat (new_id, nodes->identifier, lead_count);
                                        l = strlen (new_id);
                                        for (i = 0; i < l; i++)
                                                new_id[i] = tolower (new_id[i]);
                                        Log (
                                            LOG_GENERAL,
                                            "# Renaming %s(%s) to %s(%s)\n",
                                            chip->identifier,
                                            nodes->identifier,
                                            chip->identifier,
                                            new_id);
                                        strcpy (nodes->identifier, new_id);
                                }
                                nodes = nodes->sktnext;
                        }
                }
                chip = chip->next;
        }
        vert_regfree (&preg);
}

/***************************************************************************************/
/* Name nets after node name on device instead of pcb CAD name                         */
/* Initially lookup all matching sockets                                               */

void alter_net_to_socket_name (char *chip_id_template, char *prefix_opt)
{
        node_t *chip_node;
        int found, rc, count = 0;
        socket_t *socket;
        vert_regex_t *preg;

        socket = socket_head;

        /*  create_unrouted_list(); */
        /* compile regular expression */

        if (!chip_id_template)
        {
                chip_id_template = ".*";
        }

        rc = vert_regcomp (&preg, chip_id_template);
        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,
                    chip_id_template);

                /*    return TCL_ERROR;
                 */
                return;
        }
        else
        {
                Log (LOG_GENERAL, "-- Using '%s' as match pattern\n", chip_id_template);
        }
        while (socket)
        {
                found = regexec (preg->preg, socket->identifier, 0, preg->regpatt, 0);

                if (!found)
                {
                        /*
                              Log(LOG_GENERAL,"found %s\n",skt->identifier);
                        */
                        count++;
                        chip_node = socket->nodes;
                        while (chip_node)
                        {
                                char name_buff[MAXIDLEN];
                                int count;
                                net_t *net = chip_node->net;
                                if (net && IS_ROUTABLE (net->how_routed))
                                {
                                        if (prefix_opt) /* TH requests this change. Not a
                                                           problem */
                                        {
                                                count = sprintf (
                                                    name_buff,
                                                    "%s%s",
                                                    prefix_opt,
                                                    chip_node->identifier);
                                        }
                                        else
                                        {
                                                count = sprintf (
                                                    name_buff,
                                                    "%s_%s",
                                                    socket->identifier,
                                                    chip_node->identifier);
                                        }
                                        net->identifier = realloc (net->identifier, count + 1);
                                        strcpy (net->identifier, name_buff);
                                        /*          printf("-- id = %s\n",name_buff); */
                                }
                                chip_node = chip_node->sktnext;
                        }
                }
                socket = socket->next;
        }
        Log (LOG_GENERAL, "-- processed %d sockets\n", count);
        vert_regfree (&preg);
}

static char pin_map_chars[] = PIN_MAP_LEGAL_CHARS;

static int row_index, col_index; /* Made static so I can check them later .*/

/***************************************************************************************/
/* Name nets after node name on device instead of pcb CAD name                         */
/* Initially lookup all matching sockets                                               */
/* change device template pin identifiers */

void edit_socket_pin_name (
    char *chip_id_template, char *pin_patt, char *pin_repl, property_t search_space)
{
        node_t *chip_node;
        int found, rc, count = 0;
        int subexpressions;
        socket_t *socket;
        vert_regex_t *preg;
        vert_regex_t *ppin_reg;
        int loop;

        if (ISNULLSTR (pin_patt))
        {
                return;
        }

        socket = template_head;

        /*  create_unrouted_list(); */
        /* compile regular expression for chip type */

        if (!chip_id_template)
        {
                chip_id_template = ".*";
        }

        rc = vert_regcomp (&preg, chip_id_template);
        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,
                    chip_id_template);

                /*    return TCL_ERROR;
                 */
                return;
        }
        else
        {
                Log (
                    LOG_GENERAL,
                    "-- Using '%s' as match pattern for chip %s\n",
                    chip_id_template,
                    search_space == Type ? "type" : "ident");
        }

        /* now compile pin regexp match pattern */
        rc = vert_regcomp (&ppin_reg, pin_patt);
        if (rc != 0)
        {
                char errbuff[100];
                regerror (rc, ppin_reg->preg, errbuff, 100);
                Log (
                    LOG_ERROR,
                    "-- Problem (rc=%d) %s with '%s' as regular expression\n",
                    rc,
                    errbuff,
                    pin_patt);

                /*    return TCL_ERROR;
                 */
                return;
        }
        else
        {
                subexpressions = ppin_reg->preg->re_nsub + 1; /* count up subexpressions */
                Log (
                    LOG_GENERAL,
                    "-- Using '%s' as chip pin ID matching pattern (%d subexpressions)\n",
                    pin_patt,
                    subexpressions);
        }

        if (subexpressions > MAX_REGEXP_SUBEXPR)
        {
                Log (LOG_ERROR, "-- Too many (>%d) subexpressions\n", MAX_REGEXP_SUBEXPR);
                return;
        }
        /* decode the command type */

        switch (search_space)
        {
        case Ident:
                loop = 1;
                break;
        case Type:
                loop = 2;
                break;
        default:
                loop = 0;
                break;
        }

        /* loop 2,1, 0 or 1,0 dependent on whether search is type or ident based */
        while (loop)
        {
                switch (loop)
                {
                case 1:
                        socket = socket_head;
                        break;
                case 2:
                        socket = template_head;
                        break;
                default:
                        break;
                }
                loop--;
                while (socket)
                {
                        if (search_space == Type)
                        {
                                found =
                                    regexec (preg->preg, socket->type, 0, preg->regpatt, 0);
                        }
                        else
                        {
                                found = regexec (
                                    preg->preg, socket->identifier, 0, preg->regpatt, 0);
                        }
                        if (!found)
                        {
                                /*
                                      Log(LOG_GENERAL,"found %s\n",skt->identifier);
                                */

                                int rows, columns;
                                /*      int row_index,col_index;  Made static so I can check
                                 * them later .*/

                                generic_info_t info, *row_expr, *col_expr;

                                /* Setup the row and column variables for this device */
                                /* these are input names that can be used in an expression */
                                info.g_type = IS_ATTRIBUTE;
                                info.g_class = DEFINED;

                                /* info is copied, simply change the variable parts and call
                                   the compile and set functions */
                                info.name = "pin_row";
                                info.expr = compile_variable_reference (&row_index, "pin_row");
                                set_generic_value (&socket->generics, &info);

                                info.name = "pin_col";
                                info.expr = compile_variable_reference (&row_index, "pin_col");
                                set_generic_value (&socket->generics, &info);

                                /* this expression will be evaluated when &n is seen in the
                                    input file */
                                row_expr = get_generic_ref (&socket->generics, "row_expr");

                                /*
                                      if(row_expr && row_expr->expr)
                                        {
                                        printf("row = ");
                                        print_expression(stdout,row_expr->expr,NO_RECURSE);
                                        printf("\n");
                                        }
                                */

                                /* this expression will be evaluated when &a is seen in the
                                    input file */
                                col_expr = get_generic_ref (&socket->generics, "col_expr");
                                /*
                                      if(col_expr && col_expr->expr)
                                        {
                                        printf("col = ");
                                        print_expression(stdout,col_expr->expr,NO_RECURSE);
                                        printf("\n");
                                        }
                                */
                                count++;
                                sort_nodes (socket, EXTRACT_XY); /* sort pins , determine pin
                                                                    row and column*/

                                rows = socket->max_pin_row - socket->min_pin_row + 1;
                                columns = socket->max_pin_col - socket->min_pin_col + 1;

                                chip_node = socket->nodes;
                                while (chip_node)
                                {
                                        char *str;
                                        str = chip_node->identifier;
                                        /* allow one bracketed subexpression in pin names */
                                        found = regexec (
                                            ppin_reg->preg,
                                            str,
                                            subexpressions,
                                            ppin_reg->regpatt,
                                            0);
                                        if (!found)
                                        {
                                                char name_buff[MAXIDLEN];
                                                int count, fail;
                                                int editp, copyp;
                                                name_buff[0] = 0;
                                                /* get length of replacement string */
                                                editp = 0;
                                                count = 0;
                                                fail = 0;
                                                /*          printf("Processing
                                                 * '%s'\n",pin_repl); */
                                                while (pin_repl[editp] && !fail)
                                                {
                                                        /* escape anything */
                                                        if (pin_repl[editp] == '\\')
                                                        {
                                                                editp++;
                                                                name_buff[count++] =
                                                                    pin_repl[editp];
                                                                if (pin_repl[editp])
                                                                {
                                                                        editp++;
                                                                }
                                                        }
                                                        /* replace matched patterns */
                                                        else if (pin_repl[editp] == '&')
                                                        {
                                                                int index, len;
                                                                char c;
                                                                char temp[30];
                                                                int digits;
                                                                /* change values to those seen
                                                                 * on this pin */
                                                                col_index = chip_node->pin_col;
                                                                row_index = chip_node->pin_row;

                                                                editp++;
                                                                c = pin_repl[editp];
                                                                if (c)
                                                                {
                                                                        /*                 printf("c='%c'
                                                                         * row = %d col
                                                                         * =%d\n",c,chip_node->pin_row
                                                                         * ,chip_node->pin_col);
                                                                         */
                                                                        editp++;
                                                                        switch (c)
                                                                        {
                                                                        case 'c':
                                                                        case 'C':
                                                                                if (chip_node
                                                                                        ->net &&
                                                                                    chip_node
                                                                                        ->net
                                                                                        ->name)
                                                                                {
                                                                                        len = strlen (
                                                                                            chip_node
                                                                                                ->net
                                                                                                ->name);
                                                                                        strncpy (
                                                                                            name_buff +
                                                                                                count,
                                                                                            chip_node
                                                                                                ->net
                                                                                                ->name,
                                                                                            len);
                                                                                        count +=
                                                                                            len;
                                                                                }
                                                                                else
                                                                                {
                                                                                        fail =
                                                                                            1;
                                                                                }
                                                                                break;

                                                                                /* &d or &D is
                                                                                 * the device
                                                                                 * identifier
                                                                                 */
                                                                        case 'd':
                                                                        case 'D':
                                                                                len = strlen (
                                                                                    socket
                                                                                        ->identifier);
                                                                                strncpy (
                                                                                    name_buff +
                                                                                        count,
                                                                                    socket
                                                                                        ->identifier,
                                                                                    len);
                                                                                count += len;
                                                                                break;
                                                                                /* &p or &P is
                                                                                 * the pin
                                                                                 * identifier
                                                                                 */
                                                                        case 'p':
                                                                        case 'P':
                                                                                len = strlen (
                                                                                    chip_node
                                                                                        ->identifier);
                                                                                strncpy (
                                                                                    name_buff +
                                                                                        count,
                                                                                    chip_node
                                                                                        ->identifier,
                                                                                    len);
                                                                                count += len;
                                                                                break;
                                                                                /* &a is the
                                                                                 * alpha
                                                                                 * component of
                                                                                 * the
                                                                                 * identifier
                                                                                 */
                                                                        case 'a':
                                                                        case 'A':
                                                                                /* always
                                                                                 * synthesise
                                                                                 * pin column
                                                                                 * from the
                                                                                 * info left by
                                                                                 * sort_nodes
                                                                                 */
                                                                                if (col_expr &&
                                                                                    col_expr
                                                                                        ->expr)
                                                                                {
                                                                                        index = eval_expression (
                                                                                            col_expr
                                                                                                ->expr,
                                                                                            &socket
                                                                                                 ->generics);
                                                                                }
                                                                                else
                                                                                {
                                                                                        index =
                                                                                            chip_node
                                                                                                ->pin_col;
                                                                                }
                                                                                /*                    printf("Alpha
                                                                                 * %d :
                                                                                 * ",index); */
                                                                                digits = 0;
                                                                                /* always at
                                                                                 * least a
                                                                                 * single char
                                                                                 */
                                                                                if (index >
                                                                                    0) /* index
                                                                                          = 0
                                                                                          means
                                                                                          no
                                                                                          chars
                                                                                          at
                                                                                          all !
                                                                                        */
                                                                                {
                                                                                        do
                                                                                        {
                                                                                                if (c ==
                                                                                                    'a') /* lower case idents if lower case 'a' is used */
                                                                                                {
                                                                                                        temp[digits++] = tolower (
                                                                                                            pin_map_chars
                                                                                                                [index %
                                                                                                                     (PIN_MAP_LEGAL_CHAR_COUNT +
                                                                                                                      1) -
                                                                                                                 1]);
                                                                                                }
                                                                                                else
                                                                                                {
                                                                                                        temp[digits++] = pin_map_chars
                                                                                                            [index %
                                                                                                                 (PIN_MAP_LEGAL_CHAR_COUNT +
                                                                                                                  1) -
                                                                                                             1];
                                                                                                }

                                                                                                index /=
                                                                                                    (PIN_MAP_LEGAL_CHAR_COUNT +
                                                                                                     1);
                                                                                        } while (
                                                                                            index);
                                                                                        temp[digits] =
                                                                                            0;
                                                                                        /*                      printf("conversion
                                                                                         * '%s'\n",temp);
                                                                                         */
                                                                                        /* reverse
                                                                                         * copy
                                                                                         * string,
                                                                                         * at
                                                                                         * least
                                                                                         * one
                                                                                         * char
                                                                                         */
                                                                                        for (
                                                                                            ;
                                                                                            digits >
                                                                                            0;
                                                                                            name_buff
                                                                                                [count++] = temp
                                                                                                    [--digits])
                                                                                                ;
                                                                                }
                                                                                else
                                                                                {
                                                                                        /* error
                                                                                         * in
                                                                                         * the
                                                                                         * expansion
                                                                                         * as
                                                                                         * the
                                                                                         * index
                                                                                         * < 0
                                                                                         */
                                                                                        /* Leave
                                                                                           it
                                                                                           blank
                                                                                           as
                                                                                           there
                                                                                           is a
                                                                                           danger
                                                                                           elsewhere
                                                                                                              name_buff[count++] = '&';
                                                                                                              name_buff[count++] = c;
                                                                                        */
                                                                                }
                                                                                break;
                                                                                /* &n is the
                                                                                 * alpha
                                                                                 * component of
                                                                                 * the
                                                                                 * identifier
                                                                                 */
                                                                        case 'n':
                                                                        case 'N':
                                                                                if (row_expr &&
                                                                                    row_expr
                                                                                        ->expr)
                                                                                {
                                                                                        index = eval_expression (
                                                                                            row_expr
                                                                                                ->expr,
                                                                                            &socket
                                                                                                 ->generics);
                                                                                }
                                                                                else
                                                                                {
                                                                                        index =
                                                                                            chip_node
                                                                                                ->pin_row;
                                                                                }
                                                                                /*                    printf("Numeric
                                                                                 * %d\n",index);
                                                                                 */
                                                                                if (index >
                                                                                    0) /* index
                                                                                          = 0
                                                                                          means
                                                                                          no
                                                                                          chars
                                                                                          at
                                                                                          all !
                                                                                        */
                                                                                {
                                                                                        sprintf (
                                                                                            temp,
                                                                                            "%"
                                                                                            "d",
                                                                                            index);
                                                                                        len = strlen (
                                                                                            temp);
                                                                                        strncpy (
                                                                                            name_buff +
                                                                                                count,
                                                                                            temp,
                                                                                            len);
                                                                                        /*                    printf("result:
                                                                                         * '%s'
                                                                                         * %d\n",name_buff,strlen(name_buff));
                                                                                         */
                                                                                        count +=
                                                                                            len;
                                                                                }
                                                                                else
                                                                                {
                                                                                        /* error
                                                                                         * in
                                                                                         * the
                                                                                         * expansion
                                                                                         * as
                                                                                         * the
                                                                                         * index
                                                                                         * < 0
                                                                                         */
                                                                                        name_buff
                                                                                            [count++] =
                                                                                                '&';
                                                                                        name_buff
                                                                                            [count++] =
                                                                                                c;
                                                                                }

                                                                                break;
                                                                        case 'i':
                                                                        case 'I':
                                                                                sprintf (
                                                                                    temp,
                                                                                    "%d",
                                                                                    chip_node
                                                                                            ->pin_row -
                                                                                        socket
                                                                                            ->min_pin_row +
                                                                                        (chip_node
                                                                                             ->pin_col -
                                                                                         socket
                                                                                             ->min_pin_col) *
                                                                                            rows +
                                                                                        1);

                                                                                len = strlen (
                                                                                    temp);
                                                                                strncpy (
                                                                                    name_buff +
                                                                                        count,
                                                                                    temp,
                                                                                    len);
                                                                                count += len;
                                                                                break;
                                                                                /* &0 to &9 or
                                                                                   whatever is
                                                                                   the regular
                                                                                   expression
                                                                                   bracketed
                                                                                   section */
                                                                        default:
                                                                                index =
                                                                                    c - '0';
                                                                                if (index <
                                                                                        0 ||
                                                                                    index >
                                                                                        subexpressions)
                                                                                {
                                                                                        fail =
                                                                                            1;
                                                                                }
                                                                                else
                                                                                {
                                                                                        /* copy
                                                                                         * subexpression
                                                                                         * over
                                                                                         */
                                                                                        copyp =
                                                                                            ppin_reg
                                                                                                ->regpatt
                                                                                                    [index]
                                                                                                .rm_so;
                                                                                        if (copyp >=
                                                                                            0)
                                                                                        {
                                                                                                while (
                                                                                                    copyp <
                                                                                                    ppin_reg
                                                                                                        ->regpatt
                                                                                                            [index]
                                                                                                        .rm_eo)
                                                                                                {
                                                                                                        name_buff
                                                                                                            [count++] = str
                                                                                                                [copyp++];
                                                                                                }
                                                                                        }
                                                                                        else
                                                                                        {
                                                                                                name_buff
                                                                                                    [count++] =
                                                                                                        '@';
                                                                                        }
                                                                                }
                                                                        }
                                                                }
                                                        }

                                                        else
                                                        {
                                                                name_buff[count++] =
                                                                    pin_repl[editp++];
                                                        }
                                                }
                                                if (!fail)
                                                {
                                                        name_buff[count] = 0;
                                                        /*
                                                                    printf("replacing '%s' with
                                                           '%s'\n",chip_node->identifier,name_buff);
                                                        */
                                                        chip_node->identifier = realloc (
                                                            chip_node->identifier, count + 1);
                                                        strcpy (
                                                            chip_node->identifier, name_buff);
                                                }
                                        }
                                        chip_node = chip_node->sktnext;
                                }
                        }
                        sort_nodes (socket, NO_EXTRACT_XY);
                        socket = socket->next;
                }
        }
        Log (LOG_GENERAL, "-- processed %d sockets\n", count);
        vert_regfree (&preg);
        vert_regfree (&ppin_reg);
}

/***************************************************************************************/
/* allows for net renaming : currently in the routed list only  */
void edit_net_names (char *pin_patt, char *pin_repl, property_t search_space)
{
        net_t *curr_net;
        int found, rc = 0;
        int subexpressions;
        int net_count;
        vert_regex_t *ppin_reg;
        int loop;
        net_count = 0;

        if (ISNULLSTR (pin_patt))
        {
                return;
        }

        curr_net = routed_list;

        /* now compile pin regexp match pattern */
        rc = vert_regcomp (&ppin_reg, pin_patt);
        if (rc != 0)
        {
                char errbuff[100];
                regerror (rc, ppin_reg->preg, errbuff, 100);
                Log (
                    LOG_ERROR,
                    "-- Problem (rc=%d) %s with '%s' as regular expression\n",
                    rc,
                    errbuff,
                    pin_patt);

                /*    return TCL_ERROR;
                 */
                return;
        }
        else
        {
                subexpressions = ppin_reg->preg->re_nsub + 1; /* count up subexpressions */
                Log (
                    LOG_GENERAL,
                    "-- Using '%s' as net matching pattern (%d subexpressions)\n",
                    pin_patt,
                    subexpressions);
        }

        if (subexpressions > MAX_REGEXP_SUBEXPR)
        {
                Log (LOG_ERROR, "-- Too many (>%d) subexpressions\n", MAX_REGEXP_SUBEXPR);
                return;
        }
        /* decode the command type */
        /*
          switch (search_space)
            {
            case Ident: loop = 1; break;
            case Type : loop = 2; break;
            default :   loop = 0; break;
            }
        */

        loop = 3;
        /* loop 2,1, 0 or 1,0 dependent on whether search is type or ident based */
        while (loop)
        {
                char *str;
                printf ("In loop %d\n", loop);
                switch (loop)
                {
                case 1:
                        curr_net = routed_list;
                        break;
                case 2:
                        curr_net = unrouted_list;
                        break;
                case 3:
                        curr_net = named_list;
                        break;
                default:
                        curr_net = NULL;
                        break;
                }
                loop--;
                while (curr_net)
                {
                        found = 1;
                        str = "nothing";
                        if (search_space == Name && !ISNULLSTR (curr_net->name))
                        {
                                found = regexec (
                                    ppin_reg->preg, curr_net->name, 0, ppin_reg->regpatt, 0);
                                str = curr_net->name;
                        }

                        if (search_space == Ident && !ISNULLSTR (curr_net->identifier))
                        {
                                found = regexec (
                                    ppin_reg->preg,
                                    curr_net->identifier,
                                    0,
                                    ppin_reg->regpatt,
                                    0);
                                str = curr_net->identifier;
                        }
                        /*      printf("Checking '%s'\n",str);  */

                        /* found will not be set if neither Name or Ident is used */
                        if (!found)
                        {
                                char name_buff[MAXIDLEN];
                                int fail, count;
                                int editp, copyp;
                                name_buff[0] = 0;
                                /* get length of replacement string */
                                editp = 0;
                                fail = 0;
                                count = 0;
                                net_count++;
                                printf ("Processing '%s'\n", str);
                                while (pin_repl[editp] && !fail)
                                {
                                        /* escape anything */
                                        if (pin_repl[editp] == '\\')
                                        {
                                                editp++;
                                                name_buff[count++] = pin_repl[editp];
                                                if (pin_repl[editp])
                                                {
                                                        editp++;
                                                }
                                        }
                                        /* replace matched patterns */
                                        else if (pin_repl[editp] == '&')
                                        {
                                                int index, len;
                                                char c;
                                                editp++;
                                                c = pin_repl[editp];
                                                if (c)
                                                {
                                                        editp++;
                                                        switch (c)
                                                        {
                                                                /* replace with name part of
                                                                 * net */
                                                        case 'n':
                                                        case 'N':
                                                                if (!ISNULLSTR (
                                                                        curr_net->name))
                                                                {
                                                                        len = strlen (
                                                                            curr_net->name);
                                                                        strncpy (
                                                                            name_buff + count,
                                                                            curr_net->name,
                                                                            len);
                                                                        count += len;
                                                                }
                                                                else
                                                                {
                                                                        fail = 1;
                                                                }
                                                                break;

                                                        case 'i':
                                                        case 'I':
                                                                if (!ISNULLSTR (
                                                                        curr_net->identifier))
                                                                {
                                                                        len = strlen (
                                                                            curr_net
                                                                                ->identifier);
                                                                        strncpy (
                                                                            name_buff + count,
                                                                            curr_net
                                                                                ->identifier,
                                                                            len);
                                                                        count += len;
                                                                }
                                                                else
                                                                {
                                                                        fail = 1;
                                                                }
                                                                break;

                                                                /* &0 to &9 or whatever is the
                                                                   regular expression bracketed
                                                                   section */
                                                        default:
                                                                index = c - '0';
                                                                if (index < 0 ||
                                                                    index > subexpressions)
                                                                {
                                                                        fail = 1;
                                                                }
                                                                else
                                                                {
                                                                        /* copy subexpression
                                                                         * over */
                                                                        copyp = ppin_reg
                                                                                    ->regpatt
                                                                                        [index]
                                                                                    .rm_so;
                                                                        if (copyp >= 0)
                                                                        {
                                                                                while (
                                                                                    copyp <
                                                                                    ppin_reg
                                                                                        ->regpatt
                                                                                            [index]
                                                                                        .rm_eo)
                                                                                {
                                                                                        name_buff
                                                                                            [count++] = str
                                                                                                [copyp++];
                                                                                }
                                                                        }
                                                                        else
                                                                        {
                                                                                name_buff
                                                                                    [count++] =
                                                                                        '@';
                                                                        }
                                                                }
                                                        } /* cae */
                                                }
                                        }

                                        else
                                        {
                                                name_buff[count++] = pin_repl[editp++];
                                        }
                                }
                                if (!fail)
                                {
                                        name_buff[count] = 0;
                                        /*
                                                    printf("replacing '%s' with
                                           '%s'\n",chip_node->identifier,name_buff);
                                        */
                                        if (search_space == Ident)
                                        {
                                                curr_net->identifier =
                                                    realloc (curr_net->identifier, count + 1);

                                                printf (
                                                    "replacing '%s' with '%s'\n",
                                                    curr_net->identifier,
                                                    name_buff);
                                                strcpy (curr_net->identifier, name_buff);
                                        }
                                        if (search_space == Name)
                                        {
                                                curr_net->name =
                                                    realloc (curr_net->name, count + 1);
                                                printf (
                                                    "replacing '%s' with '%s'\n",
                                                    curr_net->name,
                                                    name_buff);
                                                strcpy (curr_net->name, name_buff);
                                        }
                                }
                        }
                        curr_net = curr_net->next;
                }
        }
        Log (LOG_GENERAL, "-- processed %d nets\n", net_count);
        vert_regfree (&ppin_reg);
}