Logo Search packages:      
Sourcecode: magic version File versions  Download package

irCommand.c

/*
 * irCommand.c --
 *
 * Command interface for interactive router.  This file processes command
 * lines beginning with the `iroute' command.  
 * 
 * (The "wizard" command, `*iroute', for testing, debugging, etc., 
 *  is processed in irTestCmd.c.)
 * 
 *     ********************************************************************* 
 *     * Copyright (C) 1987, 1990 Michael H. Arnold, Walter S. Scott, and  *
 *     * the Regents of the University of California.                      * 
 *     * Permission to use, copy, modify, and distribute this              * 
 *     * software and its documentation for any purpose and without        * 
 *     * fee is hereby granted, provided that the above copyright          * 
 *     * notice appear in all copies.  The University of California        * 
 *     * makes no representations about the suitability of this            * 
 *     * software for any purpose.  It is provided "as is" without         * 
 *     * express or implied warranty.  Export of this software outside     * 
 *     * of the United States of America may require an export license.    * 
 *     *********************************************************************
 *
 */

#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-7.5/irouter/irCommand.c,v 1.8 2007/03/24 22:58:42 tim Exp $";
#endif  /* not lint */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/geometry.h"
#include "utils/hash.h"
#include "tiles/tile.h"
#include "database/database.h"
#include "utils/signals.h"
#include "textio/textio.h"
#include "graphics/graphics.h"
#include "windows/windows.h"
#include "dbwind/dbwind.h"
#include "dbwind/dbwtech.h"
#include "textio/txcommands.h"
#include "utils/main.h"
#include "utils/utils.h"
#include "commands/commands.h"
#include "utils/styles.h"
#include "utils/malloc.h"
#include "utils/list.h"
#include "mzrouter/mzrouter.h"
#include "irouter/irouter.h"
#include "irouter/irInternal.h"

/* window command issued to */
static MagWindow *irWindow;

/* Subcommand table - declared here since its referenced before defined */
00060 typedef struct
{
    char    *sC_name;   /* name of iroute subcommand */
    void    (*sC_proc)();     /* Procedure implementing this subcommand */
    char    *sC_commentString;      /* describes subcommand */
    char    *sC_usage;        /* command syntax */

} SubCmdTableE;
extern SubCmdTableE irSubcommands[]; 


/*
 * ----------------------------------------------------------------------------
 *
 * irSetNoisyAutoInt
 *
 * Set integer parameter, interpeting the string "AUTOMATIC" (or prefix)
 * as -1.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    If valueS is a nonnull string, interpret and set parm
 *      accordingly.
 *
 *      If valueS is null, the parameter value is left unaltered.
 *
 *      If file is nonnull parameter value is written to file.
 *
 *      If file is null, parameter value is written to magic text window via
 *      TxPrintf
 *
 *    If file is (FILE *)1, parameter value is returned as a Tcl object
 *    
 * ----------------------------------------------------------------------------
 */

void
irSetNoisyAutoInt(parm, valueS, file)
    int *parm;
    char *valueS;
    FILE *file;
{
    int which;

    /* special value Table */
#define V_AUTOMATIC     -1
    static struct
    {
      char  *sv_name;   /* name */
      int    sv_type;
    } specialValues[] = {
      "automatic",      V_AUTOMATIC,
      0
    };
    
    /* If value non-null set parm */
    if(valueS!=NULL)
    {
      int i;

      /* check if special value */
      which = LookupStruct(
          valueS,
          (char **) specialValues, 
          sizeof specialValues[0]);

      if(which == -1)
      {
          TxError("Ambiguous value: '%s'\n",valueS);
          TxError("Value must be 'AUTOMATIC', or a nonnegative integer\n");
          return;
      }
      else if (which >= 0 )
      {
          /* special value */
          int type = specialValues[which].sv_type;

          if(type == V_AUTOMATIC)
          {
              *parm = -1;
          }
          else
          {
            /* should not ever get here */
            ASSERT(FALSE,"irSetNoisyAutoInt");
          }
      }
      else if(StrIsInt(valueS) && (i=atoi(valueS))>=0)
      {
          *parm = i;
      }
      else
      {
          TxError("Bad value: \"%s\"\n", valueS);
          TxError("Value must be 'AUTOMATIC', or a nonnegative integer\n");
          return;
      }
    }

    /* Print parm value */
    if(file)
    {
      if(*parm == -1)
      {
          fprintf(file,"AUTOMATIC");
      }
      else
      {
          fprintf(file, "%8d ",*parm);
      }
    }
    else
    {
      if(*parm == -1)
      {
          TxPrintf("AUTOMATIC");
      }
      else
      {
          TxPrintf("%8d ",*parm);
      }   
    }

    return;
}


/*
 * ----------------------------------------------------------------------------
 *
 * irLSet<parm> --
 *
 * Set and display Route Layer parameter <parm>.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Call low level routine of appropriate type to set/display parameter.
 *    Value of parm can be displayed either in Magic text window (file is
 *      NULL) or to a file.
 *    
 * ----------------------------------------------------------------------------
 */

#ifdef MAGIC_WRAPPER

/* irLSetActive --  */
Tcl_Obj *
irLSetActive(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewBooleanObj(rL->rl_routeType.rt_active);
    SetNoisyBool(&(rL->rl_routeType.rt_active), s, file);
    return NULL;
}

/* irLSetWidth -- */
Tcl_Obj *
irLSetWidth(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewIntObj(rL->rl_routeType.rt_width);
    SetNoisyInt(&(rL->rl_routeType.rt_width),s,file);
    return NULL;
}

/* irLSetLength -- */
Tcl_Obj *
irLSetLength(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewIntObj(rL->rl_routeType.rt_length);
    SetNoisyInt(&(rL->rl_routeType.rt_length),s,file);
    return NULL;
}

/* irLSetHCost -- */
Tcl_Obj *
irLSetHCost(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewIntObj(rL->rl_hCost);
    SetNoisyInt(&(rL->rl_hCost),s,file);
    return NULL;
}
      
/* irLSetVCost -- */
Tcl_Obj *
irLSetVCost(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewIntObj(rL->rl_vCost);
    SetNoisyInt(&(rL->rl_vCost),s,file);
    return NULL;
}

/* irLSetJogCost -- */
Tcl_Obj *
irLSetJogCost(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewIntObj(rL->rl_jogCost);
    SetNoisyInt(&(rL->rl_jogCost),s,file);
    return NULL;
}

/* irLSetHintCost  -- */
Tcl_Obj *
irLSetHintCost(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewIntObj(rL->rl_hintCost);
    SetNoisyInt(&(rL->rl_hintCost),s,file);
    return NULL;
}

/* irLSetOverCost  -- */
Tcl_Obj *
irLSetOverCost(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewIntObj(rL->rl_overCost);
    SetNoisyInt(&(rL->rl_overCost),s,file);
    return NULL;
}

#else

/* irLSetActive --  */
void
irLSetActive(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    SetNoisyBool(&(rL->rl_routeType.rt_active),s,file);
}

/* irLSetWidth -- */
void
irLSetWidth(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    SetNoisyInt(&(rL->rl_routeType.rt_width),s,file);
}

/* irLSetLength -- */
void
irLSetLength(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    SetNoisyInt(&(rL->rl_routeType.rt_length),s,file);
}

/* irLSetHCost -- */
void
irLSetHCost(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    SetNoisyInt(&(rL->rl_hCost),s,file);
}
      
/* irLSetVCost -- */
void
irLSetVCost(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    SetNoisyInt(&(rL->rl_vCost),s,file);
}

/* irLSetJogCost -- */
void
irLSetJogCost(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    SetNoisyInt(&(rL->rl_jogCost),s,file);
}

 
/* irLSetHintCost  -- */
void
irLSetHintCost(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    SetNoisyInt(&(rL->rl_hintCost),s,file);
}

/* irLSetOverCost  -- */
void
irLSetOverCost(rL,s,file)
    RouteLayer *rL;
    char *s;
    FILE *file;
{
    SetNoisyInt(&(rL->rl_overCost),s,file);
}

#endif


/*
 * ----------------------------------------------------------------------------
 *
 * irCSet<parm> --
 *
 * Set and display contact parameter <parm>.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Call low level routine of appropriate type to set/display parameter.
 *    Value of parm can be displayed either in Magic text window (file is
 *      NULL) or to a file.
 *    
 * ----------------------------------------------------------------------------
 */
      
#ifdef MAGIC_WRAPPER

