
/*
 *  $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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <regex.h>



#include "vertcl_main.h"
#include "expression.h"
#include "generic.h"
#include "database.h"
#include "rename.h"
#include "cmdparse.h"
#include "cmdlog.h"
#include "lx_support.h"
#include "chck_names.h"
#include "sorting.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);
   }