805 lines
20 KiB
C
805 lines
20 KiB
C
/*
|
|
* DBtechname.c --
|
|
*
|
|
* Mapping between tile types and their names.
|
|
* WARNING: with the exception of DB*TechName{Type,Plane}() and
|
|
* DB*ShortName(), * the procedures in this file MUST be called
|
|
* after DBTechFinalType() has been called.
|
|
*
|
|
* *********************************************************************
|
|
* * Copyright (C) 1985, 1990 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-8.0/database/DBtechname.c,v 1.3 2008/06/01 18:37:39 tim Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include "tcltk/tclmagic.h"
|
|
#include "utils/magic.h"
|
|
#include "utils/geometry.h"
|
|
#include "utils/utils.h"
|
|
#include "tiles/tile.h"
|
|
#include "utils/hash.h"
|
|
#include "database/database.h"
|
|
#include "database/databaseInt.h"
|
|
#include "utils/tech.h"
|
|
#include "textio/textio.h"
|
|
#include "utils/malloc.h"
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* DBTechNameType --
|
|
*
|
|
* Map from a type name into a type number. If the type name has
|
|
* the form "<type>/<plane>" and <type> is a contact, then the
|
|
* type returned is the image of the contact on <plane>. Of
|
|
* course, in this case, <type> must have an image on <plane>.
|
|
*
|
|
* Results:
|
|
* Type number. A value of -2 indicates that the type name was
|
|
* unknown; -1 indicates that it was ambiguous.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
TileType
|
|
DBTechNameType(typename)
|
|
char *typename; /* The name of the type */
|
|
{
|
|
char *slash;
|
|
TileType type;
|
|
int plane;
|
|
LayerInfo *lp;
|
|
|
|
slash = strchr(typename, '/');
|
|
if (slash != NULL) *slash = 0;
|
|
type = (TileType)(spointertype) dbTechNameLookup(typename, &dbTypeNameLists);
|
|
if (type < 0)
|
|
{
|
|
/* Check against the alias table. However, any specified alias */
|
|
/* must point to a SINGLE tile type, or we treat it as */
|
|
/* ambiguous. */
|
|
|
|
HashEntry *he;
|
|
TileTypeBitMask *bitmask;
|
|
TileType ttest;
|
|
|
|
he = HashLookOnly(&DBTypeAliasTable, typename);
|
|
if (he)
|
|
{
|
|
bitmask = (TileTypeBitMask *)HashGetValue(he);
|
|
for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
|
|
if (TTMaskHasType(bitmask, type))
|
|
{
|
|
for (ttest = type + 1; ttest < DBNumUserLayers; ttest++)
|
|
if (TTMaskHasType(bitmask, ttest))
|
|
{
|
|
type = -1;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (type == DBNumUserLayers)
|
|
type = -2;
|
|
}
|
|
}
|
|
|
|
if (slash == NULL) return type;
|
|
*slash = '/';
|
|
if (type < 0) return type;
|
|
|
|
/* There's a plane qualification. Make sure the type exists */
|
|
/* on the indicated plane. If not, return an error. */
|
|
|
|
plane = (spointertype) dbTechNameLookup(slash + 1, &dbPlaneNameLists);
|
|
if (plane < 0) return -2;
|
|
|
|
lp = &dbLayerInfo[type];
|
|
if (PlaneMaskHasPlane(lp->l_pmask, plane))
|
|
return type;
|
|
|
|
return -2;
|
|
}
|
|
|
|
TileType
|
|
DBTechNameTypeExact(typename)
|
|
char *typename; /* The name of the type */
|
|
{
|
|
char *slash;
|
|
ClientData result;
|
|
|
|
slash = strchr(typename, '/');
|
|
if (slash != NULL) return (TileType)(-1);
|
|
|
|
result = dbTechNameLookupExact(typename, &dbTypeNameLists);
|
|
return (TileType)((spointertype)result);
|
|
}
|
|
|
|
/*
|
|
*-------------------------------------------------------------------------
|
|
*
|
|
* The following returns a bitmask with the appropriate types set for the
|
|
* typename supplied.
|
|
*
|
|
* Results: returns the first type found
|
|
*
|
|
* Side Effects: sets bitmask with the appropriate types.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
TileType
|
|
DBTechNameTypes(typename, bitmask)
|
|
char *typename; /* The name of the type */
|
|
TileTypeBitMask *bitmask;
|
|
{
|
|
char *slash;
|
|
TileType type;
|
|
int plane;
|
|
LayerInfo *lp;
|
|
|
|
TTMaskZero(bitmask);
|
|
slash = strchr(typename, '/');
|
|
if (slash != NULL) *slash = 0;
|
|
type = (TileType)(spointertype) dbTechNameLookup(typename, &dbTypeNameLists);
|
|
if (type < 0)
|
|
{
|
|
HashEntry *he;
|
|
|
|
/* Check against the alias table */
|
|
he = HashLookOnly(&DBTypeAliasTable, typename);
|
|
if (he)
|
|
{
|
|
TTMaskSetMask(bitmask, (TileTypeBitMask *)HashGetValue(he));
|
|
for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
|
|
if (TTMaskHasType(bitmask, type))
|
|
break;
|
|
|
|
if (type == DBNumUserLayers)
|
|
type = -2;
|
|
}
|
|
}
|
|
else
|
|
TTMaskSetType(bitmask, type);
|
|
|
|
if (slash == NULL)
|
|
return type;
|
|
else
|
|
*slash = '/';
|
|
|
|
/* There's a plane qualification. Locate the image. */
|
|
|
|
plane = (spointertype) dbTechNameLookup(slash + 1, &dbPlaneNameLists);
|
|
if (plane < 0) return -2;
|
|
|
|
TTMaskAndMask(bitmask, &DBPlaneTypes[plane]);
|
|
|
|
/* If the type is no longer in the bitmask, return the first type that is. */
|
|
|
|
if (!TTMaskHasType(bitmask, type))
|
|
for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
|
|
if (TTMaskHasType(bitmask, type))
|
|
break;
|
|
|
|
return (type < DBNumUserLayers) ? type : -2;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* DBTechNoisyNameType --
|
|
*
|
|
* Map from a type name into a type number, complaining if the type
|
|
* is unknown.
|
|
*
|
|
* Results:
|
|
* Type number. A value of -2 indicates that the type name was
|
|
* unknown; -1 indicates that it was ambiguous.
|
|
*
|
|
* Side effects:
|
|
* Prints a diagnostic message if the type name is unknown.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
TileType
|
|
DBTechNoisyNameType(typename)
|
|
char *typename; /* The name of the type */
|
|
{
|
|
TileType type;
|
|
|
|
switch (type = DBTechNameType(typename))
|
|
{
|
|
case -1:
|
|
TechError("Ambiguous layer (type) name \"%s\"\n", typename);
|
|
break;
|
|
case -2:
|
|
TechError("Unrecognized layer (type) name \"%s\"\n", typename);
|
|
break;
|
|
default:
|
|
if (type < 0)
|
|
TechError("Funny type \"%s\" returned %d\n", typename, type);
|
|
break;
|
|
}
|
|
|
|
return (type);
|
|
}
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* DBTechNamePlane --
|
|
*
|
|
* Map from a plane name into a plane number.
|
|
*
|
|
* Results:
|
|
* Plane number. A value of -2 indicates that the plane name was
|
|
* unknown; -1 indicates that it was ambiguous.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
DBTechNamePlane(planename)
|
|
char *planename; /* The name of the plane */
|
|
{
|
|
return ((spointertype) dbTechNameLookup(planename, &dbPlaneNameLists));
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* DBTechNoisyNamePlane --
|
|
*
|
|
* Map from a plane name into a plane number, complaining if the plane
|
|
* is unknown.
|
|
*
|
|
* Results:
|
|
* Plane number. A value of -2 indicates that the plane name was
|
|
* unknown; -1 indicates that it was ambiguous.
|
|
*
|
|
* Side effects:
|
|
* Prints a diagnostic message if the type name is unknown.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
int
|
|
DBTechNoisyNamePlane(planename)
|
|
char *planename; /* The name of the plane */
|
|
{
|
|
int pNum;
|
|
|
|
switch (pNum = DBTechNamePlane(planename))
|
|
{
|
|
case -1:
|
|
TechError("Ambiguous plane name \"%s\"\n", planename);
|
|
break;
|
|
case -2:
|
|
TechError("Unrecognized plane name \"%s\"\n", planename);
|
|
break;
|
|
}
|
|
|
|
return (pNum);
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* DBTypeShortName --
|
|
* DBPlaneShortName --
|
|
*
|
|
* Return the short name for a type or plane.
|
|
* The short name is the "official abbreviation" for the type or plane,
|
|
* identified by a leading '*' in the list of names in the technology
|
|
* file.
|
|
*
|
|
* Results:
|
|
* Pointer to the primary short name for the given type or plane.
|
|
* If the type or plane has no official abbreviation, returns
|
|
* a pointer to the string "???".
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
const char *
|
|
DBTypeShortName(
|
|
TileType type)
|
|
{
|
|
const NameList *tbl;
|
|
|
|
for (tbl = dbTypeNameLists.sn_next;
|
|
tbl != &dbTypeNameLists;
|
|
tbl = tbl->sn_next)
|
|
{
|
|
if (tbl->sn_value == (ClientData)(pointertype) type && tbl->sn_primary)
|
|
return (tbl->sn_name);
|
|
}
|
|
|
|
if (type < 0) return ("ERROR");
|
|
else if (DBTypeLongNameTbl[type])
|
|
return (DBTypeLongNameTbl[type]);
|
|
return ("???");
|
|
}
|
|
|
|
const char *
|
|
DBPlaneShortName(
|
|
int pNum)
|
|
{
|
|
const NameList *tbl;
|
|
|
|
for (tbl = dbPlaneNameLists.sn_next;
|
|
tbl != &dbPlaneNameLists;
|
|
tbl = tbl->sn_next)
|
|
{
|
|
if (tbl->sn_value == (ClientData)(pointertype) pNum && tbl->sn_primary)
|
|
return (tbl->sn_name);
|
|
}
|
|
|
|
if (DBPlaneLongNameTbl[pNum])
|
|
return (DBPlaneLongNameTbl[pNum]);
|
|
return ("???");
|
|
}
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* DBTechTypesToPlanes --
|
|
*
|
|
* Convert a TileTypeBitMask into a mask of the planes which may
|
|
* contain tiles of that type.
|
|
*
|
|
* Results:
|
|
* A mask with bits set for those planes in which tiles of
|
|
* the types specified by the mask may reside. The mask
|
|
* is guaranteed only to contain bits corresponding to
|
|
* paint tile planes.
|
|
*
|
|
* Side effects:
|
|
* None.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
PlaneMask
|
|
DBTechTypesToPlanes(mask)
|
|
TileTypeBitMask *mask;
|
|
{
|
|
TileType t;
|
|
PlaneMask planeMask, noCellMask, retMask;
|
|
|
|
/* Space tiles are present in all planes but the router plane */
|
|
noCellMask = ~(PlaneNumToMaskBit(PL_ROUTER));
|
|
if (TTMaskHasType(mask, TT_SPACE)) {
|
|
retMask = PlaneNumToMaskBit(DBNumPlanes) - 1;
|
|
retMask &= noCellMask;
|
|
return retMask;
|
|
}
|
|
|
|
planeMask = 0;
|
|
for (t = 0; t < DBNumTypes; t++)
|
|
if (TTMaskHasType(mask, t))
|
|
planeMask |= DBTypePlaneMaskTbl[t];
|
|
|
|
retMask = planeMask & noCellMask;
|
|
return retMask;
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* DBTechPrintTypes --
|
|
*
|
|
* This routine prints out all the layer names for types defined
|
|
* in the current technology. If "typename" is non-NULL, then
|
|
* the "canonical" name of typename is printed.
|
|
*
|
|
* Results:
|
|
* None. In the Tcl version, the layer names are returned as a Tcl list.
|
|
*
|
|
* Side effects:
|
|
* Stuff is printed.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
void
|
|
DBTechPrintTypes(mask, dolist)
|
|
TileTypeBitMask *mask; /* Print layers defined by this mask. */
|
|
bool dolist; /* return as a list and don't print aliases */
|
|
{
|
|
TileType i;
|
|
NameList *p;
|
|
bool firstline = TRUE;
|
|
bool firstname;
|
|
DefaultType *dtp;
|
|
char *keepname;
|
|
|
|
if (!dolist) TxPrintf("Layer names are:\n");
|
|
|
|
/* List technology-dependent types */
|
|
for (i = TT_TECHDEPBASE; i < DBNumUserLayers; i++)
|
|
{
|
|
if (!TTMaskHasType(mask, i)) continue;
|
|
firstname = TRUE;
|
|
for (p = dbTypeNameLists.sn_next; p != &dbTypeNameLists;
|
|
p = p->sn_next)
|
|
{
|
|
/* Ignore aliases */
|
|
if (p->sn_alias) continue;
|
|
|
|
if (((TileType)(spointertype) p->sn_value) == i)
|
|
{
|
|
if (dolist)
|
|
{
|
|
if (firstname) keepname = p->sn_name;
|
|
else if (strlen(p->sn_name) > strlen(keepname))
|
|
keepname = p->sn_name;
|
|
}
|
|
else
|
|
{
|
|
if (firstname) TxPrintf(" %s", p->sn_name);
|
|
else TxPrintf(" or %s", p->sn_name);
|
|
}
|
|
firstname = FALSE;
|
|
}
|
|
}
|
|
|
|
if (!firstline)
|
|
{
|
|
if (dolist)
|
|
{
|
|
#ifdef MAGIC_WRAPPER
|
|
Tcl_AppendResult(magicinterp, " ", (char *)NULL);
|
|
#else
|
|
TxPrintf(" ");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (dolist)
|
|
{
|
|
#ifdef MAGIC_WRAPPER
|
|
Tcl_AppendResult(magicinterp, keepname, (char *)NULL);
|
|
#else
|
|
TxPrintf("%s", keepname);
|
|
#endif
|
|
}
|
|
else TxPrintf("\n");
|
|
|
|
firstline = FALSE;
|
|
}
|
|
|
|
/* List built-in types that are normally painted by name */
|
|
for (dtp = dbTechDefaultTypes; dtp->dt_names; dtp++)
|
|
{
|
|
if (!TTMaskHasType(mask, dtp->dt_type)) continue;
|
|
if (dtp->dt_print)
|
|
{
|
|
firstname = TRUE;
|
|
for (p = dbTypeNameLists.sn_next; p != &dbTypeNameLists;
|
|
p = p->sn_next)
|
|
{
|
|
if (((TileType)(spointertype) p->sn_value) == dtp->dt_type)
|
|
{
|
|
if (dolist)
|
|
{
|
|
if (firstname) keepname = p->sn_name;
|
|
else if (strlen(p->sn_name) > strlen(keepname))
|
|
keepname = p->sn_name;
|
|
}
|
|
else
|
|
{
|
|
if (firstname) TxPrintf(" %s", p->sn_name);
|
|
else TxPrintf(" or %s", p->sn_name);
|
|
}
|
|
firstname = FALSE;
|
|
}
|
|
}
|
|
|
|
if (!firstline)
|
|
{
|
|
if (dolist)
|
|
{
|
|
#ifdef MAGIC_WRAPPER
|
|
Tcl_AppendResult(magicinterp, " ", (char *)NULL);
|
|
#else
|
|
TxPrintf(" ");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (dolist)
|
|
{
|
|
#ifdef MAGIC_WRAPPER
|
|
Tcl_AppendResult(magicinterp, keepname, (char *)NULL);
|
|
#else
|
|
TxPrintf("%s", keepname);
|
|
#endif
|
|
}
|
|
else TxPrintf("\n");
|
|
|
|
firstline = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
*
|
|
* DBTechNoisyNameMask --
|
|
*
|
|
* Parses an argument string that selects a group of layers.
|
|
* The string may contain one or more layer names separated
|
|
* by commas. The special layer name of "0" specifies no layer,
|
|
* it is used as a place holder, e.g., to specify a null
|
|
* layer list for the CornerTypes field in a drc edge-rule.
|
|
* In addition, a tilde may be used to indicate
|
|
* "all layers but", and parentheses may be used for grouping.
|
|
* Thus ~x means "all layers but x", and ~(x,y),z means "z plus
|
|
* everything except x and y)". When contacts are specified,
|
|
* ALL images of the contact are automatically included, unless
|
|
* a specific plane is indicated in the layer specification
|
|
* using "/". For example, x/foo refers to the image of contact
|
|
* "x" on plane "foo". The layer specification may also follow
|
|
* a parenthesized group. For example, ~(x,y)/foo refers to
|
|
* all layers on plane "foo" except "x" and "y".
|
|
*
|
|
* Magic version 7.3 defines *x to mean "x and all
|
|
* contact layers containing x as a residue". Thus, for example,
|
|
* *metal1 expands to m1,pc,ndc,pdc,nsc,psc,m2c,... Because many
|
|
* connect, cif, extract, and drc rules list all these layers,
|
|
* the asterisk notation makes the techfile shorter and more
|
|
* readable.
|
|
*
|
|
* Magic version 7.3 also defines a hash table "DBTypeAliasTable"
|
|
* that allows macros to be embedded in the technology file.
|
|
* Macros are expanded first, prior to applying the parsing
|
|
* described above.
|
|
*
|
|
* Results:
|
|
* Returns a plane mask of all the planes specified.
|
|
*
|
|
* Side effects:
|
|
* Error messages are output if layers aren't understood.
|
|
* Sets the TileTypeBitMask 'mask' to all the layer names indicated.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
PlaneMask
|
|
DBTechNameMask0(layers, mask, noisy)
|
|
char *layers; /* String to be parsed. */
|
|
TileTypeBitMask *mask; /* Where to store the layer mask. */
|
|
bool noisy; /* Whether or not to output errors */
|
|
{
|
|
char *p, *p2, c;
|
|
TileTypeBitMask m2; /* Each time around the loop, we will
|
|
* form the mask for one section of
|
|
* the layer string.
|
|
*/
|
|
char save;
|
|
bool allBut;
|
|
PlaneMask planemask = 0;
|
|
TileTypeBitMask *rMask;
|
|
|
|
TTMaskZero(mask);
|
|
p = layers;
|
|
while (TRUE)
|
|
{
|
|
TTMaskZero(&m2);
|
|
|
|
c = *p;
|
|
if (c == 0) break;
|
|
|
|
/* Check for a tilde, and remember it in order to do negation. */
|
|
|
|
if (c == '~')
|
|
{
|
|
allBut = TRUE;
|
|
p += 1;
|
|
c = *p;
|
|
}
|
|
else allBut = FALSE;
|
|
|
|
/* Check for parentheses. If there's an open parenthesis,
|
|
* find the matching close parenthesis and recursively parse
|
|
* the string in-between.
|
|
*/
|
|
|
|
if (c == '(')
|
|
{
|
|
int nesting = 0;
|
|
|
|
p += 1;
|
|
for (p2 = p; ; p2 += 1)
|
|
{
|
|
if (*p2 == '(') nesting += 1;
|
|
else if (*p2 == ')')
|
|
{
|
|
nesting -= 1;
|
|
if (nesting < 0) break;
|
|
}
|
|
else if (*p2 == 0)
|
|
{
|
|
TechError("Unmatched parenthesis in layer name \"%s\".\n",
|
|
layers);
|
|
break;
|
|
}
|
|
}
|
|
save = *p2;
|
|
*p2 = 0;
|
|
planemask |= DBTechNameMask0(p, &m2, noisy);
|
|
*p2 = save;
|
|
if (save == ')') p = p2 + 1;
|
|
else p = p2;
|
|
}
|
|
else
|
|
{
|
|
TileType t, rtype;
|
|
bool allResidues = FALSE;
|
|
|
|
/* No parenthesis, so just parse off a single name. Layer
|
|
* name "0" corresponds to no layers at all.
|
|
*/
|
|
|
|
for (p2 = p; ; p2++)
|
|
{
|
|
c = *p2;
|
|
if ((c == '/') || (c == ',') || (c == 0)) break;
|
|
}
|
|
if (p2 == p)
|
|
{
|
|
TechError("Missing layer name in \"%s\".\n", layers);
|
|
}
|
|
else if (strcmp(p, "0") != 0)
|
|
{
|
|
HashEntry *he;
|
|
|
|
save = *p2;
|
|
*p2 = '\0';
|
|
|
|
/* Check the alias table for macro definitions */
|
|
he = HashLookOnly(&DBTypeAliasTable, p);
|
|
if (he)
|
|
{
|
|
TileTypeBitMask *amask;
|
|
amask = (TileTypeBitMask *)HashGetValue(he);
|
|
TTMaskSetMask(&m2, amask);
|
|
}
|
|
else
|
|
{
|
|
/* Check for asterisk notation, meaning to include */
|
|
/* all types which have this type as a residue. */
|
|
if (*p == '*')
|
|
{
|
|
allResidues = TRUE;
|
|
p++;
|
|
}
|
|
|
|
if (noisy)
|
|
t = DBTechNoisyNameType(p);
|
|
else
|
|
t = DBTechNameType(p);
|
|
if (t >= 0)
|
|
m2 = DBLayerTypeMaskTbl[t];
|
|
|
|
/* Include all types which have t as a residue */
|
|
|
|
if (allResidues)
|
|
for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
|
|
{
|
|
rMask = DBResidueMask(rtype);
|
|
if (TTMaskHasType(rMask, t))
|
|
TTMaskSetType(&m2, rtype);
|
|
}
|
|
|
|
/* Include all stacking types which have t as a residue */
|
|
/* (this is done regardless of the presence of "*") */
|
|
|
|
for (rtype = DBNumUserLayers; rtype < DBNumTypes; rtype++)
|
|
{
|
|
rMask = DBResidueMask(rtype);
|
|
if (TTMaskIntersect(rMask, &m2))
|
|
TTMaskSetType(&m2, rtype);
|
|
}
|
|
}
|
|
*p2 = save;
|
|
}
|
|
p = p2;
|
|
}
|
|
|
|
/* Now negate the layers, if that is called for. */
|
|
|
|
if (allBut) TTMaskCom(&m2);
|
|
|
|
/* Restrict to a single plane, if that is called for. */
|
|
|
|
if (*p == '/')
|
|
{
|
|
int plane;
|
|
|
|
p2 = p+1;
|
|
while ((*p2 != 0) && (*p2 != ',')) p2 += 1;
|
|
save = *p2;
|
|
*p2 = 0;
|
|
if (noisy)
|
|
plane = DBTechNoisyNamePlane(p+1);
|
|
else
|
|
plane = DBTechNamePlane(p+1);
|
|
*p2 = save;
|
|
p = p2;
|
|
if (plane > 0)
|
|
{
|
|
TTMaskAndMask(&m2, &DBPlaneTypes[plane]);
|
|
planemask = PlaneNumToMaskBit(plane);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TileType t;
|
|
|
|
for (t = TT_TECHDEPBASE; t < DBNumUserLayers; t++)
|
|
if (TTMaskHasType(&m2, t))
|
|
planemask |= DBTypePlaneMaskTbl[t];
|
|
}
|
|
|
|
TTMaskSetMask(mask, &m2);
|
|
while (*p == ',') p++;
|
|
}
|
|
|
|
/* If there are no types, or if "space" is the only type, then */
|
|
/* return a full planemask */
|
|
|
|
if ((TTMaskIsZero(mask) || TTMaskEqual(mask, &DBSpaceBits)) &&
|
|
(planemask == (PlaneMask)0))
|
|
planemask = DBTypePlaneMaskTbl[TT_SPACE];
|
|
|
|
return planemask;
|
|
}
|
|
|
|
/* Wrappers for DBTechNameMask0() */
|
|
|
|
PlaneMask
|
|
DBTechNoisyNameMask(layers, mask)
|
|
char *layers; /* String to be parsed. */
|
|
TileTypeBitMask *mask; /* Where to store the layer mask. */
|
|
{
|
|
return DBTechNameMask0(layers, mask, TRUE);
|
|
}
|
|
|
|
PlaneMask
|
|
DBTechNameMask(layers, mask)
|
|
char *layers; /* String to be parsed. */
|
|
TileTypeBitMask *mask; /* Where to store the layer mask. */
|
|
{
|
|
return DBTechNameMask0(layers, mask, FALSE);
|
|
}
|