/* irCSetActive -- */
Tcl_Obj *
irCSetActive(rC,s, file)
    RouteContact *rC;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewBooleanObj(rC->rc_routeType.rt_active);
    SetNoisyBool(&(rC->rc_routeType.rt_active),s,file);
    return NULL;
}

/* irCSetWidth --  */
Tcl_Obj *
irCSetWidth(rC,s,file)
    RouteContact *rC;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewIntObj(rC->rc_routeType.rt_width);
    SetNoisyInt(&(rC->rc_routeType.rt_width),s,file);
    return NULL;
}
      
/* irCSetLength--  */
Tcl_Obj *
irCSetLength(rC,s,file)
    RouteContact *rC;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewIntObj(rC->rc_routeType.rt_length);
    SetNoisyInt(&(rC->rc_routeType.rt_length),s,file);
    return NULL;
}

/* irCSetCost -- */
Tcl_Obj *
irCSetCost(rC,s,file)
    RouteContact *rC;
    char *s;
    FILE *file;
{
    if (file == (FILE *)1)
      return Tcl_NewIntObj(rC->rc_cost);
    SetNoisyInt(&(rC->rc_cost),s,file);
    return NULL;
}

#else

/* irCSetActive -- */
void
irCSetActive(rC,s, file)
    RouteContact *rC;
    char *s;
    FILE *file;
{
    SetNoisyBool(&(rC->rc_routeType.rt_active),s,file);
}

/* irCSetWidth --  */
void
irCSetWidth(rC,s,file)
    RouteContact *rC;
    char *s;
    FILE *file;
{
    SetNoisyInt(&(rC->rc_routeType.rt_width),s,file);
}
      
/* irCSetLength --  */
void
irCSetLength(rC,s,file)
    RouteContact *rC;
    char *s;
    FILE *file;
{
    SetNoisyInt(&(rC->rc_routeType.rt_length),s,file);
}
      
/* irCSetCost -- */
void
irCSetCost(rC,s,file)
    RouteContact *rC;
    char *s;
    FILE *file;
{
    SetNoisyInt(&(rC->rc_cost),s,file);
}


#endif


/*
 * ----------------------------------------------------------------------------
 *
 * irSrSet<parm> --
 *
 * Set and display search parameter <parm>.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Call low level routine of appropriate type to set/display parameter.
 *    Value of parm can be displayed either in Magic text window (file is
 *      NULL) or to a file.
 *    
 * ----------------------------------------------------------------------------
 */


/* irSrSetRate -- */
void
irSrSetRate(s,file)
    char *s;
    FILE *file;
{
    SetNoisyDI(&irMazeParms->mp_wRate,s,file);
}

/* irSrSetWidth -- */
void
irSrSetWidth(s,file)
    char *s;
    FILE *file;
{
    SetNoisyDI(&(irMazeParms->mp_wWidth),s,file);
}


/*
 * ----------------------------------------------------------------------------
 *
 * irWzdSet<parm> --
 *
 * Set and display wizard parameter <parm>.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Call low level routine of appropriate type to set/display parameter.
 *    Value of parm can be displayed either in Magic text window (file is
 *      NULL) or to a file.
 *    
 * ----------------------------------------------------------------------------
 */

/* irWzdSetBloomCost -- */
void
irWzdSetBloomCost(s,file)
    char *s;
    FILE *file;
{
    SetNoisyDI(&(irMazeParms->mp_bloomDeltaCost),s,file);
}

/* irWzdSetBloomLimit -- */
void
irWzdSetBloomLimit(s,file)
    char *s;
    FILE *file;
{
    SetNoisyDI(&(irMazeParms->mp_bloomLimit),s,file);
}

/* irWzdSetBoundsIncrement -- */
void
irWzdSetBoundsIncrement(s,file)
    char *s;
    FILE *file;
{
    irSetNoisyAutoInt(&(irMazeParms->mp_boundsIncrement),s,file);
}

/* irWzdSetEstimate -- */
void
irWzdSetEstimate(s,file)
    char *s;
    FILE *file;
{
    SetNoisyBool(&(irMazeParms->mp_estimate),s,file);
}

/* irWzdSetExpandEndpoints-- */
void
irWzdSetExpandEndpoints(s, file)
char *s;
FILE *file;
{
    SetNoisyBool(&(irMazeParms->mp_expandEndpoints),s,file);
}

/* irWzdSetPenalty -- */
void
irWzdSetPenalty(s, file)
    char *s;
    FILE *file;
{
    if(s)
    {
        /* arg given, set penalty to it */
      float value;
      if(sscanf(s,"%f",&value)==1)
      {
          irMazeParms->mp_penalty.rf_mantissa = 
                (int) (value * (1<<irMazeParms->mp_penalty.rf_nExponent));
      }
      else
      {
          TxError("Bad penalty value: %s\n",s);
      }
    }

    /* print the current penalty factor. */
    if(file)
    {
      fprintf(file,"%f",
                   (double)irMazeParms->mp_penalty.rf_mantissa /
                   (double)(1<<irMazeParms->mp_penalty.rf_nExponent));
    }
    else
    {
      TxPrintf("%f",
             (double)irMazeParms->mp_penalty.rf_mantissa /
             (double)(1<<irMazeParms->mp_penalty.rf_nExponent));
    }

    return;
}

/* irWzdSetPenetration-- */
void
irWzdSetPenetration(s, file)
char *s;
FILE *file;
{
    irSetNoisyAutoInt(&(irMazeParms->mp_maxWalkLength),s,file);
}

/* irWzdSetWindow -- */
void
irWzdSetWindow(s, file)
char *s;
FILE *file;
{
    int which;
    int i, type;

    /* special arg Table */
#define SP_COMMAND      -1
#define SP_DOT          -2
    static struct
    {
      char  *sp_name;   /* name */
      int    sp_type;
    } specialArgs[] = {
      "command",  SP_COMMAND,
      ".",        SP_DOT,
      0
    };

    if(s!=NULL)
    /* set parameter */
    {
      /* check if special arg */
      which = LookupStruct(
          s,
          (char **) specialArgs, 
          sizeof specialArgs[0]);

      if(which == -1)
      {
          TxError("Ambiguous argument: '%s'\n",s);
          TxError("Argument must 'COMMAND', '.', or a nonneg. integer\n");
          return;
      }
      else if (which >= 0 )
      {
          /* special argument */
          type = specialArgs[which].sp_type;
          if(type == SP_COMMAND)
          {
              irRouteWid = -1;
          }
          else
          {
            ASSERT(type==SP_DOT,"wzdSetWindow");
            if(irWindow==NULL)
            {
                TxError("Point to a layout window first!\n");
                return;
            }
            else
                irRouteWid = irWindow->w_wid;
          }
      }
      else if(StrIsInt(s) && (i=atoi(s))>=0)
      {
          irRouteWid = i;
      }
      else
      {
          TxError("Bad argument: \"%s\"\n", s);
          TxError("Argument must be 'COMMAND', '.', or a nonneg. integer\n");
          return;
      }
    }

    /* Print current value of parm */
    if(file)
    {
      if(irRouteWid == -1)
      {
          fprintf(file,"COMMAND");
      }
      else
      {
          fprintf(file,"%d",irRouteWid);
      }
    }
    else
    {
      if(irRouteWid == -1)
      {
          TxPrintf("COMMAND");
      }
      else
      {
          TxPrintf("%d",irRouteWid);
      }
    }
    
    return;
}


/*
 * ----------------------------------------------------------------------------
 *
 * irContactsCmd --
 *
 * Irouter subcommand to set and display parameters on contacts.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Modify contact parameters and display them.
 *    
 * ----------------------------------------------------------------------------
 */

/* Contact Parameter Table */
static struct
{
    char    *cP_name;   /* name of parameter */
#ifdef MAGIC_WRAPPER
    Tcl_Obj *(*cP_proc)();    /* Procedure processing this parameter */
#else
    void          (*cP_proc)();     /* Procedure processing this parameter */
#endif
} cParms[] = {
    "active",     irCSetActive,
    "width",      irCSetWidth,
    "length",     irCSetLength,
    "cost", irCSetCost,
    0
};

/* NEXTVALUE - returns pointer to next value arg (string). */
#define NEXTVALUE \
( \
  (argc <= 4) ? NULL : \
    (nV_i >= argc-1) ? cmd->tx_argv[nV_i=4] : cmd->tx_argv[++nV_i] \
)

