1 /*
2  * DBtechname.c --
3  *
4  * Mapping between tile types and their names.
5  * WARNING: with the exception of DB*TechName{Type,Plane}() and
6  * DB*ShortName(), * the procedures in this file MUST be called
7  * after DBTechFinalType() has been called.
8  *
9  *     *********************************************************************
10  *     * Copyright (C) 1985, 1990 Regents of the University of California. *
11  *     * Permission to use, copy, modify, and distribute this              *
12  *     * software and its documentation for any purpose and without        *
13  *     * fee is hereby granted, provided that the above copyright          *
14  *     * notice appear in all copies.  The University of California        *
15  *     * makes no representations about the suitability of this            *
16  *     * software for any purpose.  It is provided "as is" without         *
17  *     * express or implied warranty.  Export of this software outside     *
18  *     * of the United States of America may require an export license.    *
19  *     *********************************************************************
20  */
21 
22 #ifndef lint
23 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 $";
24 #endif  /* not lint */
25 
26 #include <stdio.h>
27 #include <string.h>
28 #include <ctype.h>
29 
30 #include "tcltk/tclmagic.h"
31 #include "utils/magic.h"
32 #include "utils/geometry.h"
33 #include "utils/utils.h"
34 #include "tiles/tile.h"
35 #include "utils/hash.h"
36 #include "database/database.h"
37 #include "database/databaseInt.h"
38 #include "utils/tech.h"
39 #include "textio/textio.h"
40 #include "utils/malloc.h"
41 
42 
43 /*
44  * ----------------------------------------------------------------------------
45  *
46  * DBTechNameType --
47  *
48  * Map from a type name into a type number.  If the type name has
49  * the form "<type>/<plane>" and <type> is a contact, then the
50  * type returned is the image of the contact on <plane>.  Of
51  * course, in this case, <type> must have an image on <plane>.
52  *
53  * Results:
54  *	Type number.  A value of -2 indicates that the type name was
55  *	unknown; -1 indicates that it was ambiguous.
56  *
57  * Side effects:
58  *	None.
59  *
60  * ----------------------------------------------------------------------------
61  */
62 
63 TileType
DBTechNameType(typename)64 DBTechNameType(typename)
65     char *typename;	/* The name of the type */
66 {
67     char *slash;
68     TileType type;
69     int plane;
70     LayerInfo *lp;
71 
72     slash = strchr(typename, '/');
73     if (slash != NULL) *slash = 0;
74     type = (TileType)(spointertype) dbTechNameLookup(typename, &dbTypeNameLists);
75     if (type < 0)
76     {
77 	/* Check against the alias table.  However, any specified alias	*/
78 	/* must point to a SINGLE tile type, or we treat it as		*/
79 	/* ambiguous.							*/
80 
81 	HashEntry *he;
82 	TileTypeBitMask *bitmask;
83 	TileType ttest;
84 
85 	he = HashLookOnly(&DBTypeAliasTable, typename);
86 	if (he)
87 	{
88 	    bitmask = (TileTypeBitMask *)HashGetValue(he);
89 	    for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
90 		if (TTMaskHasType(bitmask, type))
91 		{
92 		    for (ttest = type + 1; ttest < DBNumUserLayers; ttest++)
93 			if (TTMaskHasType(bitmask, ttest))
94 			{
95 			    type = -1;
96 			    break;
97 			}
98 		    break;
99 		}
100 
101 	    if (type == DBNumUserLayers)
102 		type = -2;
103 	}
104     }
105 
106     if (slash == NULL) return type;
107     *slash = '/';
108     if (type < 0) return type;
109 
110     /* There's a plane qualification.  Make sure the type exists */
111     /* on the indicated plane.  If not, return an error.	 */
112 
113     plane = (spointertype) dbTechNameLookup(slash + 1, &dbPlaneNameLists);
114     if (plane < 0) return -2;
115 
116     lp = &dbLayerInfo[type];
117     if (PlaneMaskHasPlane(lp->l_pmask, plane))
118 	return type;
119 
120     return -2;
121 }
122 
123 TileType
DBTechNameTypeExact(typename)124 DBTechNameTypeExact(typename)
125     char *typename;	/* The name of the type */
126 {
127     char *slash;
128     ClientData result;
129 
130     slash = strchr(typename, '/');
131     if (slash != NULL) return (TileType)(-1);
132 
133     result = dbTechNameLookupExact(typename, &dbTypeNameLists);
134     return (TileType)((spointertype)result);
135 }
136 
137 /*
138  *-------------------------------------------------------------------------
139  *
140  * The following returns a bitmask with the appropriate types set for the
141  *	typename supplied.
142  *
143  * Results: returns the first type found
144  *
145  * Side Effects: sets bitmask with the appropriate types.
146  *
147  *-------------------------------------------------------------------------
148  */
149 
150 TileType
DBTechNameTypes(typename,bitmask)151 DBTechNameTypes(typename, bitmask)
152     char *typename;	/* The name of the type */
153     TileTypeBitMask	*bitmask;
154 {
155     char *slash;
156     TileType type;
157     int plane;
158     LayerInfo *lp;
159 
160     TTMaskZero(bitmask);
161     slash = strchr(typename, '/');
162     if (slash != NULL) *slash = 0;
163     type = (TileType)(spointertype) dbTechNameLookup(typename, &dbTypeNameLists);
164     if (type < 0)
165     {
166 	HashEntry *he;
167 
168 	/* Check against the alias table */
169 	he = HashLookOnly(&DBTypeAliasTable, typename);
170 	if (he)
171 	{
172 	    TTMaskSetMask(bitmask, (TileTypeBitMask *)HashGetValue(he));
173 	    for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
174 		if (TTMaskHasType(bitmask, type))
175 		    break;
176 
177 	    if (type == DBNumUserLayers)
178 		type = -2;
179 	}
180     }
181     else
182     	 TTMaskSetType(bitmask, type);
183 
184     if (slash == NULL)
185 	return type;
186     else
187 	*slash = '/';
188 
189     /* There's a plane qualification.  Locate the image. */
190 
191     plane = (spointertype) dbTechNameLookup(slash + 1, &dbPlaneNameLists);
192     if (plane < 0) return -2;
193 
194     TTMaskAndMask(bitmask, &DBPlaneTypes[plane]);
195 
196     /* If the type is no longer in the bitmask, return the first type that is. */
197 
198     if (!TTMaskHasType(bitmask, type))
199 	for (type = TT_TECHDEPBASE; type < DBNumUserLayers; type++)
200 	    if (TTMaskHasType(bitmask, type))
201 		break;
202 
203     return (type < DBNumUserLayers) ? type : -2;
204 }
205 
206 
207 /*
208  * ----------------------------------------------------------------------------
209  *
210  * DBTechNoisyNameType --
211  *
212  * Map from a type name into a type number, complaining if the type
213  * is unknown.
214  *
215  * Results:
216  *	Type number.  A value of -2 indicates that the type name was
217  *	unknown; -1 indicates that it was ambiguous.
218  *
219  * Side effects:
220  *	Prints a diagnostic message if the type name is unknown.
221  *
222  * ----------------------------------------------------------------------------
223  */
224 
225 TileType
DBTechNoisyNameType(typename)226 DBTechNoisyNameType(typename)
227     char *typename;	/* The name of the type */
228 {
229     TileType type;
230 
231     switch (type = DBTechNameType(typename))
232     {
233 	case -1:
234 	    TechError("Ambiguous layer (type) name \"%s\"\n", typename);
235 	    break;
236 	case -2:
237 	    TechError("Unrecognized layer (type) name \"%s\"\n", typename);
238 	    break;
239 	default:
240 	    if (type < 0)
241 		TechError("Funny type \"%s\" returned %d\n", typename, type);
242 	    break;
243     }
244 
245     return (type);
246 }
247 /*
248  * ----------------------------------------------------------------------------
249  *
250  * DBTechNamePlane --
251  *
252  * Map from a plane name into a plane number.
253  *
254  * Results:
255  *	Plane number.  A value of -2 indicates that the plane name was
256  *	unknown; -1 indicates that it was ambiguous.
257  *
258  * Side effects:
259  *	None.
260  *
261  * ----------------------------------------------------------------------------
262  */
263 
264 int
DBTechNamePlane(planename)265 DBTechNamePlane(planename)
266     char *planename;	/* The name of the plane */
267 {
268     return ((spointertype) dbTechNameLookup(planename, &dbPlaneNameLists));
269 }
270 
271 /*
272  * ----------------------------------------------------------------------------
273  *
274  * DBTechNoisyNamePlane --
275  *
276  * Map from a plane name into a plane number, complaining if the plane
277  * is unknown.
278  *
279  * Results:
280  *	Plane number.  A value of -2 indicates that the plane name was
281  *	unknown; -1 indicates that it was ambiguous.
282  *
283  * Side effects:
284  *	Prints a diagnostic message if the type name is unknown.
285  *
286  * ----------------------------------------------------------------------------
287  */
288 
289 int
DBTechNoisyNamePlane(planename)290 DBTechNoisyNamePlane(planename)
291     char *planename;	/* The name of the plane */
292 {
293     int pNum;
294 
295     switch (pNum = DBTechNamePlane(planename))
296     {
297 	case -1:
298 	    TechError("Ambiguous plane name \"%s\"\n", planename);
299 	    break;
300 	case -2:
301 	    TechError("Unrecognized plane name \"%s\"\n", planename);
302 	    break;
303     }
304 
305     return (pNum);
306 }
307 
308 /*
309  * ----------------------------------------------------------------------------
310  *
311  * DBTypeShortName --
312  * DBPlaneShortName --
313  *
314  * Return the short name for a type or plane.
315  * The short name is the "official abbreviation" for the type or plane,
316  * identified by a leading '*' in the list of names in the technology
317  * file.
318  *
319  * Results:
320  *	Pointer to the primary short name for the given type or plane.
321  *	If the type or plane has no official abbreviation, returns
322  *	a pointer to the string "???".
323  *
324  * Side effects:
325  *	None.
326  *
327  * ----------------------------------------------------------------------------
328  */
329 
330 char *
DBTypeShortName(type)331 DBTypeShortName(type)
332     TileType type;
333 {
334     NameList *tbl;
335 
336     for (tbl = dbTypeNameLists.sn_next;
337 	    tbl != &dbTypeNameLists;
338 	    tbl = tbl->sn_next)
339     {
340 	if (tbl->sn_value == (ClientData)(pointertype) type && tbl->sn_primary)
341 	    return (tbl->sn_name);
342     }
343 
344     if (type < 0) return ("ERROR");
345     else if (DBTypeLongNameTbl[type])
346 	return (DBTypeLongNameTbl[type]);
347     return ("???");
348 }
349 
350 char *
DBPlaneShortName(pNum)351 DBPlaneShortName(pNum)
352     int pNum;
353 {
354     NameList *tbl;
355 
356     for (tbl = dbPlaneNameLists.sn_next;
357 	    tbl != &dbPlaneNameLists;
358 	    tbl = tbl->sn_next)
359     {
360 	if (tbl->sn_value == (ClientData)(pointertype) pNum && tbl->sn_primary)
361 	    return (tbl->sn_name);
362     }
363 
364     if (DBPlaneLongNameTbl[pNum])
365 	return (DBPlaneLongNameTbl[pNum]);
366     return ("???");
367 }
368 
369 /*
370  * ----------------------------------------------------------------------------
371  *
372  * DBTechTypesToPlanes --
373  *
374  * Convert a TileTypeBitMask into a mask of the planes which may
375  * contain tiles of that type.
376  *
377  * Results:
378  *	A mask with bits set for those planes in which tiles of
379  *	the types specified by the mask may reside.  The mask
380  *	is guaranteed only to contain bits corresponding to
381  *	paint tile planes.
382  *
383  * Side effects:
384  *	None.
385  *
386  * ----------------------------------------------------------------------------
387  */
388 
389 PlaneMask
DBTechTypesToPlanes(mask)390 DBTechTypesToPlanes(mask)
391     TileTypeBitMask *mask;
392 {
393     TileType t;
394     PlaneMask planeMask, noCellMask, retMask;
395 
396     /* Space tiles are present in all planes but the router plane */
397     noCellMask = ~(PlaneNumToMaskBit(PL_ROUTER));
398     if (TTMaskHasType(mask, TT_SPACE)) {
399 	retMask = PlaneNumToMaskBit(DBNumPlanes) - 1;
400 	retMask &= noCellMask;
401 	return retMask;
402     }
403 
404     planeMask = 0;
405     for (t = 0; t < DBNumTypes; t++)
406 	if (TTMaskHasType(mask, t))
407 	    planeMask |= DBTypePlaneMaskTbl[t];
408 
409     retMask = planeMask & noCellMask;
410     return retMask;
411 }
412 
413 
414 /*
415  * ----------------------------------------------------------------------------
416  *
417  * DBTechPrintTypes --
418  *
419  * 	This routine prints out all the layer names for types defined
420  *	in the current technology.  If "typename" is non-NULL, then
421  *	the "canonical" name of typename is printed.
422  *
423  * Results:
424  *	None.  In the Tcl version, the layer names are returned as a Tcl list.
425  *
426  * Side effects:
427  *	Stuff is printed.
428  *
429  * ----------------------------------------------------------------------------
430  */
431 
432 void
DBTechPrintTypes(mask,dolist)433 DBTechPrintTypes(mask, dolist)
434     TileTypeBitMask *mask;  /* Print layers defined by this mask.	*/
435     bool dolist;	    /* return as a list and don't print aliases	*/
436 {
437     TileType i;
438     NameList *p;
439     bool firstline = TRUE;
440     bool firstname;
441     DefaultType *dtp;
442     char *keepname;
443 
444     if (!dolist) TxPrintf("Layer names are:\n");
445 
446     /* List technology-dependent types */
447     for (i = TT_TECHDEPBASE; i < DBNumUserLayers; i++)
448     {
449 	if (!TTMaskHasType(mask, i)) continue;
450 	firstname = TRUE;
451 	for (p = dbTypeNameLists.sn_next; p != &dbTypeNameLists;
452 		p = p->sn_next)
453 	{
454 	    /* Ignore aliases */
455 	    if (p->sn_alias) continue;
456 
457 	    if (((TileType)(spointertype) p->sn_value) == i)
458 	    {
459 		if (dolist)
460 		{
461 		    if (firstname) keepname = p->sn_name;
462 		    else if (strlen(p->sn_name) > strlen(keepname))
463 			keepname = p->sn_name;
464 		}
465 		else
466 		{
467 		    if (firstname) TxPrintf("    %s", p->sn_name);
468 		    else TxPrintf(" or %s", p->sn_name);
469 		}
470 		firstname = FALSE;
471 	    }
472 	}
473 
474 	if (!firstline)
475 	{
476 	    if (dolist)
477 	    {
478 #ifdef MAGIC_WRAPPER
479 		Tcl_AppendResult(magicinterp, " ", (char *)NULL);
480 #else
481 		TxPrintf(" ", keepname);
482 #endif
483 	    }
484 	}
485 
486 	if (dolist)
487 	{
488 #ifdef MAGIC_WRAPPER
489 	    Tcl_AppendResult(magicinterp, keepname, (char *)NULL);
490 #else
491 	    TxPrintf("%s", keepname);
492 #endif
493 	}
494 	else TxPrintf("\n");
495 
496 	firstline = FALSE;
497     }
498 
499     /* List built-in types that are normally painted by name */
500     for (dtp = dbTechDefaultTypes; dtp->dt_names; dtp++)
501     {
502 	if (!TTMaskHasType(mask, dtp->dt_type)) continue;
503 	if (dtp->dt_print)
504 	{
505 	    firstname = TRUE;
506 	    for (p = dbTypeNameLists.sn_next; p != &dbTypeNameLists;
507 		p = p->sn_next)
508 	    {
509 		if (((TileType)(spointertype) p->sn_value) == dtp->dt_type)
510 		{
511 		    if (dolist)
512 		    {
513 		        if (firstname) keepname = p->sn_name;
514 		        else if (strlen(p->sn_name) > strlen(keepname))
515 			    keepname = p->sn_name;
516 		    }
517 		    else
518 		    {
519 		        if (firstname) TxPrintf("    %s", p->sn_name);
520 		        else TxPrintf(" or %s", p->sn_name);
521 		    }
522 		    firstname = FALSE;
523 		}
524 	    }
525 
526 	    if (!firstline)
527 	    {
528 		if (dolist)
529 		{
530 #ifdef MAGIC_WRAPPER
531 		    Tcl_AppendResult(magicinterp, " ", (char *)NULL);
532 #else
533 		    TxPrintf(" ", keepname);
534 #endif
535 		}
536 	    }
537 
538 	    if (dolist)
539 	    {
540 #ifdef MAGIC_WRAPPER
541 		Tcl_AppendResult(magicinterp, keepname, (char *)NULL);
542 #else
543 		TxPrintf("%s", keepname);
544 #endif
545 	    }
546 	    else TxPrintf("\n");
547 
548 	    firstline = FALSE;
549 	}
550     }
551 }
552 
553 
554 /*
555  * ----------------------------------------------------------------------------
556  *
557  * DBTechNoisyNameMask --
558  *
559  *	Parses an argument string that selects a group of layers.
560  *	The string may contain one or more layer names separated
561  *	by commas.  The special layer name of "0" specifies no layer,
562  *      it is used as a place holder, e.g., to specify a null
563  *      layer list for the CornerTypes field in a drc edge-rule.
564  *      In addition, a tilde may be used to indicate
565  *	"all layers but", and parentheses may be used for grouping.
566  *	Thus ~x means "all layers but x", and ~(x,y),z means "z plus
567  *	everything except x and y)".  When contacts are specified,
568  *	ALL images of the contact are automatically included, unless
569  *	a specific plane is indicated in the layer specification
570  *	using "/".  For example, x/foo refers to the image of contact
571  *	"x" on plane "foo".  The layer specification may also follow
572  *	a parenthesized group.  For example, ~(x,y)/foo refers to
573  *	all layers on plane "foo" except "x" and "y".
574  *
575  *	Magic version 7.3 defines *x to mean "x and all
576  *	contact layers containing x as a residue".  Thus, for example,
577  *	*metal1 expands to m1,pc,ndc,pdc,nsc,psc,m2c,...  Because many
578  *	connect, cif, extract, and drc rules list all these layers,
579  *	the asterisk notation makes the techfile shorter and more
580  *	readable.
581  *
582  *	Magic version 7.3 also defines a hash table "DBTypeAliasTable"
583  *	that allows macros to be embedded in the technology file.
584  *	Macros are expanded first, prior to applying the parsing
585  *	described above.
586  *
587  * Results:
588  *	Returns a plane mask of all the planes specified.
589  *
590  * Side effects:
591  *	Error messages are output if layers aren't understood.
592  *	Sets the TileTypeBitMask 'mask' to all the layer names indicated.
593  *
594  * ----------------------------------------------------------------------------
595  */
596 
597 PlaneMask
DBTechNameMask0(layers,mask,noisy)598 DBTechNameMask0(layers, mask, noisy)
599     char *layers;			/* String to be parsed. */
600     TileTypeBitMask *mask;		/* Where to store the layer mask. */
601     bool noisy;				/* Whether or not to output errors */
602 {
603     char *p, *p2, c;
604     TileTypeBitMask m2;        /* Each time around the loop, we will
605 				* form the mask for one section of
606 				* the layer string.
607 				*/
608     char save;
609     bool allBut;
610     PlaneMask planemask = 0;
611     TileTypeBitMask *rMask;
612 
613     TTMaskZero(mask);
614     p = layers;
615     while (TRUE)
616     {
617 	TTMaskZero(&m2);
618 
619 	c = *p;
620 	if (c == 0) break;
621 
622 	/* Check for a tilde, and remember it in order to do negation. */
623 
624 	if (c == '~')
625 	{
626 	    allBut = TRUE;
627 	    p += 1;
628 	    c = *p;
629 	}
630 	else allBut = FALSE;
631 
632 	/* Check for parentheses.  If there's an open parenthesis,
633 	 * find the matching close parenthesis and recursively parse
634 	 * the string in-between.
635 	 */
636 
637 	if (c == '(')
638 	{
639 	    int nesting = 0;
640 
641 	    p += 1;
642 	    for (p2 = p; ; p2 += 1)
643 	    {
644 		if (*p2 == '(') nesting += 1;
645 		else if (*p2 == ')')
646 		{
647 		    nesting -= 1;
648 		    if (nesting < 0) break;
649 		}
650 		else if (*p2 == 0)
651 		{
652 		    TechError("Unmatched parenthesis in layer name \"%s\".\n",
653 			layers);
654 		    break;
655 		}
656 	    }
657 	    save = *p2;
658 	    *p2 = 0;
659 	    planemask |= DBTechNameMask0(p, &m2, noisy);
660 	    *p2 = save;
661 	    if (save == ')') p = p2 + 1;
662 	    else p = p2;
663 	}
664 	else
665 	{
666 	    TileType t, rtype;
667 	    bool allResidues = FALSE;
668 
669 	    /* No parenthesis, so just parse off a single name.  Layer
670 	     * name "0" corresponds to no layers at all.
671 	     */
672 
673 	    for (p2 = p; ; p2++)
674 	    {
675 		c = *p2;
676 		if ((c == '/') || (c == ',') || (c == 0)) break;
677 	    }
678 	    if (p2 == p)
679 	    {
680 		TechError("Missing layer name in \"%s\".\n", layers);
681 	    }
682 	    else if (strcmp(p, "0") != 0)
683 	    {
684 		HashEntry *he;
685 
686 		save = *p2;
687 		*p2 = '\0';
688 
689 		/* Check the alias table for macro definitions */
690 		he = HashLookOnly(&DBTypeAliasTable, p);
691 		if (he)
692 		{
693 		    TileTypeBitMask *amask;
694 		    amask = (TileTypeBitMask *)HashGetValue(he);
695 		    TTMaskSetMask(&m2, amask);
696 		}
697 		else
698 		{
699 		    /* Check for asterisk notation, meaning to include	*/
700 		    /* all types which have this type as a residue.	*/
701 		    if (*p == '*')
702 		    {
703 			allResidues = TRUE;
704 			p++;
705 		    }
706 
707 		    if (noisy)
708 			t = DBTechNoisyNameType(p);
709 		    else
710 			t = DBTechNameType(p);
711 		    if (t >= 0)
712 			m2 = DBLayerTypeMaskTbl[t];
713 
714 		    /* Include all types which have t as a residue		*/
715 
716 		    if (allResidues)
717 			for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
718 			{
719 			    rMask = DBResidueMask(rtype);
720 			    if (TTMaskHasType(rMask, t))
721 				TTMaskSetType(&m2, rtype);
722 			}
723 
724 		    /* Include all stacking types which have t as a residue	*/
725 		    /* (this is done regardless of the presence of "*")		*/
726 
727 		    for (rtype = DBNumUserLayers; rtype < DBNumTypes; rtype++)
728 		    {
729 			rMask = DBResidueMask(rtype);
730 			if (TTMaskIntersect(rMask, &m2))
731 			    TTMaskSetType(&m2, rtype);
732 		    }
733 		}
734 		*p2 = save;
735 	    }
736 	    p = p2;
737 	}
738 
739 	/* Now negate the layers, if that is called for. */
740 
741 	if (allBut) TTMaskCom(&m2);
742 
743 	/* Restrict to a single plane, if that is called for. */
744 
745 	if (*p == '/')
746 	{
747 	    int plane;
748 
749 	    p2 = p+1;
750 	    while ((*p2 != 0) && (*p2 != ',')) p2 += 1;
751 	    save = *p2;
752 	    *p2 = 0;
753 	    if (noisy)
754     		plane = DBTechNoisyNamePlane(p+1);
755 	    else
756     		plane = DBTechNamePlane(p+1);
757 	    *p2 = save;
758 	    p = p2;
759 	    if (plane > 0)
760 	    {
761 		TTMaskAndMask(&m2, &DBPlaneTypes[plane]);
762 		planemask = PlaneNumToMaskBit(plane);
763 	    }
764 	}
765 	else
766 	{
767 	    TileType t;
768 
769 	    for (t = TT_TECHDEPBASE; t < DBNumUserLayers; t++)
770 		if (TTMaskHasType(&m2, t))
771 		    planemask |= DBTypePlaneMaskTbl[t];
772 	}
773 
774 	TTMaskSetMask(mask, &m2);
775 	while (*p == ',') p++;
776     }
777 
778     /* If there are no types, or if "space" is the only type, then	*/
779     /* return a full planemask						*/
780 
781     if ((TTMaskIsZero(mask) || TTMaskEqual(mask, &DBSpaceBits)) &&
782 		(planemask == (PlaneMask)0))
783 	planemask = DBTypePlaneMaskTbl[TT_SPACE];
784 
785     return planemask;
786 }
787 
788 /* Wrappers for DBTechNameMask0() */
789 
790 PlaneMask
DBTechNoisyNameMask(layers,mask)791 DBTechNoisyNameMask(layers, mask)
792     char *layers;			/* String to be parsed. */
793     TileTypeBitMask *mask;		/* Where to store the layer mask. */
794 {
795     return DBTechNameMask0(layers, mask, TRUE);
796 }
797 
798 PlaneMask
DBTechNameMask(layers,mask)799 DBTechNameMask(layers, mask)
800     char *layers;			/* String to be parsed. */
801     TileTypeBitMask *mask;		/* Where to store the layer mask. */
802 {
803     return DBTechNameMask0(layers, mask, FALSE);
804 }
805