void
irContactsCmd(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    TileType tileType;
    RouteContact *rC;

    int argc = cmd->tx_argc;
    int which, n;
    int nV_i;                 /* Used by NEXTVALUE, must be initialized */
    bool doList = FALSE;

#ifdef MAGIC_WRAPPER
    /* Check for "-list" option */
    if (!strncmp(cmd->tx_argv[argc - 1], "-list", 5))
    {
      doList = TRUE;
      argc--;
    }
#endif

    nV_i = argc - 1;
    
    /* Process by case */
    if(argc == 2 ||
      (argc == 3 && (strcmp(cmd->tx_argv[2],"*")==0)) ||
      (argc >= 4 && 
          (strcmp(cmd->tx_argv[2],"*")==0) &&
          (strcmp(cmd->tx_argv[3],"*")==0)))
    {
      /* PROCESS ALL PARMS FOR ALL CONTACT TYPES */

#ifdef MAGIC_WRAPPER
      if (doList)
      {
          Tcl_Obj *alllist, *rlist, *rname, *robj;
          alllist = Tcl_NewListObj(0, NULL);

          /* Process contact parms */
          for (rC = irRouteContacts; rC != NULL; rC = rC->rc_next)
          {
            rlist = Tcl_NewListObj(0, NULL);
            rname = Tcl_NewStringObj(
                  DBTypeLongNameTbl[rC->rc_routeType.rt_tileType], -1);
            Tcl_ListObjAppendElement(magicinterp, rlist, rname);
            for (n = 0; cParms[n].cP_name; n++)
            {
                robj = (*cParms[n].cP_proc)(rC, NEXTVALUE, (FILE *)1);
                Tcl_ListObjAppendElement(magicinterp, rlist, robj);
            }
            Tcl_ListObjAppendElement(magicinterp, alllist, rlist);
          }
          Tcl_SetObjResult(magicinterp, alllist);
      }
      else
#endif
      {
          /* Print Contact Heading */
          TxPrintf("%-12.12s ", "contact");
          for(n=0; cParms[n].cP_name; n++)
          {
            TxPrintf("%8.8s ",cParms[n].cP_name);
          }
          TxPrintf("\n");

          TxPrintf("%-12.12s ", irRepeatChar(strlen("contact"),'-'));
          for(n=0; cParms[n].cP_name; n++)
          {
            TxPrintf("%8.8s ",irRepeatChar(strlen(cParms[n].cP_name),'-'));
          }
          TxPrintf("\n");

          /* Process contact parms */
          for (rC=irRouteContacts; rC!= NULL; rC=rC->rc_next)
          {
            TxPrintf("%-12.12s ",
                  DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]);
            for(n=0; cParms[n].cP_name; n++)
            {
                (*cParms[n].cP_proc)(rC,NEXTVALUE,NULL);
            }
            TxPrintf("\n");
          }
      }
    }
    else if(argc==3 ||
      (argc >= 4 && (strcmp(cmd->tx_argv[3],"*")==0)))
    {
      /* PROCESS ALL PARMS ASSOCIATED WITH CONTACT */
      /* convert layer string to tileType */
      tileType = DBTechNameType(cmd->tx_argv[2]);
      if(tileType<0) 
      {
          TxError("Unrecognized layer (type): \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }

      if(rC=irFindRouteContact(tileType))
      {
          /* Print Contact Heading */
          TxPrintf("%-12.12s ", "contact");
          for(n=0; cParms[n].cP_name; n++)
          {
            TxPrintf("%8.8s ",cParms[n].cP_name);
          }
          TxPrintf("\n");

          TxPrintf("%-12.12s ", irRepeatChar(strlen("contact"),'-'));
          for(n=0; cParms[n].cP_name; n++)
          {
            TxPrintf("%8.8s ",irRepeatChar(strlen(cParms[n].cP_name),'-'));
          }
          TxPrintf("\n");

          /* Process contact parms */
          TxPrintf("%-12.12s ",
            DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]);
          for(n=0; cParms[n].cP_name; n++)
          {
            (*cParms[n].cP_proc)(rC,NEXTVALUE,NULL);
          }
          TxPrintf("\n");
      }
      else 
      {
          TxError("Unrecognized route-contact: \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }
    }
    else if(argc>=4 && strcmp(cmd->tx_argv[2],"*")==0)
    {
      /* PROCESS A COLUMN (THE VALUES OF A PARAMETER FOR ALL CONTACTS) */
     
      /* Lookup parameter name in contact parm table */
      which = LookupStruct(
          cmd->tx_argv[3], 
          (char **) cParms, 
          sizeof cParms[0]);

      /* Process table lookup */
      if (which == -1)
      {
          /* AMBIGUOUS PARAMETER */
          TxError("Ambiguous parameter: \"%s\"\n", 
            cmd->tx_argv[3]);
          return;
      }
      else if (which<0)
      {
          /* PARAMETER NOT FOUND */
          TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]);
          TxError("Valid contact parameters are:  ");
          for (n = 0; cParms[n].cP_name; n++)
            TxError(" %s", cParms[n].cP_name);
          TxError("\n");
          return;
      }

      else 
      {
          /* CONTACT PARAMETER FOUND */

          /* Print Heading */
          TxPrintf("%-12.12s ", "contact");
          TxPrintf("%8.8s ",cParms[which].cP_name);
          TxPrintf("\n");

          TxPrintf("%-12.12s ", irRepeatChar(strlen("contact"),'-'));
          TxPrintf("%8.8s ",
            irRepeatChar(strlen(cParms[which].cP_name),'-'));
          TxPrintf("\n");

          /* Process contact parm */
          for (rC=irRouteContacts; rC!= NULL; rC=rC->rc_next)
          {
            TxPrintf("%-12.12s ",
                DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]);
            (*cParms[which].cP_proc)(rC,NEXTVALUE,NULL);
            TxPrintf("\n");
          }
      }
    }
    else if(argc>=4)
    {
      /* PROCESS PARAMETER ASSOCIATED WITH CONTACT */
      /* convert layer string to tileType */
      tileType = DBTechNameType(cmd->tx_argv[2]);
      if(tileType<0) 
      {
          TxError("Unrecognized layer (type): \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }

      if(rC=irFindRouteContact(tileType))
      {
          /* Lookup contact parameter name in table */
          which = LookupStruct(
            cmd->tx_argv[3], 
            (char **) cParms, 
            sizeof cParms[0]);

          /* Process result of lookup */
          if (which >= 0)
          {
            /* parameter found - call proc that processes it 
             * NULL second arg means display only
             */
            (*cParms[which].cP_proc)(rC,NEXTVALUE,NULL);
            TxPrintf("\n");
          }
          else if (which == -1)
          {
            /* ambiguous parameter - complain */
            TxError("Ambiguous parameter: \"%s\"\n", 
                cmd->tx_argv[3]);
            return;
          }
          else
          {
            /* unrecognized parameter - complain */
            TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]);
            TxError("Valid contact parameters are:  ");
            for (n = 0; cParms[n].cP_name; n++)
                TxError(" %s", cParms[n].cP_name);
            TxError("\n");
            return;
          }
      }
      else 
      {
          TxError("Unrecognized route-contact: \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }

    }

    /* Give warning if number of parm values didn't come out even */
    if (nV_i != argc-1)
    {
      TxError("Warning:  Number of parameter values didn't match number of parameters.\n");
    }

    return;
}


/*
 * ----------------------------------------------------------------------------
 *
 * irHelpCmd --
 *
 * Irouter subcommand to describe available commands.  (Driven by command
 * table, defined above IRCommand()).
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Display requested help info.
 *    
 * ----------------------------------------------------------------------------
 */

    /*ARGSUSED*/
void
irHelpCmd(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    int n;
    int which;

    if(cmd->tx_argc == 2)
    {
      /* No arg, so print summary of commands */
      TxPrintf("\niroute - route from cursor to box\n\n");
      for(n=0; irSubcommands[n].sC_name!=NULL; n++)
      {
          TxPrintf("iroute %s - %s\n",
                irSubcommands[n].sC_name,
                irSubcommands[n].sC_commentString);
      }
      TxPrintf("\niroute help <subcmd>");
      TxPrintf(" - print usage info for subcommand.\n\n");
    }
    else
    {
      /* Lookup subcommand in table, and printed associated help info */
      which = LookupStruct(
          cmd->tx_argv[2], 
          (char **) irSubcommands, 
          sizeof irSubcommands[0]);

        /* Process result of lookup */
      if (which >= 0)
      {
          /* subcommand found - call print out its comment string and usage */
          TxPrintf("\niroute %s - %s\n",
                irSubcommands[which].sC_name,
                irSubcommands[which].sC_commentString);
          TxPrintf("\nusage:\niroute %s\n",
                irSubcommands[which].sC_usage);
      }
      else if (which == -1)
      {
          /* ambiguous subcommand - complain */
          TxError("Ambiguous iroute subcommand: \"%s\"\n", cmd->tx_argv[2]);
      }
      else
      {
          /* unrecognized subcommand - complain */
          TxError("Unrecognized iroute subcommand: \"%s\"\n", 
                cmd->tx_argv[2]);
          TxError("Valid iroute irSubcommands are:  ");
          for (n = 0; irSubcommands[n].sC_name; n++)
            TxError(" %s", irSubcommands[n].sC_name);
          TxError("\n");
      }
    }

    return;
}


/*
 * ----------------------------------------------------------------------------
 *
 * irLayersCmd --
 *
 * Irouter subcommand to set and display parameters on route layers.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Modify contact parameters and display them.
 *    
 * ----------------------------------------------------------------------------
 */

/* Layer Parameter Table */
static struct
{
    char    *lP_name;   /* name of parameter */
#ifdef MAGIC_WRAPPER
    Tcl_Obj *(*lP_proc)();    /* procedure processing this parameter */
#else
    void    (*lP_proc)();     /* procedure processing this parameter */
#endif
} lParms[] = {
    "active",     irLSetActive,
    "width",      irLSetWidth,
    "length",     irLSetLength,
    "hCost",      irLSetHCost,
    "vCost",      irLSetVCost,
    "jogCost",    irLSetJogCost,
    "hintCost", irLSetHintCost,
    "overCost", irLSetOverCost,
    0
};

/* NEXTVALUE - returns pointer to next value arg (string). */
#define NEXTVALUE \
( \
  (argc <= 4) ? NULL : \
    (nV_i >= argc-1) ? cmd->tx_argv[nV_i=4] : cmd->tx_argv[++nV_i] \
)

    /*ARGSUSED*/  
void
irLayersCmd(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    TileType tileType;
    RouteLayer *rL;
    bool doList = FALSE;

    int argc = cmd->tx_argc;
    int which, n;
    int nV_i;           /* Used by NEXTVALUE, must be initialized */

#ifdef MAGIC_WRAPPER
    /* Check for "-list" option */
    if (!strncmp(cmd->tx_argv[argc - 1], "-list", 5))
    {
      doList = TRUE;
      argc--;
    }
#endif

    nV_i = argc - 1;
    
    /* Process by case */
    if(argc == 2 ||
      (argc == 3 && (strcmp(cmd->tx_argv[2],"*")==0)) ||
      (argc >= 4 && 
          (strcmp(cmd->tx_argv[2],"*")==0) &&
          (strcmp(cmd->tx_argv[3],"*")==0)))
    {
      /* PROCESS ALL PARMS FOR ALL ROUTE LAYERS */

#ifdef MAGIC_WRAPPER
      if (doList)
      {
          Tcl_Obj *alllist, *rlist, *robj, *rname;
          alllist = Tcl_NewListObj(0, NULL);

          /* Process parms for each route layer */
          for (rL = irRouteLayers; rL != NULL; rL = rL->rl_next)
          {
            rlist = Tcl_NewListObj(0, NULL);
            rname = Tcl_NewStringObj(
                  DBTypeLongNameTbl[rL->rl_routeType.rt_tileType], -1);
            Tcl_ListObjAppendElement(magicinterp, rlist, rname);
            for (n = 0; lParms[n].lP_name; n++)
            {
                robj = (*lParms[n].lP_proc)(rL, NEXTVALUE, (FILE *)1);
                Tcl_ListObjAppendElement(magicinterp, rlist, robj);
            }
              Tcl_ListObjAppendElement(magicinterp, alllist, rlist);
          }
          Tcl_SetObjResult(magicinterp, alllist);
      }
      else
#endif
      {
          /* Print Route Layer Heading */
          TxPrintf("%-12.12s ", "layer");
          for(n=0; lParms[n].lP_name; n++)
          {
            TxPrintf("%8.8s ",lParms[n].lP_name);
          }
          TxPrintf("\n");

          TxPrintf("%-12.12s ", irRepeatChar(strlen("layer"),'-'));
          for(n=0; lParms[n].lP_name; n++)
          {
            TxPrintf("%8.8s ", irRepeatChar(strlen(lParms[n].lP_name),'-'));
          }
          TxPrintf("\n");

          /* Process parms for each route layer */
          for (rL=irRouteLayers; rL!= NULL; rL=rL->rl_next)
          {
            TxPrintf("%-12.12s ", 
                  DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]);
            for(n=0; lParms[n].lP_name; n++)
            {
                (*lParms[n].lP_proc)(rL,NEXTVALUE,NULL);
            }
            TxPrintf("\n");
          }
      }
    }
    else if(argc==3 ||
      (argc >= 4 && (strcmp(cmd->tx_argv[3],"*")==0)))
    {
      /* PROCESS ALL PARMS ASSOCIATED WITH ROUTE LAYER */
      /* convert layer string to tileType */
      tileType = DBTechNameType(cmd->tx_argv[2]);
      if(tileType<0) 
      {
          TxError("Unrecognized layer (type): \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }

      if (rL=irFindRouteLayer(tileType))
      {
          /* Print Route Layer Heading */
          TxPrintf("%-12.12s ", "layer");
          for(n=0; lParms[n].lP_name; n++)
          {
            TxPrintf("%8.8s ",lParms[n].lP_name);
          }
          TxPrintf("\n");

          TxPrintf("%-12.12s ", irRepeatChar(strlen("layer"),'-'));
          for(n=0; lParms[n].lP_name; n++)
          {
            TxPrintf("%8.8s ", irRepeatChar(strlen(lParms[n].lP_name),'-'));
          }
          TxPrintf("\n");

          /* Process parms for route layer */
          TxPrintf("%-12.12s ", 
            DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]);
          for(n=0; lParms[n].lP_name; n++)
          {
            (*lParms[n].lP_proc)(rL,NEXTVALUE,NULL);
          }
          TxPrintf("\n");
      }
      else 
      {
          TxError("Unrecognized route layer or contact: \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }
    }
    else if(argc>=4 && strcmp(cmd->tx_argv[2],"*")==0)
    {
      /* PROCESS A COLUMN (THE VALUES OF A PARAMETER FOR ALL LAYERS) */
     
      /* Lookup parameter name in layer parm table */
      which = LookupStruct(
          cmd->tx_argv[3], 
          (char **) lParms, 
          sizeof lParms[0]);

      /* Process table lookup */
      if (which == -1)
      {
          /* AMBIGUOUS PARAMETER */
          TxError("Ambiguous parameter: \"%s\"\n", 
            cmd->tx_argv[3]);
          return;
      }

      else if (which<0)
      {
          /* PARAMETER NOT FOUND */
          TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]);
          TxError("Valid layer parameters are:  ");
          for (n = 0; lParms[n].lP_name; n++)
            TxError(" %s", lParms[n].lP_name);
          TxError("\n");
          return;
      }

      else
      {
          /* LAYER PARAMETER FOUND */

          /* Print Heading */
          TxPrintf("%-12.12s ", "layer");
          TxPrintf("%8.8s ",lParms[which].lP_name);
          TxPrintf("\n");

          TxPrintf("%-12.12s ", irRepeatChar(strlen("layer"),'-'));
          TxPrintf("%8.8s ", 
            irRepeatChar(strlen(lParms[which].lP_name),'-'));
          TxPrintf("\n");

          /* Process parm for each route layer */
          for (rL=irRouteLayers; rL!= NULL; rL=rL->rl_next)
          {
            TxPrintf("%-12.12s ", 
                DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]);
            (*lParms[which].lP_proc)(rL,NEXTVALUE,NULL);
            TxPrintf("\n");
          }

      }
    }
    else if(argc>=4)
    {
      /* PROCESS PARAMETER ASSOCIATED WITH ROUTE LAYER */
      /* convert layer string to tileType */
      tileType = DBTechNameType(cmd->tx_argv[2]);
      if(tileType<0) 
      {
          TxError("Unrecognized layer (type): \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }

      if (rL=irFindRouteLayer(tileType))
      {
          /* Lookup route layer parameter name in table */
          which = LookupStruct(
            cmd->tx_argv[3], 
            (char **) lParms, 
            sizeof lParms[0]);

          /* Process result of lookup */
          if (which >= 0)
          {
            /* parameter found - call proc that processes it 
             * NULL second arg means display only
             */
            (*lParms[which].lP_proc)(rL,NEXTVALUE,NULL);
            TxPrintf("\n");
          }
          else if (which == -1)
          {
            /* ambiguous parameter - complain */
            TxError("Ambiguous parameter: \"%s\"\n", 
                cmd->tx_argv[3]);
            return;
          }
          else
          {
            /* unrecognized parameter - complain */
            TxError("Unrecognized parameter: %s\n", cmd->tx_argv[3]);
            TxError("Valid route layer parameters are:  ");
            for (n = 0; lParms[n].lP_name; n++)
                TxError(" %s", lParms[n].lP_name);
            TxError("\n");
            return;
          }
      }
      else 
      {
          TxError("Unrecognized layer: \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }
    }

    /* Give warning if number of parm values didn't come out even */
    if (nV_i != argc-1)
    {
      TxError("Warning:  Number of parameter values didn't match number of parameters.\n");
    }

    return;
}


/*
 * ----------------------------------------------------------------------------
 *
 * irRouteCmd --
 *
 * Irouter subcommand to actually do a route. 
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Compute a route and paint it into edit cell.
 *    
 * ----------------------------------------------------------------------------
 */

/* Route options Table */
static char* rOptions[] = {
    "-dbox",      /* 0 */
    "-dlabel",  /* 1 */
    "-dlayers", /* 2 */
    "-drect",   /* 3 */
    "-dselection",/* 4 */
    "-scursor",   /* 5 */
    "-slabel",    /* 6 */
    "-slayers", /* 7 */
    "-spoint",    /* 8 */
#ifdef MAGIC_WRAPPER
    "-timeout",   /* 9 */
#endif
    NULL
};

void
irRouteCmd(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    Point *startPtArg = NULL; /* pts to start point, if given on command */
    Rect  *destRectArg = NULL;      /* pts to dest rect, if given on command */
    char *startLabel = NULL;  /* pts to labelname, if given on command */
    char *destLabel = NULL;   /* pts to labelname, if given on command */
    List *startLayers = NULL;
    List *destLayers = NULL;
    int startType;            /* type of start specifier */
    int destType;       /* type of destination specifier */
    Point startPt;
    Rect destRect;
    int irResult = MZ_NO_ACTION;
    int i;              /* index of arg being processed */
    int argc = cmd->tx_argc;
    char **argv = cmd->tx_argv;

    TileTypeBitMask layerMask;
    RouteLayer *rL;

    /* set startType and destType to defaults */
    startType = ST_CURSOR;
    destType = DT_BOX;

    /* skip over cmd name args */
    i = 2;

    /* process options */
    while(i<argc)
    {
      int which = Lookup(argv[i],&(rOptions[0]));
      switch (which) 
      {
          case -2:
            /* not found */
            TxError("Bad option to 'iroute route':  '%s'\n",argv[i]);
            goto leaveClean;
          case -1:
            /* ambiguous */
            TxError("Ambiguous option to 'iroute route':  '%s'\n",argv[i]);
            goto leaveClean;
          case 0:
            /* dBox */
            destType = DT_BOX;
            break;
          case 1:
            /* dLabel */
            destType = DT_LABEL;
            if(++i>=argc)
            {
                TxError("Missing label.\n");
                goto leaveClean;
            }
            destLabel = argv[i];
            break;
          case 2:
            /* dLayers */
            if(++i>=argc)
            {
                TxError("Missing layer list.\n");
                goto leaveClean;
            }
            (void) CmdParseLayers(argv[i],&layerMask);
            for(rL=irRouteLayers; rL!=NULL; rL=rL->rl_next)
            {
                if(TTMaskHasType(&layerMask,rL->rl_routeType.rt_tileType) &&
                      rL->rl_routeType.rt_active)
                {
                  LIST_ADD(rL, destLayers);
                }
            }
            if(destLayers==NULL)
            {
                TxError("No active route layers in destination list!\n");
                goto leaveClean;
            }
            break;
          case 3:
            /* dRect */
            destType = DT_RECT;
            if(++i>=argc)
            {
                TxError("Incomplete coordinates.\n");
                goto leaveClean;
            }
            if(!StrIsNumeric(argv[i]))
            {
                TxError("Non coordinate: %s\n",argv[i]);
                goto leaveClean;
            }
            destRect.r_xbot = cmdParseCoord(w, argv[i], FALSE, TRUE);

            if(++i>=argc)
            {
                TxError("Incomplete coordinates.\n");
                goto leaveClean;
            }
            if(!StrIsNumeric(argv[i]))
            {
            TxError("Nonnumeric coordinate: %s\n",argv[i]);
            goto leaveClean;
            }
            destRect.r_ybot = cmdParseCoord(w, argv[i], FALSE, FALSE);

            if(++i>=argc)
            {
                TxError("Incomplete coordinates.\n");
                goto leaveClean;
            }
            if(!StrIsNumeric(argv[i]))
            {
                TxError("Nonnumeric coordinate: %s\n",argv[i]);
                goto leaveClean;
            }
            destRect.r_xtop = cmdParseCoord(w, argv[i], FALSE, TRUE);

            if(++i>=argc)
            {
                TxError("Incomplete coordinates.\n");
                goto leaveClean;
            }
            if(!StrIsNumeric(argv[i]))
            {
            TxError("Nonnumeric coordinate: %s\n",argv[i]);
            goto leaveClean;
            }
            destRect.r_ytop = cmdParseCoord(w, argv[i], FALSE, FALSE);

            destRectArg = &destRect;
            break;          
          case 4:
            /* dSelection */
            destType = DT_SELECTION;
            break;
          case 5:
            /* sCursor */
            startType = ST_CURSOR;
            break;
          case 6:
            /* sLabel */
            startType = ST_LABEL;
            if(++i>=argc)
            {
                TxError("Missing label.\n");
                goto leaveClean;
            }
            startLabel = argv[i];
            break;
          case 7:
            /* sLayers */
            if(++i>=argc)
            {
                TxError("Missing layer list.\n");
                goto leaveClean;
            }
            (void) CmdParseLayers(argv[i],&layerMask);
            for(rL=irRouteLayers; rL!=NULL; rL=rL->rl_next)
            {
                if(TTMaskHasType(&layerMask,
                             rL->rl_routeType.rt_tileType) &&
                      rL->rl_routeType.rt_active)
                {
                  LIST_ADD(rL, startLayers);
                }
            }
            if(startLayers==NULL)
            {
                TxError("No active route layers in start list!\n");
                goto leaveClean;
            }
              break;
          case 8:
            /* sPoint */
            startType = ST_POINT;
            if(++i>=argc)
            {
                TxError("Incomplete coordinates.\n");
                goto leaveClean;
            }
            if(!StrIsNumeric(argv[i]))
            {
                TxError("Nonnumeric coordinate: %s\n",argv[i]);
                goto leaveClean;
            }
            startPt.p_x = cmdParseCoord(w, argv[i], FALSE, TRUE);
            if(++i>=argc)
            {
                TxError("Incomplete coordinates.\n");
                goto leaveClean;
            }
            if(!StrIsNumeric(argv[i]))
            {
            TxError("Nonnumeric coordinate: %s\n",argv[i]);
            goto leaveClean;
            }
            startPt.p_y = cmdParseCoord(w, argv[i], FALSE, FALSE);

            startPtArg = &startPt;
            break;
#ifdef MAGIC_WRAPPER
          case 9:
            if(++i>=argc)
            {
                TxError("No timeout value given.\n");
                goto leaveClean;
            }
            if(!StrIsInt(argv[i]))
            {
                TxError("Noninteger timeout value: %s\n",argv[i]);
                goto leaveClean;
            }
            SigRemoveTimer();
            SigTimerInterrupts();
            SigSetTimer(atoi(argv[i]));
            break;
#endif
          default:
            /* shouldn't happen */
            ASSERT(FALSE,"irRouteCmd");
            break;
      }

      /* advance to next option */
      ++i;
    }

    /* We're done parsing the command, call irRoute to do the real work */
    irResult = irRoute(w, startType, startPtArg, startLabel, startLayers,
                  destType, destRectArg, destLabel, destLayers);

#ifdef MAGIC_WRAPPER
    SigTimerDisplay();

    /* Set Tcl Result to irResult */
    switch (irResult)
    {
      case MZ_SUCCESS:
          Tcl_SetResult(magicinterp, "Route success", 0);
          break;
      case MZ_CURRENT_BEST:
          Tcl_SetResult(magicinterp, "Route best before interrupt", 0);
          break;
      case MZ_FAILURE:
          Tcl_SetResult(magicinterp, "Route failure", 0);
          break;
      case MZ_UNROUTABLE:
          Tcl_SetResult(magicinterp, "Route unroutable", 0);
          break;
      case MZ_INTERRUPTED:
          Tcl_SetResult(magicinterp, "Route interrupted", 0);
          break;
      case MZ_ALREADY_ROUTED:
          Tcl_SetResult(magicinterp, "Route already routed", 0);
          break;
    }
#endif

leaveClean:
    ListDealloc(startLayers);
    ListDealloc(destLayers);
    return;
}


/*
 * ----------------------------------------------------------------------------
 *
 * irSearchCmd --
 *
 * Irouter subcommand to set and display search parameters.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Modify search parameters and display them.
 *    
 * ----------------------------------------------------------------------------
 */

/* Search Parameter Table */
static struct
{
    char    *srP_name;  /* name of parameter */
    void    (*srP_proc)();    /* Procedure processing this parameter */
} srParms[] = {
    "rate",       irSrSetRate,
    "width",            irSrSetWidth,
    0
};

void
irSearchCmd(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    
    /* Process by case */
    if(cmd->tx_argc == 2)
    /* print values of all parms */
    {
      int n;

      for(n=0; srParms[n].srP_name; n++)
      {
          TxPrintf("  %s=", srParms[n].srP_name); 
          (*srParms[n].srP_proc)(NULL,NULL);
      }
      TxPrintf("\n");
    }
    else if(cmd->tx_argc == 3 || cmd->tx_argc == 4)
    /* process single parameter */
    {
      int which;

      /* Lookup parameter name in contact parm table */
      which = LookupStruct(
          cmd->tx_argv[2], 
          (char **) srParms, 
          sizeof srParms[0]);

      /* Process table lookup */
      if (which == -1)
      /* parameter ambiguous */
      {
          TxError("Ambiguous parameter: \"%s\"\n", 
            cmd->tx_argv[2]);
          return;
      }
      else if (which<0)
      /* parameter not found */
      {
          int n;

          TxError("Unrecognized parameter: %s\n", cmd->tx_argv[2]);
          TxError("Valid search parameters are:  ");
          for (n = 0; srParms[n].srP_name; n++)
            TxError(" %s", srParms[n].srP_name);
          TxError("\n");
          return;
      }
      else 
      /* parameter found - process it */
      {
          char *arg;

          if(cmd->tx_argc == 3)
          /* just want current value - use null argument */
          {
            arg = NULL;
          }
          else
          /* setting parameter, arg = value string */
          {
            arg = cmd->tx_argv[3];
          }

          TxPrintf("  %s=", srParms[which].srP_name); 
          (*srParms[which].srP_proc)(arg,NULL);
          TxPrintf("\n");
      }

    }
    else
    /* Too many arguments */
    {
      TxError("Too many args on 'iroute search'\n");
    }

    return;
}


/*
 * ----------------------------------------------------------------------------
 *
 * irSpacingsCmd --
 *
 * Irouter subcommand to set and display minimum spacings between 
 * routetypes. 
 * 
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Modify and display spacing parameters. 
 *    
 * ----------------------------------------------------------------------------
 */

void
irSpacingsCmd(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    TileType tileType;
    RouteType *rT;
    char *s;
    int which, value, argI, i, n;

    /* Special Value Table */
    static struct
    {
      char  *sV_name;   /* name of value */
      int     sV_value; /* corresponding interger value */
    } sValue[] = {
      "n",        -1,
      "nil",            -1,
      "none",           -1,
      "null",           -1,
      0
    };

    /* Subcell Table */
    static struct
    {
      char  *sT_name;   /* name of value */
      int     sT_value; /* corresponding interger value */
    } subcellTable[] = {
      "subcell",        TT_SUBCELL,
      0
    };

    /* Process by case */
    if(cmd->tx_argc == 2)
    {
      /* NO ARGS TO SPACING REQUEST - DISPLAY ALL SPACINGS */

      /* Print spacings for each route type */
      for (rT=irRouteTypes; rT!= NULL; rT=rT->rt_next)
      {
          TxPrintf("%s:  ", 
              DBTypeLongNameTbl[rT->rt_tileType]);
          for (i=0;i<TT_MAXTYPES;i++)
            if(rT->rt_spacing[i]>=0)
                TxPrintf("%s=%d ",DBTypeLongNameTbl[i],rT->rt_spacing[i]);
          if(rT->rt_spacing[TT_SUBCELL]>=0)
            TxPrintf("%s=%d ","SUBCELL",rT->rt_spacing[TT_SUBCELL]);
          TxPrintf("\n\n");
      }
    }
    else if(cmd->tx_argc==3)
    {
      /* ONE ARG TO SPACING REQUEST */

      if (strcmp(cmd->tx_argv[2],"CLEAR")==0)
      {
          /* CLEAR ALL SPACINGS */
          for (rT=irRouteTypes; rT!= NULL; rT=rT->rt_next)
            /* <=TT_MAXTYPES below includes TT_SUBCELL */
            for (i=0;i<=TT_MAXTYPES;i++)
                rT->rt_spacing[i]= -1;
      }
      else
      {
          /* PRINT SPACINGS FOR GIVEN ROUTE LAYER */

          /* convert layer string to tileType */
          tileType = DBTechNameType(cmd->tx_argv[2]);
          if(tileType<0) 
          {
            TxError("Unrecognized layer (type): \"%.20s\"\n", 
                cmd->tx_argv[2]);
            return;
          }

          if (rT=irFindRouteType(tileType))
          {

            TxPrintf("%s:  ", 
                DBTypeLongNameTbl[rT->rt_tileType]);
            for (i=0;i<TT_MAXTYPES;i++)
                if(rT->rt_spacing[i]>=0)
                  TxPrintf("%s=%d ",
                        DBTypeLongNameTbl[i],rT->rt_spacing[i]);
            if(rT->rt_spacing[TT_SUBCELL]>=0)
                TxPrintf("%s=%d ","SUBCELL",rT->rt_spacing[TT_SUBCELL]);
            TxPrintf("\n\n");
          }
          else 
          {
            TxError("Unrecognized route layer or contact: \"%.20s\"\n", 
                cmd->tx_argv[2]);
            return;
          }
      }
    }
    else if(cmd->tx_argc==4)
    {
      /* PRINT VALUE OF GIVEN SPACING */
     
      /* convert layer string to tileType */
      tileType = DBTechNameType(cmd->tx_argv[2]);
      if(tileType<0) 
      {
          TxError("Unrecognized layer (type): \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }

      if ((rT=irFindRouteType(tileType))==NULL)
      {
          TxError("Unrecognized route layer or contact: \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }

      /* convert type-string spacing is "to" to tiletype */
      tileType = DBTechNameType(cmd->tx_argv[3]);
      if(tileType<0) 
      {
          /* if not a real type, check to see if "SUBCELL" */
          which = LookupStruct(
            cmd->tx_argv[3],
            (char **) subcellTable,
            sizeof subcellTable[0]);
          if ( which>= 0)
              tileType = TT_SUBCELL;
      }
      if(tileType<0) 
      {
          TxError("Unrecognized layer (type): \"%.20s\"\n", 
            cmd->tx_argv[3]);
          return;
      }

      /* Print current value of spacing */
      if(rT->rt_spacing[tileType] >= 0)
          TxPrintf("\t%d\n",rT->rt_spacing[tileType]);
      else
          TxPrintf("\tNIL\n");
    }
    else if(EVEN(cmd->tx_argc))
    {
      /* TYPE PARMS DON'T PAIR EVENLY WITH VALUE PARMS */
      TxError("Type and value args don't pair evenly.\n");
      TxError("Usage:  *iroute spacing [routeType] [type1] [value1] [type2 value2] ... [typen valuen]\n");
    }
    else
    {
      /* SET SPACINGS */
     
      /* convert layer string to tileType */
      tileType = DBTechNameType(cmd->tx_argv[2]);
      if(tileType<0) 
      {
          TxError("Unrecognized layer (type): \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }

      if ((rT=irFindRouteType(tileType))==NULL)
      {
          TxError("Unrecognized route layer or contact: \"%.20s\"\n", 
            cmd->tx_argv[2]);
          return;
      }

      /* Prepend tab to echo of new values */
      TxPrintf("\t");

        /* process type/value pairs */
      for (argI=3; argI<cmd->tx_argc; argI +=2)
      {
          /* convert type-string spacing is "to" to tiletype */
          tileType = DBTechNameType(cmd->tx_argv[argI]);
          if(tileType<0) 
          {
            /* if not a real type, check to see if "SUBCELL" */
            which = LookupStruct(
                cmd->tx_argv[argI],
                (char **) subcellTable,
                sizeof subcellTable[0]);
            if ( which>= 0)
              tileType = TT_SUBCELL;
          }
          if(tileType<0) 
          {
            TxError("\nUnrecognized layer (type): \"%.20s\"\n", 
                cmd->tx_argv[argI]);
            continue;
          }

          /* convert value-string to integer */
          s = cmd->tx_argv[argI+1];
          if (StrIsNumeric(s))
          {
            value = cmdParseCoord(w, s, TRUE, FALSE);
            if (value < -1)
            {
                TxError("\nBad spacing value: %d\n",value);
                TxError("Valid spacing values are:  ");
                TxError("<a nonnegative integer> -1");
                for (n = 0; sValue[n].sV_name; n++)
                  TxError(" %s", sValue[n].sV_name);
            TxError("\n");
            return;
            }
          }
          else
          {
            /* Lookup in special value table */
            which = LookupStruct(
                s, 
                (char **) sValue, 
                sizeof sValue[0]);

            /* Process result of lookup */
            if (which >= 0)
            {
                /* special value found, set string accordingly */
                value = sValue[which].sV_value;
            }
            else if (which == -1)
            {
                /* ambiguous value - complain */
                TxError("\nAmbiguous value: \"%s\"\n",s);
                continue;
            }
            else
            {
                /* unrecognized value - complain */
                TxError("Bad spacing value: %s\n",s);
                TxError("Valid spacing values are:  ");
                TxError("<a nonnegative integer> -1");
                for (n = 0; sValue[n].sV_name; n++)
                  TxError(" %s", sValue[n].sV_name);
                TxError("\n");
                continue;
            }
          }

          /* Set value in route type */
          rT->rt_spacing[tileType]=value;

          /* Print new value */
          if(rT->rt_spacing[tileType] != -1)
            TxPrintf(" %s=%d",
                (tileType == TT_SUBCELL ? 
                  "SUBCELL" : DBTypeLongNameTbl[tileType]),
                  rT->rt_spacing[tileType]);
          else
            TxPrintf(" %s=NIL",
                (tileType==TT_SUBCELL ? 
                  "SUBCELL" : DBTypeLongNameTbl[tileType]));
      }
      TxPrintf("\n");
    }

    return;
}


/*
 * ----------------------------------------------------------------------------
 *
 * irVerbosityCmd --
 *
 * Irouter subcommand to set amount of messages given by irouter and mzrouter.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Sets verbosity parameter
 *    
 * ----------------------------------------------------------------------------
 */

void
irVerbosityCmd(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    if(cmd->tx_argc >3)
    {
      TxError("'iroute verbosity' only takes one arg!\n");
      return;
    }
    
    if(cmd->tx_argc == 3)
    {
      int i;

      /* ONE ARG */
      if(StrIsInt(cmd->tx_argv[2]) && (i=atoi(cmd->tx_argv[2]))>=0)
      {
          irMazeParms->mp_verbosity = i;
      }
      else
      {
          TxError("Bad argument: \"%s\"\n", cmd->tx_argv[2]);
          TxError("Argument must be a nonnegative integer\n");
          return;
      }
    }

    /* Print current value of verbosity */
    switch (irMazeParms->mp_verbosity)
    {
      case 0:
      /* shhhhh! we're in silent mode */
      break;
          
      case 1:
      TxPrintf("\t1 (Brief messages)\n");
      break;
          
      default:
      ASSERT(irMazeParms->mp_verbosity>=2,"irVerbosityCmd");
      TxPrintf("\t%d (Lots of statistics)\n",
             irMazeParms->mp_verbosity);
    }
    
    return;
}


/*
 * ----------------------------------------------------------------------------
 *
 * irVersionCmd --
 *
 * Irouter subcommand to display irouter version string.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Displays version string.
 *    
 * ----------------------------------------------------------------------------
 */

void
irVersionCmd(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{

    if(cmd->tx_argc == 2)
    {
      /* Print out version string */
        TxPrintf("\tIrouter version %s\n", IROUTER_VERSION);
    }
    else
    {
      TxError("Too many args on 'iroute version'\n");
    }

    return;
}


/*
 * ----------------------------------------------------------------------------
 *
 * irWizardCmd --
 *
 * Irouter subcommand to set and display less frequently modified  parameters.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    See above.
 *    
 * ----------------------------------------------------------------------------
 */

/* Wizard Parameter Table */
static struct
{
    char    *wzdP_name; /* name of parameter */
    void    (*wzdP_proc)();   /* Procedure processing this parameter */
} wzdParms[] = {
    "bloom",            irWzdSetBloomCost,
    "bloomLimit", irWzdSetBloomLimit,
    "boundsIncrement",  irWzdSetBoundsIncrement,
    "estimate",         irWzdSetEstimate,
    "expandEndpoints",  irWzdSetExpandEndpoints,
    "penalty",          irWzdSetPenalty,
    "penetration",      irWzdSetPenetration,
    "window",           irWzdSetWindow,
    0
};

void
irWizardCmd(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    
    /* Process by case */
    if(cmd->tx_argc == 2)
    /* print values of all parms */
    {
      int n;

      for(n=0; wzdParms[n].wzdP_name; n++)
      {
          TxPrintf("  %s=", wzdParms[n].wzdP_name); 
          (*wzdParms[n].wzdP_proc)(NULL,NULL);
          TxPrintf("\n");
      }
    }
    else if(cmd->tx_argc == 3 || cmd->tx_argc == 4)
    /* process single parameter */
    {
      int which;

      /* Lookup parameter name in contact parm table */
      which = LookupStruct(
          cmd->tx_argv[2], 
          (char **) wzdParms, 
          sizeof wzdParms[0]);

      /* Process table lookup */
      if (which == -1)
      /* parameter ambiguous */
      {
          TxError("Ambiguous parameter: \"%s\"\n", 
            cmd->tx_argv[2]);
          return;
      }
      else if (which<0)
      /* parameter not found */
      {
          int n;

          TxError("Unrecognized parameter: %s\n", cmd->tx_argv[2]);
          TxError("Valid wizard parameters are:  ");
          for (n = 0; wzdParms[n].wzdP_name; n++)
            TxError(" %s", wzdParms[n].wzdP_name);
          TxError("\n");
          return;
      }
      else 
      /* parameter found - process it */
      {
          char *arg;

          if(cmd->tx_argc == 3)
          /* just want current value - use null argument */
          {
            arg = NULL;
          }
          else
          /* setting parameter, arg = value string */
          {
            arg = cmd->tx_argv[3];
          }

          TxPrintf("  %s=", wzdParms[which].wzdP_name); 
          (*wzdParms[which].wzdP_proc)(arg,NULL);
          TxPrintf("\n");
      }

    }
    else
    /* Too many arguments */
    {
      TxError("Too many args on 'iroute wizard'\n");
    }

    return;
}

/*
 * ----------------------------------------------------------------------------
 *
 * irSaveParametersCmd --
 *
 * Irouter subcommand to create "source" file setting all irouter parameters
 * (except ref. window) to current value - to reset to these values just
 * source the file with `:source'.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Write file of Magic commands to set parms. to current values.
 *    
 * NOTE:
 *      Note defined after all other commands, so it can make use of 
 *      datastructures defined just in front of other commands, 
 *      such as the search parameter table.
 * ----------------------------------------------------------------------------
 */

void
irSaveParametersCmd(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    FILE *saveFile;
    RouteContact *rC;
    RouteLayer *rL;

    /* make sure exactly one arg given */
    if(cmd->tx_argc !=3)
    {
      if(cmd->tx_argc == 2)
          TxError("Must specify save file!\n");
      else
          TxError("Too many args on ':iroute saveParameter'\n");
      return;
    }

    /* open save file */
    saveFile = fopen(cmd->tx_argv[2], "w");
    if (saveFile == NULL) 
    {
      TxError("Could not open file '%s' for writing.\n", cmd->tx_argv[2]);
      return;
    }

    /* write header comment */
    fprintf(saveFile,"# Irouter version %s\n", IROUTER_VERSION);
    fprintf(saveFile,"#\n");
    fprintf(saveFile,
          "# This is a Magic command file generated by the Magic command\n");
    fprintf(saveFile,"#\t:iroute saveParameters\n");
    fprintf(saveFile,"# To restore these parameter settings,");
    fprintf(saveFile," use the Magic `:source' command.\n\n");

    /* turn verbosity down to errors and warnings, to avoid lots of
     * gibberish when the file is sourced.
     */
    fprintf(saveFile,":iroute verbosity 0\n");
          
    /* save CONTACT parameters */
    for (rC=irRouteContacts; rC!= NULL; rC=rC->rc_next)
    {
      int n;

      fprintf(saveFile,":iroute contact %s * ",
                   DBTypeLongNameTbl[rC->rc_routeType.rt_tileType]);
      for(n=0; cParms[n].cP_name; n++)
      {
          (*cParms[n].cP_proc)(rC,NULL,saveFile);
      }
      fprintf(saveFile,"\n");
    }

    /* save LAYER paramters */
    for (rL=irRouteLayers; rL!= NULL; rL=rL->rl_next)
    {
      int n;

      fprintf(saveFile,":iroute layer %s * ", 
          DBTypeLongNameTbl[rL->rl_routeType.rt_tileType]);
      for(n=0; lParms[n].lP_name; n++)
      {
          (*lParms[n].lP_proc)(rL,NULL,saveFile);
      }
      fprintf(saveFile,"\n");
    }

    /* save SEARCH parameters */
    {
      int n;

      for(n=0; srParms[n].srP_name; n++)
      {
          fprintf(saveFile,":iroute search %s ", 
                     srParms[n].srP_name); 
          (*srParms[n].srP_proc)(NULL,saveFile);
          fprintf(saveFile,"\n");
      }
    }

    /* save SPACINGS */
    {
      RouteType *rT;
      int i;

      fprintf(saveFile,":iroute spacings CLEAR\n");
      for (rT=irRouteTypes; rT!= NULL; rT=rT->rt_next)
      {
          for (i=0;i<TT_MAXTYPES;i++)
            if(rT->rt_spacing[i]>=0)
                fprintf(saveFile,":iroute spacings %s %s %d\n", 
                           DBTypeLongNameTbl[rT->rt_tileType],
                           DBTypeLongNameTbl[i],
                           rT->rt_spacing[i]);
          if(rT->rt_spacing[TT_SUBCELL]>=0)
            fprintf(saveFile,":iroute spacings %s %s %d\n", 
                         DBTypeLongNameTbl[rT->rt_tileType],
                         "SUBCELL",
                         rT->rt_spacing[TT_SUBCELL]);
      }
    }

    /* save WIZARD parameters */
    {
      int n;

      for(n=0; wzdParms[n].wzdP_name; n++)
      {
          fprintf(saveFile,":iroute wizard %s ", 
                     wzdParms[n].wzdP_name); 
          (*wzdParms[n].wzdP_proc)(NULL,saveFile);
          fprintf(saveFile,"\n");
      }
    }

    /* save VERBOSITY parameter (done last so :source is silent) */
    fprintf(saveFile,":iroute verbosity %d\n",
          irMazeParms->mp_verbosity);
    
    (void) fclose(saveFile);
    return;
}


/*
 * ----------------------------------------------------------------------------
 *
 * IRCommand --
 *
 * Command interface for interactive router.  Processes `:iroute' command
 * lines.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Depends on the command; see below.
 *
 * Organization:
 *    We select a procedure based on the first keyword (argv[0])
 *    and call it to do the work of implementing the subcommand.  Each
 *    such procedure is of the following form:
 *
 *    int   
 *    proc(argc, argv)
 *        int argc;
 *        char *argv[];
 *    {
 *    }
 *
 * ----------------------------------------------------------------------------
 */

/*--- Subcommand Table ---*/

SubCmdTableE irSubcommands[] = {
    "contacts",   irContactsCmd,
    "set route-contact parameters",
    "contacts [type] [parameter] [value1] ... [valuen]\n\
\t(can use '*' for type or parameter)",

    "help",       irHelpCmd,
    "summarize iroute subcommands",
    "help [subcommand]",

    "layers",     irLayersCmd,
    "set route-layer parameters",
    "layers [type] [parameter] [value1] ... [valuen]\n\
\t(can use '*' for type or parameter)",

    "route",      irRouteCmd,
    "connect point to node(s)",
    "route [options]\n\
\t-sLayers layers = layers route may start on.\n\
\t-sCursor = start route at cursor (DEFAULT)\n\
\t-sLabel name = start route at label of given name\n\
\t-sPoint x y = start route at given coordinates\n\
\t-dLayers layers = layers route may end on.\n\
\t-dBox = route to box (DEFAULT)\n\
\t-dLabel name = route to label of given name\n\
\t-dRect xbot ybot xtop ytop =  route to rectangle of given coordinates\n\
\t-dSelection = route to selection",

    "saveParameters",   irSaveParametersCmd,
    "write out all irouter parameters\n\
\t(can be read back with :source)",
    "saveParameters <filename>",

    "search", irSearchCmd,
    "set parameters controlling the internal search for routes",
    "search [searchParameter] [value]",

    "spacings",   irSpacingsCmd,
    "set minimum spacing between route-type and arbitrary type",
    "spacings [route-type] [type] [spacing] ... [typen spacingn]\n\
\t(types can be 'SUBCELL', spacing can be 'nil')\n\
iroute spacings CLEAR\n\
\t(sets all spacings to nil)",

    "verbosity", irVerbosityCmd,
    "control the amount of messages printed",
    "verbosity [level]\n\
\t(0 = errors and warnings only, 1 = brief, 2 = lots of statistics)",

    "version",    irVersionCmd,
    "identify irouter version",
    "version",

    "wizard", irWizardCmd,
    "set miscellaneous parameters",
    "wizard [wizardParameter] [value]",

    0
}, *subCmdP;

void
IRCommand(w, cmd)
    MagWindow *w;
    TxCommand *cmd;
{
    int n;
    int which;

    /* make sure we have maze parameters */
    if(irMazeParms==NULL)
    {
      TxError("Need irouter style in mzrouter section of technology file");
      TxError(" to use irouter.\n");
      return;
    }

    /* make window available to all subroutines */
    irWindow = w;

    /* If in silent mode, turn printing off */
    if(irMazeParms->mp_verbosity==0)
    {
      TxPrintOff();
    }

    if(cmd->tx_argc == 1)
    {
      int irResult;

      /* No subcommand specified - so just route from cursor to box
       * No endpts or layers explicitly given on cmd, so args are
       * NULL below.
       */
      irResult = irRoute(w, ST_CURSOR,
            (Point*)NULL, (char*)NULL, (List*)NULL,     
            DT_BOX, (Point*)NULL, (char*)NULL, (List*)NULL);

#ifdef MAGIC_WRAPPER
      /* Set Tcl Result to irResult */
      switch (irResult)
      {
          case MZ_SUCCESS:
            Tcl_SetResult(magicinterp, "Route success", 0);
            break;
          case MZ_CURRENT_BEST:
            Tcl_SetResult(magicinterp, "Route best before interrupt", 0);
            break;
          case MZ_FAILURE:
            Tcl_SetResult(magicinterp, "Route failure", 0);
            break;
          case MZ_UNROUTABLE:
            Tcl_SetResult(magicinterp, "Route unroutable", 0);
            break;
          case MZ_INTERRUPTED:
            Tcl_SetResult(magicinterp, "Route interrupted", 0);
            break;
          case MZ_ALREADY_ROUTED:
            Tcl_SetResult(magicinterp, "Route already routed", 0);
            break;
      }
#endif

    }
    else
    {
      /* Lookup subcommand in table */
      which = LookupStruct(
          cmd->tx_argv[1], 
          (char **) irSubcommands, 
          sizeof irSubcommands[0]);

        /* Process result of lookup */
      if (which >= 0)
      {
          /* subcommand found - call proc that implements it */
          subCmdP = &irSubcommands[which];
          (*subCmdP->sC_proc)(w,cmd);
      }
      else if (which == -1)
      {
          /* ambiguous subcommand - complain */
          TxError("Ambiguous iroute subcommand: \"%s\"\n", cmd->tx_argv[1]);
      }
      else
      {
          /* unrecognized subcommand - complain */
          TxError("Unrecognized iroute subcommand: \"%s\"\n", 
                cmd->tx_argv[1]);
          TxError("Valid iroute irSubcommands are:  ");
          for (n = 0; irSubcommands[n].sC_name; n++)
            TxError(" %s", irSubcommands[n].sC_name);
          TxError("\n");
      }
    }

    /* turn printing back on, and return */
    TxPrintOn();
    return;
}

Generated by  Doxygen 1.6.0   Back to index