1 /*
2  * EFbuild.c -
3  *
4  * Procedures for building up the hierarchical representation
5  * of a circuit.  These are all called from efReadDef() in EFread.c.
6  *
7  *     *********************************************************************
8  *     * Copyright (C) 1985, 1990 Regents of the University of California. *
9  *     * Permission to use, copy, modify, and distribute this              *
10  *     * software and its documentation for any purpose and without        *
11  *     * fee is hereby granted, provided that the above copyright          *
12  *     * notice appear in all copies.  The University of California        *
13  *     * makes no representations about the suitability of this            *
14  *     * software for any purpose.  It is provided "as is" without         *
15  *     * express or implied warranty.  Export of this software outside     *
16  *     * of the United States of America may require an export license.    *
17  *     *********************************************************************
18  */
19 
20 #ifndef lint
21 static char rcsid[] __attribute__ ((unused)) = "$Header$";
22 #endif  /* not lint */
23 
24 #include <stdio.h>
25 #include <stdlib.h>		/* for atof() */
26 #include <string.h>
27 
28 #include "utils/magic.h"
29 #include "utils/geometry.h"
30 #include "utils/hash.h"
31 #include "utils/utils.h"
32 #include "utils/malloc.h"
33 #include "tiles/tile.h"
34 #include "database/database.h"	/* for TileType definition */
35 #include "extflat/extflat.h"
36 #include "extflat/EFint.h"
37 #include "extract/extract.h"	/* for device class list */
38 
39 /*
40  * To avoid allocating ridiculously large amounts of memory to hold
41  * transistor types and the names of node types, we maintain the following
42  * string tables.  Each string (transistor type or Magic layername) appears
43  * exactly once in its respective table; each Dev structure's dev_type field
44  * is an index into EFDevTypes[], and each node layer name an index into
45  * EFLayerNames[].
46  */
47 
48 /* The following are ridiculously high */
49 #define	MAXTYPES	100
50 
51 /* Table of transistor types */
52 char *EFDevTypes[TT_MAXTYPES];
53 int   EFDevNumTypes;
54 
55 /* Table of Magic layers */
56 char *EFLayerNames[MAXTYPES] = { "space" };
57 int   EFLayerNumNames;
58 
59 /* Forward declarations */
60 Connection *efAllocConn();
61 EFNode *efBuildDevNode();
62 void efNodeAddName();
63 void efNodeMerge();
64 
65 bool efConnBuildName();
66 bool efConnInitSubs();
67 
68 extern float locScale;
69 
70 
71 /*
72  * ----------------------------------------------------------------------------
73  *
74  * efBuildNode --
75  *
76  * Process a "node" line from a .ext file.
77  * Creates a new node with an initial name of 'nodeName'
78  * and capacitance to substrate 'nodeCap'.  If there is
79  * already a node by the name of 'nodeName', adds 'nodeCap'
80  * to its existing capacitance.
81  *
82  * In addition, the arguments 'av' and 'ac' are an (argv, argc)
83  * vector of pairs of perimeters and areas for each of the
84  * resist classes; these are either stored in the newly created
85  * node, or added to the values already stored in an existing one.
86  *
87  * Results:
88  *	None.
89  *
90  * Side effects:
91  *	Updates the HashTable and node list of 'def'.
92  *
93  * EFNode tables:
94  *	Each hash table of nodes is organized in the following way.
95  *	This organization is true both for the node tables for each
96  *	Def, and for the global table of flattened nodes maintained
97  *	in EFflatten.c (although the flattened nodes use the HierName
98  *	struct for representing hierarchical names efficiently).
99  *
100  *	Each HashEntry points to a EFNodeName struct.  The EFNodeName
101  *	is a link back to the hash key (a HierName), as well as
102  *	a link to the actual EFNode for that name.  The EFNode points
103  *	to the first EFNodeName in the NULL-terminated list of all
104  *	EFNodeNames pointing to that EFNode; the intent is that this
105  *	first EFNodeName is the "official" or highest-precedence
106  *	name for the node.
107  *
108  *	The nodes themselves are linked into a circular, doubly
109  *	linked list, for ease in merging two nodes into a single
110  *	one as a result of a "connect" statement.
111  *
112  *	HashEntries	EFNodeNames	       EFNodes
113  *
114  *			    +---------------+
115  *			    |		    |
116  *			    V		    | to    from
117  *	+-------+	+-------+	    | prev  prev
118  *	|	| ---->	|	|-+ 	    |	^   |
119  *	+-------+	+-------+ | 	    |	|   |
120  *			    |	  | 	    |	|   V
121  *			    V	  | 	+---------------+
122  *	+-------+	+-------+ +--->	|		|
123  *	|	| ---->	|	| ---->	|		|
124  *	+-------+	+-------+ +--->	|		|
125  *			    |	  |	+---------------+
126  *			    V	  |		^   |
127  *	+-------+	+-------+ |		|   |
128  *	|	| ---->	|	|-+		|   V
129  *	+-------+	+-------+	      from  to
130  *			    |		      next  next
131  *			    V
132  *			   NIL
133  *
134  * ----------------------------------------------------------------------------
135  */
136 
137 void
efBuildNode(def,isSubsnode,nodeName,nodeCap,x,y,layerName,av,ac)138 efBuildNode(def, isSubsnode, nodeName, nodeCap, x, y, layerName, av, ac)
139     Def *def;		/* Def to which this connection is to be added */
140     bool isSubsnode;	/* TRUE if the node is the substrate */
141     char *nodeName;	/* One of the names for this node */
142     double nodeCap;	/* Capacitance of this node to ground */
143     int x; int y;	/* Location of a point inside this node */
144     char *layerName;	/* Name of tile type */
145     char **av;		/* Pairs of area, perimeter strings */
146     int ac;		/* Number of strings in av */
147 {
148     EFNodeName *newname;
149     EFNode *newnode;
150     HashEntry *he;
151     unsigned size;
152     int n;
153 
154     he = HashFind(&def->def_nodes, nodeName);
155     if (newname = (EFNodeName *) HashGetValue(he))
156     {
157 	if (efWarn)
158 	    efReadError("Warning: duplicate node name %s\n", nodeName);
159 
160 	/* newnode should exist if newname does.  Having a NULL node	*/
161 	/* may be caused by detached labels "connected" to space.	*/
162 
163 	if ((newnode = newname->efnn_node) != NULL)
164 	{
165 	    /* Just add to C, perim, area of existing node */
166 	    newnode->efnode_cap += (EFCapValue) nodeCap;
167 	    for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2)
168 	    {
169 		newnode->efnode_pa[n].pa_area += atoi(*av++);
170 		newnode->efnode_pa[n].pa_perim += atoi(*av++);
171 	    }
172 
173 	    /* If this node is identified as substrate, ensure that */
174 	    /* the flag is set.					    */
175 	    if (isSubsnode == TRUE)
176 		newnode->efnode_flags |= EF_SUBS_NODE;
177 
178 	    return;
179 	}
180     }
181 
182     if (!newname)
183     {
184 	/* Allocate a new node with 'nodeName' as its single name */
185 	newname = (EFNodeName *) mallocMagic((unsigned)(sizeof (EFNodeName)));
186 	newname->efnn_hier = EFStrToHN((HierName *) NULL, nodeName);
187 	newname->efnn_port = -1;	/* No port assignment */
188 	newname->efnn_refc = 0;		/* Only reference is self */
189 	newname->efnn_next = NULL;
190 	HashSetValue(he, (char *) newname);
191     }
192 
193     /* New node itself */
194     size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (EFPerimArea);
195     newnode = (EFNode *) mallocMagic((unsigned)(size));
196     newnode->efnode_flags = (isSubsnode == TRUE) ? EF_SUBS_NODE : 0;
197     newnode->efnode_cap = nodeCap;
198     newnode->efnode_attrs = (EFAttr *) NULL;
199     newnode->efnode_loc.r_xbot = (int)(0.5 + (float)x * locScale);
200     newnode->efnode_loc.r_ybot = (int)(0.5 + (float)y * locScale);
201     newnode->efnode_loc.r_xtop = newnode->efnode_loc.r_xbot + 1;
202     newnode->efnode_loc.r_ytop = newnode->efnode_loc.r_ybot + 1;
203     newnode->efnode_client = (ClientData) NULL;
204     newnode->efnode_num = 1;
205     if (layerName) newnode->efnode_type =
206 	    efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName);
207     else newnode->efnode_type = 0;
208 
209     for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2)
210     {
211 	newnode->efnode_pa[n].pa_area = atoi(*av++);
212 	newnode->efnode_pa[n].pa_perim = atoi(*av++);
213     }
214     for ( ; n < efNumResistClasses; n++)
215 	newnode->efnode_pa[n].pa_area = newnode->efnode_pa[n].pa_perim = 0;
216 
217     /* Update back pointers */
218     newnode->efnode_name = newname;
219     newname->efnn_node = newnode;
220 
221     /* Link the node into the list for this def */
222     newnode->efnode_next = def->def_firstn.efnode_next;
223     newnode->efnode_prev = (EFNodeHdr *) &def->def_firstn;
224     def->def_firstn.efnode_next->efnhdr_prev = (EFNodeHdr *) newnode;
225     def->def_firstn.efnode_next = (EFNodeHdr *) newnode;
226 
227     /* If isSubsnode was TRUE, then turn off backwards compatibility mode */
228     if (isSubsnode == TRUE) EFCompat = FALSE;
229 }
230 
231 /*
232  * Process a "subcap" line by adding the specified adjustment
233  * value to the indicated node's substrate capacitance.
234  */
235 
236 void
efAdjustSubCap(def,nodeName,nodeCapAdjust)237 efAdjustSubCap(def, nodeName, nodeCapAdjust)
238     Def *def;			/* Def to which this connection is to be added */
239     char *nodeName;		/* One of the names for this node */
240     double nodeCapAdjust;	/* Substrate capacitance adjustment */
241 {
242     EFNodeName *nodename;
243     EFNode *node;
244     HashEntry *he;
245 
246     he = HashLookOnly(&def->def_nodes, nodeName);
247     if (he && (nodename = (EFNodeName *) HashGetValue(he)))
248     {
249 	node = nodename->efnn_node;
250 	node->efnode_cap += (EFCapValue) nodeCapAdjust;
251 	return;
252     }
253     else
254     {
255 	if (efWarn)
256 	    efReadError("Error: subcap has unknown node %s\n", nodeName);
257     }
258 }
259 
260 /*
261  * ----------------------------------------------------------------------------
262  *
263  * efBuildAttr --
264  *
265  * Prepend another node attribute to the list for node 'nodeName'.
266  * The attribute is located at the coordinates given by 'r' and
267  * is on the layer 'layerName'.  The text of the attribute is 'text'.
268  *
269  * Results:
270  *	None.
271  *
272  * Side effects:
273  *	See above.
274  *
275  * ----------------------------------------------------------------------------
276  */
277 
278 void
efBuildAttr(def,nodeName,r,layerName,text)279 efBuildAttr(def, nodeName, r, layerName, text)
280     Def *def;
281     char *nodeName;
282     Rect *r;
283     char *layerName;
284     char *text;
285 {
286     HashEntry *he;
287     EFNodeName *nn;
288     EFAttr *ap;
289     int size;
290 
291     he = HashLookOnly(&def->def_nodes, nodeName);
292     if (he == NULL || HashGetValue(he) == NULL)
293     {
294 	efReadError("Attribute for nonexistent node %s ignored\n", nodeName);
295 	return;
296     }
297     nn = (EFNodeName *) HashGetValue(he);
298 
299     size = ATTRSIZE(strlen(text));
300     ap = (EFAttr *) mallocMagic((unsigned)(size));
301     (void) strcpy(ap->efa_text, text);
302     ap->efa_type =
303 	efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName);
304     ap->efa_loc = *r;
305     ap->efa_next = nn->efnn_node->efnode_attrs;
306     nn->efnn_node->efnode_attrs = ap;
307 }
308 
309 /*
310  * ----------------------------------------------------------------------------
311  *
312  * efBuildDist --
313  *
314  * Process a "dist" line from a .ext file.
315  * Both of the names driver and receiver are pathnames with slashes.
316  * Add a new Distance record to the hash table for Def, or update
317  * an existing Distance record.
318  *
319  * This strategy allows the .ext file to contain several distance
320  * lines for the same pair of points; we do the compression here
321  * rather than requiring it be done during extraction.  It's necessary
322  * to do compression at some point before flattening; see the description
323  * in efFlatDists().
324  *
325  * Results:
326  *	None.
327  *
328  * Side effects:
329  *	See above.
330  *
331  * ----------------------------------------------------------------------------
332  */
333 
334 void
efBuildDist(def,driver,receiver,min,max)335 efBuildDist(def, driver, receiver, min, max)
336     Def *def;		/* Def for which we're adding a new Distance */
337     char *driver;	/* Source terminal */
338     char *receiver;	/* Destination terminal */
339     int min, max;	/* Minimum and maximum acyclic distance from source
340 			 * to destination.
341 			 */
342 {
343     Distance *dist, distKey;
344     HierName *hn1, *hn2;
345     HashEntry *he;
346 
347     hn1 = EFStrToHN((HierName *) NULL, driver);
348     hn2 = EFStrToHN((HierName *) NULL, receiver);
349     distKey.dist_min = min;
350     distKey.dist_max = max;
351     if (EFHNBest(hn1, hn2))
352     {
353 	distKey.dist_1 = hn1;
354 	distKey.dist_2 = hn2;
355     }
356     else
357     {
358 	distKey.dist_1 = hn2;
359 	distKey.dist_2 = hn1;
360     }
361 #ifdef	notdef
362     TxError("ADD %s ", EFHNToStr(distKey.dist_1));
363     TxError("%s ", EFHNToStr(distKey.dist_2));
364     TxError("%d %d\n", min, max);
365 #endif	/* notdef */
366 
367     he = HashFind(&def->def_dists, (char *) &distKey);
368     if (dist = (Distance *) HashGetValue(he))
369     {
370 	/*
371 	 * There was already an entry in the table; update it
372 	 * to reflect new minimum and maximum distances.  We
373 	 * can free the keys since they were already in the
374 	 * table.
375 	 */
376 	dist->dist_min = MIN(dist->dist_min, min);
377 	dist->dist_max = MAX(dist->dist_max, max);
378 	EFHNFree(hn1, (HierName *) NULL, HN_ALLOC);
379 	EFHNFree(hn2, (HierName *) NULL, HN_ALLOC);
380     }
381     else
382     {
383 	/*
384 	 * When the key was installed in the hash table, it was
385 	 * a copy of the Distance 'distKey'.  Leave this as the
386 	 * value of the HashEntry.
387 	 */
388 	HashSetValue(he, (ClientData) he->h_key.h_ptr);
389     }
390 }
391 
392 /*
393  * ----------------------------------------------------------------------------
394  *
395  * efBuildKill --
396  *
397  * Process a "killnode" line from a .ext file.
398  * Prepends a Kill to the list for def.
399  *
400  * Results:
401  *	None.
402  *
403  * Side effects:
404  *	See above.
405  *
406  * ----------------------------------------------------------------------------
407  */
408 
409 void
efBuildKill(def,name)410 efBuildKill(def, name)
411     Def *def;		/* Def for which we're adding a new Kill */
412     char *name;		/* Name of node to die */
413 {
414     Kill *kill;
415 
416     kill = (Kill *) mallocMagic((unsigned)(sizeof (Kill)));
417     kill->kill_name = EFStrToHN((HierName *) NULL, name);
418     kill->kill_next = def->def_kills;
419     def->def_kills = kill;
420 }
421 
422 /*
423  * ----------------------------------------------------------------------------
424  *
425  * efBuildEquiv --
426  *
427  * Process an "equiv" line from a .ext file.
428  * One of the names 'nodeName1' or 'nodeName2' should be a name for
429  * an existing node in the def 'def'.  We simply prepend this name to
430  * the list of names for that node.
431  *
432  * Results:
433  *	None.
434  *
435  * Side effects:
436  *	See above.
437  *
438  * ----------------------------------------------------------------------------
439  */
440 
441 void
efBuildEquiv(def,nodeName1,nodeName2)442 efBuildEquiv(def, nodeName1, nodeName2)
443     Def *def;		/* Def for which we're adding a new node name */
444     char *nodeName1;	/* One of node names to be made equivalent */
445     char *nodeName2;	/* Other name to be made equivalent.  One of nodeName1
446 			 * or nodeName2 must already be known.
447 			 */
448 {
449     EFNodeName *nn1, *nn2;
450     HashEntry *he1, *he2;
451 
452     /* Look up both names in the hash table for this def */
453     he1 = HashFind(&def->def_nodes, nodeName1);
454     he2 = HashFind(&def->def_nodes, nodeName2);
455 
456     nn1 = (EFNodeName *) HashGetValue(he1);
457     nn2 = (EFNodeName *) HashGetValue(he2);
458 
459     if (nn1 == nn2) return;	/* These nodes already merged */
460 
461     if (nn2 == (EFNodeName *) NULL)
462     {
463 	/* Create nodeName1 if it doesn't exist */
464 	if (nn1 == (EFNodeName *) NULL)
465 	{
466 	    if (efWarn)
467 		efReadError("Creating new node %s\n", nodeName1);
468 	    efBuildNode(def, FALSE,
469 		    nodeName1, (double)0, 0, 0,
470 		    (char *) NULL, (char **) NULL, 0);
471 	    nn1 = (EFNodeName *) HashGetValue(he1);
472 	}
473 
474 	/* Make nodeName2 be another alias for node1 */
475 	efNodeAddName(nn1->efnn_node, he2,
476 			EFStrToHN((HierName *) NULL, nodeName2));
477 	return;
478     }
479     else if (nn2->efnn_node == (EFNode *)NULL)
480 	return;		/* Repeated "equiv" statement */
481 
482     /* If both names exist and are for different ports, then keep   */
483     /* them separate and add a zero ohm resistor or a zero volt	    */
484     /* source between them, based on the method set by "ext2spice   */
485     /* shorts".							    */
486 
487     if (nn1 && nn2 && (nn1->efnn_port >= 0) && (nn2->efnn_port >= 0) &&
488 	    (nn1->efnn_port != nn2->efnn_port))
489     {
490 	if ((EFOutputFlags & EF_SHORT_MASK) != EF_SHORT_NONE)
491 	{
492 	    int i;
493 	    int sdev;
494 	    char *argv[10], zeroarg[] = "0";
495 
496 	    if ((EFOutputFlags & EF_SHORT_MASK) == EF_SHORT_R)
497 		sdev = DEV_RES;
498 	    else
499 		sdev = DEV_VOLT;
500 
501 	    for (i = 0; i < 10; i++) argv[i] = zeroarg;
502 	    argv[0] = StrDup((char **)NULL, "0.0");
503 	    argv[1] = StrDup((char **)NULL, "dummy");
504 	    argv[4] = StrDup((char **)NULL, nodeName1);
505 	    argv[7] = StrDup((char **)NULL, nodeName2);
506 	    efBuildDevice(def, sdev, "None", &GeoNullRect, 10, argv);
507 	    freeMagic(argv[0]);
508 	    freeMagic(argv[1]);
509 	    freeMagic(argv[4]);
510 	    freeMagic(argv[7]);
511 	    return;
512 	}
513 	else
514 	{
515 	    /* Flag a strong warning */
516 	    TxError("Warning:  Ports \"%s\" and \"%s\" are electrically shorted.\n",
517 			nodeName1, nodeName2);
518 	}
519     }
520 
521     /* If both names exist and are for different nodes, merge them */
522     if (nn1)
523     {
524 	if (nn1->efnn_node == (EFNode *)NULL)
525 	    return;		/* Repeated "equiv" statement */
526 	if (nn1->efnn_node != nn2->efnn_node)
527 	{
528 	    struct efnode *node1 = nn1->efnn_node;
529 	    struct efnode *node2 = nn2->efnn_node;
530     	    HashSearch hs;
531 
532 	    if (efWarn)
533 		efReadError("Merged nodes %s and %s\n", nodeName1, nodeName2);
534 	    efNodeMerge(&nn1->efnn_node, &nn2->efnn_node);
535 	    if (nn1->efnn_port > 0) nn2->efnn_port = nn1->efnn_port;
536 	    else if (nn2->efnn_port > 0) nn1->efnn_port = nn2->efnn_port;
537 
538 	    /* If a node has been merged away, make sure that its name	*/
539 	    /* and all aliases point to the merged name's hash.		*/
540 
541 	    if (nn1->efnn_node == NULL)
542 	    {
543 		nn2->efnn_refc += nn1->efnn_refc + 1;
544     		HashStartSearch(&hs);
545     		while (he1 = HashNext(&def->def_nodes, &hs))
546 		    if ((EFNodeName *)HashGetValue(he1) == nn1)
547 			HashSetValue(he1, (char *)nn2);
548 	    }
549 	    else if (nn2->efnn_node == NULL)
550 	    {
551 		nn1->efnn_refc += nn2->efnn_refc + 1;
552     		HashStartSearch(&hs);
553     		while (he2 = HashNext(&def->def_nodes, &hs))
554 		    if ((EFNodeName *)HashGetValue(he2) == nn2)
555 			HashSetValue(he2, (char *)nn1);
556 	    }
557 	}
558 	return;
559     }
560 
561     /* Make nodeName1 be another alias for node2 */
562     efNodeAddName(nn2->efnn_node, he1,
563 			EFStrToHN((HierName *) NULL, nodeName1));
564 }
565 
566 
567 /*
568  * ----------------------------------------------------------------------------
569  *
570  *
571  * ----------------------------------------------------------------------------
572  */
573 
574 DevParam *
efGetDeviceParams(name)575 efGetDeviceParams(name)
576     char *name;
577 {
578     HashEntry *he;
579     DevParam *plist = NULL;
580 
581     he = HashLookOnly(&efDevParamTable, (char *)name);
582     if (he != NULL)
583 	plist = (DevParam *)HashGetValue(he);
584     return plist;
585 }
586 
587 /*
588  * ----------------------------------------------------------------------------
589  *
590  * efBuildDeviceParams --
591  *
592  * Fill in a device parameter hash table entry from a "parameters" line in
593  * the .ext file.
594  *
595  * ----------------------------------------------------------------------------
596  */
597 
598 void
efBuildDeviceParams(name,argc,argv)599 efBuildDeviceParams(name, argc, argv)
600     char *name;
601     int argc;
602     char *argv[];
603 {
604     HashEntry *he;
605     DevParam *plist = NULL, *newparm;
606     char *pptr;
607     int n;
608 
609     he = HashFind(&efDevParamTable, name);
610     plist = (DevParam *)HashGetValue(he);
611     if (plist != NULL) return;			/* Already got one! */
612 
613     /* Parse arguments for each parameter */
614     for (n = 0; n < argc; n++)
615     {
616 	char *mult;
617 
618 	pptr = strchr(argv[n], '=');
619 	if (pptr == NULL)
620 	{
621 	    efReadError("Bad parameter assignment \"%s\" for device \"%s\"\n",
622 			argv[n], name);
623 	    continue;
624 	}
625 	newparm = (DevParam *)mallocMagic(sizeof(DevParam));
626 	newparm->parm_type[0] = *argv[n];
627 	if ((pptr - argv[n]) == 1)
628 	    newparm->parm_type[1] = '\0';
629 	else
630 	    newparm->parm_type[1] = *(argv[n] + 1);
631 
632 	if ((mult = strchr(pptr + 1, '*')) != NULL)
633 	{
634 	    *mult = '\0';
635 	    newparm->parm_scale = atof(mult + 1);
636 	}
637 	else
638 	    newparm->parm_scale = 1.0;
639 
640 	// For parameters defined for cell defs, copy the whole
641 	// expression verbatim into parm_name.  parm_type is
642 	// reassigned to be a numerical order.
643 
644 	if (name[0] == ':')
645 	{
646 	    newparm->parm_name = StrDup((char **)NULL, argv[n]);
647 	    newparm->parm_type[0] = '0' + n / 10;
648 	    newparm->parm_type[1] = '0' + n % 10;
649 	}
650 	else
651 	    newparm->parm_name = StrDup((char **)NULL, pptr + 1);
652 	newparm->parm_next = plist;
653 	plist = newparm;
654     }
655     HashSetValue(he, (char *)plist);
656 }
657 
658 /*
659  * ----------------------------------------------------------------------------
660  *
661  * efBuildDevice --
662  *
663  * Process a device line from a .ext file.
664  * The number of terminals in the dev is argc/3 (which must be integral).
665  * Each block of 3 strings in argv describes a single terminal; see the
666  * comments below for their interpretation.
667  *
668  * Results:
669  *	Returns 0 on success, 1 on failure to parse any terminal's values
670  *
671  * Side effects:
672  *	Prepends this dev to the list for the def 'def'.
673  *
674  * ----------------------------------------------------------------------------
675  */
676 
677 int
efBuildDevice(def,class,type,r,argc,argv)678 efBuildDevice(def, class, type, r, argc, argv)
679     Def *def;		/* Def to which this connection is to be added */
680     char class;		/* Class (dev, bjt, etc.) of this device */
681     char *type;		/* Type (name) of this device */
682     Rect *r;		/* Coordinates of 1x1 rectangle entirely inside device */
683     int argc;		/* Size of argv */
684     char *argv[];	/* Tokens for the rest of the dev line.
685 			 * Starts with the last two position values, used to
686 			 * hash the device record.  The next arguments depend
687 			 * on the type of device.  The rest are taken in groups
688 			 * of 3, one for each terminal.  Each group of 3 consists
689 			 * of the node name to which the terminal connects, the
690 			 * length of the terminal, and an attribute list (or the
691 			 * token 0).
692 			 */
693 {
694     int n, nterminals, pn;
695     HashEntry *he;
696     DevTerm *term;
697     Dev *newdev, devtmp;
698     DevParam *newparm, *devp, *sparm;
699     TileType ttype;
700     int dev_type;
701     char ptype, *pptr, **av;
702     char devhash[64];
703     int argstart = 1;	/* start of terminal list in argv[] */
704     bool hasModel = strcmp(type, "None") ? TRUE : FALSE;
705 
706     int area, perim;	/* Total area, perimeter of primary type (i.e., channel) */
707 
708     newdev = (Dev *)NULL;
709     devtmp.dev_subsnode = NULL;
710     devtmp.dev_cap = 0.0;
711     devtmp.dev_res = 0.0;
712     devtmp.dev_area = 0;
713     devtmp.dev_perim = 0;
714     devtmp.dev_length = 0;
715     devtmp.dev_width = 0;
716     devtmp.dev_params = NULL;
717 
718     switch (class)
719     {
720 	case DEV_FET:
721 	case DEV_MOSFET:
722 	case DEV_ASYMMETRIC:
723 	case DEV_BJT:
724 	    argstart = 3;
725 	    break;
726 	case DEV_DIODE:
727 	case DEV_NDIODE:
728 	case DEV_PDIODE:
729 	    argstart = 0;
730 	    break;
731 	case DEV_RES:
732 	case DEV_CAP:
733 	case DEV_CAPREV:
734 	    if (hasModel)
735 		argstart = 2;
736 	    break;
737 	case DEV_SUBCKT:
738 	case DEV_MSUBCKT:
739 	case DEV_RSUBCKT:
740 	case DEV_CSUBCKT:
741 	    argstart = 0;
742     }
743 
744     devp = efGetDeviceParams(type);
745 
746     /* Parse initial arguments for parameters */
747     while ((pptr = strchr(argv[argstart], '=')) != NULL)
748     {
749 	// Check if this parameter is in the table.
750 	// If so, handle appropriately.  Otherwise, the
751 	// parameter gets saved verbatim locally.  The
752 	// "parameters" line comes before any "device" line
753 	// in the .ext file, so the table should be complete.
754 
755 	*pptr = '\0';
756 	for (sparm = devp; sparm; sparm = sparm->parm_next)
757 	    if (!strcasecmp(sparm->parm_type, argv[argstart]))
758 		break;
759 	*pptr = '=';
760 	if (sparm == NULL)
761 	{
762 	    /* Copy the parameter into dev_params */
763 	    /* (parm_type and parm_scale records are not used) */
764 	    newparm = (DevParam *)mallocMagic(sizeof(DevParam));
765 	    newparm->parm_name = StrDup((char **)NULL, argv[argstart]);
766 	    newparm->parm_next = devtmp.dev_params;
767 	    devtmp.dev_params = newparm;
768 	    argstart++;
769 	    continue;
770 	}
771 
772 	pptr++;
773 	switch(*argv[argstart])
774 	{
775 	    case 'a':
776 		if ((pptr - argv[argstart]) == 2)
777 		    devtmp.dev_area = atoi(pptr);
778 		else
779 		{
780 		    pn = *(argv[argstart] + 1) - '0';
781 		    if (pn == 0)
782 			devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
783 				* locScale * locScale);
784 		    /* Otherwise, punt */
785 		}
786 		break;
787 	    case 'p':
788 		if ((pptr - argv[argstart]) == 2)
789 		    devtmp.dev_perim = atoi(pptr);
790 		else
791 		{
792 		    pn = *(argv[argstart] + 1) - '0';
793 		    if (pn == 0)
794 			devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
795 		    /* Otherwise, use verbatim */
796 		}
797 		break;
798 	    case 'l':
799 		devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
800 		break;
801 	    case 'w':
802 		devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
803 		break;
804 	    case 'c':
805 		devtmp.dev_cap = (float)atof(pptr);
806 		break;
807 	    case 'r':
808 		devtmp.dev_res = (float)atof(pptr);
809 		break;
810 	}
811 	argstart++;
812     }
813 
814     /* Check for optional substrate node */
815     switch (class)
816     {
817 	case DEV_RES:
818 	case DEV_CAP:
819 	case DEV_CAPREV:
820 	case DEV_RSUBCKT:
821 	case DEV_CSUBCKT:
822 	case DEV_MSUBCKT:
823 	case DEV_SUBCKT:
824 	case DEV_DIODE:
825 	case DEV_NDIODE:
826 	case DEV_PDIODE:
827 	    n = argc - argstart;
828 	    if ((n % 3) == 1)
829 	    {
830 		if (strncmp(argv[argstart], "None", 4) != 0)
831 		    devtmp.dev_subsnode = efBuildDevNode(def, argv[argstart], TRUE);
832 
833 		argstart++;
834 	    }
835 	    break;
836     }
837 
838     /* Between argstart and argc, we should only have terminal triples */
839     if (((argc - argstart) % 3) != 0)
840 	return 1;
841 
842     nterminals = (argc - argstart) / 3;
843 
844     dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, type);
845 
846     /* Determine if this device has been seen before */
847     /* NOTE:  This is done by tile type, not name, because the extresist
848      * device extraction is less sophisticated than the standard extraction
849      * and does not differentiate between different device names belonging
850      * to the same tile type.  The extGetDevType() function is not efficient,
851      * and all of this needs to be done better.
852      */
853 
854     ttype = extGetDevType(type);
855     if (ttype < 0)
856     {
857 	/* For zero-ohm resistors used to separate ports on the same	*/
858 	/* net, generate a unique devhash.				*/
859 	ttype = DBNumTypes;
860 	while (1)
861 	{
862 	    sprintf(devhash, "%dx%d_%d", r->r_xbot, r->r_ybot, ttype);
863 	    he = HashLookOnly(&def->def_devs, devhash);
864 	    if (he == NULL) break;
865 	    ttype++;
866 	}
867     }
868 
869     sprintf(devhash, "%dx%d_%d", r->r_xbot, r->r_ybot, ttype);
870     he = HashFind(&def->def_devs, devhash);
871     newdev = (Dev *)HashGetValue(he);
872 
873     if (newdev)
874     {
875 	/* Duplicate device.  Duplicates will only appear in res.ext files
876 	 * where a device has nodes changed.  Merge all properties of the
877 	 * original device with nodes from the new device.  Keep the
878 	 * original device and discard the new one.
879 	 *
880 	 * Check that the device is actually the same device type and number
881 	 * of terminals.  If not, throw an error and abandon the new device.
882 	 *
883 	 * NOTE:  Quick check is made on dev_type, but for the reason stated
884 	 * above for the calculation of ttype, only the tile types need to
885 	 * match, so make an additional (expensive) check on tile type.
886 	 */
887 
888         if ((newdev->dev_class != class) || ((newdev->dev_type != dev_type)
889 		 && (ttype != extGetDevType(EFDevTypes[newdev->dev_type]))))
890 	{
891 	    TxError("Device %s %s at (%d, %d) overlaps incompatible device %s %s!\n",
892 		    extDevTable[class], type, r->r_xbot, r->r_ybot,
893 		    extDevTable[newdev->dev_class], EFDevTypes[newdev->dev_type]);
894 	    return 0;
895 	}
896         else if (newdev->dev_nterm != nterminals)
897 	{
898 	    TxError("Device %s %s at (%d, %d) overlaps device with incompatible"
899 		    " number of terminals (%d vs. %d)!\n",
900 		    extDevTable[class], type, r->r_xbot, r->r_ybot, nterminals,
901 		    newdev->dev_nterm);
902 	    return 0;
903 	}
904     }
905     else
906     {
907 	newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals));
908 
909 	/* Add this dev to the hash table for def */
910 	HashSetValue(he, (ClientData)newdev);
911 
912         newdev->dev_cap = devtmp.dev_cap;
913         newdev->dev_res = devtmp.dev_res;
914         newdev->dev_area = devtmp.dev_area;
915         newdev->dev_perim = devtmp.dev_perim;
916         newdev->dev_length = devtmp.dev_length;
917         newdev->dev_width = devtmp.dev_width;
918         newdev->dev_params = devtmp.dev_params;
919 
920         newdev->dev_nterm = nterminals;
921         newdev->dev_rect = *r;
922         newdev->dev_type = dev_type;
923         newdev->dev_class = class;
924 
925         switch (class)
926         {
927 	    case DEV_FET:		/* old-style "fet" record */
928 		newdev->dev_area = atoi(argv[0]);
929 		newdev->dev_perim = atoi(argv[1]);
930 		break;
931 	    case DEV_MOSFET:	/* new-style "device mosfet" record */
932 	    case DEV_ASYMMETRIC:
933 	    case DEV_BJT:
934 		newdev->dev_length = atoi(argv[0]);
935 		newdev->dev_width = atoi(argv[1]);
936 		break;
937 	    case DEV_RES:
938 		if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
939 		{
940 		    newdev->dev_length = atoi(argv[0]);
941 		    newdev->dev_width = atoi(argv[1]);
942 		}
943 		else if (StrIsNumeric(argv[0]))
944 		{
945 		    newdev->dev_res = (float)atof(argv[0]);
946 		}
947 		else
948 		{
949 		    if (hasModel)
950 		    {
951 			efReadError("Error: expected L and W, got %s %s\n", argv[0],
952 				argv[1]);
953 			newdev->dev_length = 0;
954 			newdev->dev_width = 0;
955 		    }
956 		    else
957 		    {
958 			efReadError("Error: expected resistance value, got %s\n",
959 				    argv[0]);
960 			newdev->dev_res = 0.0;
961 		    }
962 		}
963 		break;
964 	    case DEV_CAP:
965 	    case DEV_CAPREV:
966 		if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
967 		{
968 		    newdev->dev_length = atoi(argv[0]);
969 		    newdev->dev_width = atoi(argv[1]);
970 		}
971 		else if (StrIsNumeric(argv[0]))
972 		{
973 		    newdev->dev_cap = (float)atof(argv[0]);
974 		}
975 		else
976 		{
977 		    if (hasModel)
978 		    {
979 			efReadError("Error: expected L and W, got %s %s\n", argv[0],
980 				argv[1]);
981 			newdev->dev_length = 0;
982 			newdev->dev_width = 0;
983 		    }
984 		    else
985 		    {
986 			efReadError("Error: expected capacitance value, got %s\n",
987 					    argv[0]);
988 			newdev->dev_cap = 0.0;
989 		    }
990 		}
991 		break;
992 	}
993     }
994 
995     newdev->dev_subsnode = devtmp.dev_subsnode;
996     switch (class)
997     {
998 	case DEV_FET:		/* old-style "fet" record */
999 	    newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
1000 	    break;
1001 	case DEV_MOSFET:	/* new-style "device mosfet" record */
1002 	case DEV_ASYMMETRIC:
1003 	case DEV_BJT:
1004 	    /* "None" in the place of the substrate name means substrate is ignored */
1005 	    if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
1006 		newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
1007 	    break;
1008 	case DEV_RES:
1009 	    if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
1010 		newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
1011 
1012 	    break;
1013 	case DEV_CAP:
1014 	case DEV_CAPREV:
1015 	    if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
1016 		newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
1017 
1018 	    break;
1019     }
1020 
1021 #define	TERM_NAME	0
1022 #define	TERM_PERIM	1
1023 #define	TERM_ATTRS	2
1024 
1025     for (av = &argv[argstart], n = 0; n < nterminals; n++, av += 3)
1026     {
1027 	term = &newdev->dev_terms[n];
1028 	term->dterm_node = efBuildDevNode(def, av[TERM_NAME], FALSE);
1029 	term->dterm_length = atoi(av[TERM_PERIM]);
1030 	term->dterm_area = 0;
1031 	term->dterm_perim = 0;
1032 
1033 	/* If the attr list is '0', this signifies no attributes */
1034 	if (av[TERM_ATTRS][0] == '0' && av[TERM_ATTRS][1] == '\0')
1035 	    term->dterm_attrs = (char *) NULL;
1036 	else
1037 	    term->dterm_attrs = StrDup((char **) NULL, av[TERM_ATTRS]);
1038     }
1039 
1040 #undef	TERM_NAME
1041 #undef	TERM_PERIM
1042 #undef	TERM_ATTRS
1043 
1044     return 0;
1045 }
1046 
1047 /*
1048  * ----------------------------------------------------------------------------
1049  *
1050  * efBuildPortNode --
1051  *
1052  *	Look for the node named 'name' in the local table for 'def', or in
1053  *	the global node name table.  If it doesn't already exist, create a
1054  *	EFNode for it, and set capacitance and area/perimeter to zero.
1055  *	Set the efnode_flags value to EF_PORT, with the port number encoded
1056  *	in the efNodeName structure.
1057  *
1058  * ----------------------------------------------------------------------------
1059  */
1060 
1061 void
efBuildPortNode(def,name,idx,x,y,layername,toplevel)1062 efBuildPortNode(def, name, idx, x, y, layername, toplevel)
1063     Def *def;		/* Def to which this connection is to be added */
1064     char *name;		/* One of the names for this node */
1065     int idx;		/* Port number (order) */
1066     int x; int y;	/* Location of a point inside this node */
1067     char *layername;	/* Name of tile type */
1068     bool toplevel;	/* 1 if the cell def is the top level cell */
1069 {
1070     HashEntry *he;
1071     EFNodeName *nn;
1072 
1073     he = HashFind(&def->def_nodes, name);
1074     nn = (EFNodeName *) HashGetValue(he);
1075     if (nn == (EFNodeName *) NULL)
1076     {
1077 	/* Create node if it doesn't already exist */
1078 	efBuildNode(def, FALSE, name, (double)0, x, y,
1079 			layername, (char **) NULL, 0);
1080 
1081 	nn = (EFNodeName *) HashGetValue(he);
1082     }
1083     if (nn != (EFNodeName *) NULL)
1084     {
1085 	nn->efnn_node->efnode_flags |= EF_PORT;
1086 	if (toplevel)
1087 	    nn->efnn_node->efnode_flags |= EF_TOP_PORT;
1088 	nn->efnn_port = idx;
1089     }
1090 }
1091 
1092 /*
1093  * ----------------------------------------------------------------------------
1094  *
1095  * EFGetPortMax --
1096  *
1097  * Find the highest port number in the cell def and return the value.
1098  *
1099  * Results:
1100  *	Value of highest port number in the cell def's node list
1101  *
1102  * Side effects:
1103  *	Larger value including the implicit ports is placed in the
1104  *	location of the pointer imp_max.
1105  *
1106  * ----------------------------------------------------------------------------
1107  */
1108 
1109 int
EFGetPortMax(def,imp_max)1110 EFGetPortMax(def, imp_max)
1111    Def *def;
1112    int *imp_max;
1113 {
1114     EFNode *snode;
1115     EFNodeName *nodeName;
1116     int portmax, portorder;
1117 
1118     portmax = -1;
1119     if (imp_max) *imp_max = -1;
1120 
1121     for (snode = (EFNode *) def->def_firstn.efnode_next;
1122                 snode != &def->def_firstn;
1123                 snode = (EFNode *) snode->efnode_next)
1124     {
1125         if (snode->efnode_flags & EF_PORT)
1126 	{
1127 	    for (nodeName = snode->efnode_name; nodeName != NULL; nodeName =
1128                         nodeName->efnn_next)
1129 	    {
1130 		portorder = nodeName->efnn_port;
1131 		if (portorder > portmax) portmax = portorder;
1132 	    }
1133 	}
1134         else if (imp_max && (snode->efnode_flags & EF_SUBS_PORT))
1135 	{
1136 	    nodeName = snode->efnode_name;
1137 	    portorder = nodeName->efnn_port;
1138 	    if (portorder > (*imp_max)) (*imp_max) = portorder;
1139 	}
1140     }
1141     if (imp_max)
1142 	if (portmax > (*imp_max)) (*imp_max) = portmax;
1143     return portmax;
1144 }
1145 
1146 /*
1147  * ----------------------------------------------------------------------------
1148  *
1149  * efBuildDevNode --
1150  *
1151  * Look for the node named 'name' in the local table for 'def', or
1152  * in the global node name table.  If it doesn't already exist,
1153  * create a EFNode for it.  If 'isSubsNode' is TRUE, this is node
1154  * is a substrate node and may not exist yet; otherwise, the node
1155  * must already exist.
1156  *
1157  * Results:
1158  *	Returns a pointer to the EFNode for 'name'.
1159  *
1160  * Side effects:
1161  *	May create a new node, as per above.
1162  *
1163  * ----------------------------------------------------------------------------
1164  */
1165 
1166 EFNode *
efBuildDevNode(def,name,isSubsNode)1167 efBuildDevNode(def, name, isSubsNode)
1168     Def *def;
1169     char *name;
1170     bool isSubsNode;
1171 {
1172     HashEntry *he;
1173     EFNodeName *nn;
1174     bool isNewNode = FALSE;
1175 
1176     he = HashFind(&def->def_nodes, name);
1177     nn = (EFNodeName *) HashGetValue(he);
1178     if (nn == (EFNodeName *) NULL)
1179     {
1180 	/* Create node if it doesn't already exist */
1181 	if (efWarn && !isSubsNode)
1182 	    efReadError("Node %s doesn't exist so creating it\n", name);
1183 	efBuildNode(def, isSubsNode, name, (double)0, 0, 0,
1184 		(char *) NULL, (char **) NULL, 0);
1185 
1186 	nn = (EFNodeName *) HashGetValue(he);
1187 	isNewNode = TRUE;
1188     }
1189     if (isSubsNode)
1190     {
1191 	if (!EFHNIsGlob(nn->efnn_hier))
1192 	{
1193 	    /* This node is declared to be an implicit port */
1194 	    nn->efnn_node->efnode_flags |= EF_SUBS_PORT;
1195 	    nn->efnn_port = -1;
1196 	    def->def_flags |= DEF_SUBSNODES;
1197 	}
1198 	nn->efnn_node->efnode_flags |= EF_SUBS_NODE;
1199 	if (isNewNode)
1200 	    nn->efnn_node->efnode_flags |= EF_DEVTERM;
1201     }
1202     return nn->efnn_node;
1203 }
1204 
1205 /*
1206  * ----------------------------------------------------------------------------
1207  *
1208  * efBuildAddStr --
1209  *
1210  * Return the index of 'str' in 'table'.
1211  * Add the string 'str' to the table 'table' if it's not already there.
1212  *
1213  * Results:
1214  *	See above.
1215  *
1216  * Side effects:
1217  *	Increments *pMax if we add an entry to the table.
1218  *
1219  * ----------------------------------------------------------------------------
1220  */
1221 
1222 int
efBuildAddStr(table,pMax,size,str)1223 efBuildAddStr(table, pMax, size, str)
1224     char *table[];	/* Table to search */
1225     int *pMax;		/* Increment this if we add an entry */
1226     int size;		/* Maximum size of table */
1227     char *str;		/* String to add */
1228 {
1229     int n, max;
1230 
1231     max = *pMax;
1232     for (n = 0; n < max; n++)
1233 	if (strcmp(table[n], str) == 0)
1234 	    return n;
1235 
1236     if (max >= size)
1237     {
1238 	printf("Too many entries in table (max is %d) to add %s\n", size, str);
1239 	printf("Recompile libextflat.a with a bigger table size\n");
1240 	exit (1);
1241     }
1242 
1243     table[n++] = StrDup((char **) NULL, str);
1244     *pMax = n;
1245 
1246     return max;
1247 }
1248 
1249 /*
1250  * ----------------------------------------------------------------------------
1251  *
1252  * efBuildUse --
1253  *
1254  * Process a "use" line from a .ext file.
1255  * Creates a new use by the name 'subUseId' of the def named 'subDefName'.
1256  * If 'subDefName' doesn't exist, it is created, but left marked as
1257  * unavailable so that readfile() will read it in after it is done
1258  * with this file.  If 'subUseId' ends in an array subscript, e.g,
1259  *	useid[xlo:xhi:xsep][ylo:yhi:ysep]
1260  * its ArrayInfo is filled in from this information; otherwise, its
1261  * ArrayInfo is marked as not being needed (xlo == xhi, ylo == yhi).
1262  *
1263  * Results:
1264  *	None.
1265  *
1266  * Side effects:
1267  *	See above.
1268  *
1269  * ----------------------------------------------------------------------------
1270  */
1271 
1272 void
efBuildUse(def,subDefName,subUseId,ta,tb,tc,td,te,tf)1273 efBuildUse(def, subDefName, subUseId, ta, tb, tc, td, te, tf)
1274     Def *def;		/* Def to which this connection is to be added */
1275     char *subDefName;	/* Def of which this a use */
1276     char *subUseId;	/* Use identifier for the def 'subDefName' */
1277     int ta, tb, tc,
1278 	td, te, tf;	/* Elements of a transform from coordinates of
1279 			 * subDefName up to def.
1280 			 */
1281 {
1282     Use *newuse;
1283     Def *newdef;
1284     char *cp;
1285     HashEntry *he;
1286 
1287     newdef = efDefLook(subDefName);
1288     if (newdef == NULL)
1289 	newdef = efDefNew(subDefName);
1290 
1291     newuse = (Use *) mallocMagic((unsigned)(sizeof (Use)));
1292     newuse->use_def = newdef;
1293     newuse->use_trans.t_a = ta;
1294     newuse->use_trans.t_b = tb;
1295     newuse->use_trans.t_c = tc;
1296     newuse->use_trans.t_d = td;
1297     newuse->use_trans.t_e = te;
1298     newuse->use_trans.t_f = tf;
1299 
1300     /* Set the use identifier and array information */
1301     if ((cp = strchr(subUseId, '[')) == NULL)
1302     {
1303 	newuse->use_id = StrDup((char **) NULL, subUseId);
1304 	newuse->use_xlo = newuse->use_xhi = 0;
1305 	newuse->use_ylo = newuse->use_yhi = 0;
1306 	newuse->use_xsep = newuse->use_ysep = 0;
1307     }
1308     else
1309     {
1310 	/* Note: Preserve any use of brackets as-is other than the  */
1311 	/* standard magic array notation below.  This allows, for   */
1312 	/* example, verilog instance arrays read from DEF files	to  */
1313 	/* be passed through correctly.				    */
1314 
1315 	if ((sscanf(cp, "[%d:%d:%d][%d:%d:%d]",
1316 		    &newuse->use_xlo, &newuse->use_xhi, &newuse->use_xsep,
1317 		    &newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep)) == 6)
1318 	{
1319 	    *cp = '\0';
1320 	    newuse->use_id = StrDup((char **) NULL, subUseId);
1321 	    *cp = '[';
1322 	}
1323 	else
1324 	{
1325 	    newuse->use_id = StrDup((char **) NULL, subUseId);
1326 	    newuse->use_xlo = newuse->use_xhi = 0;
1327 	    newuse->use_ylo = newuse->use_yhi = 0;
1328 	    newuse->use_xsep = newuse->use_ysep = 0;
1329 	}
1330     }
1331 
1332     he = HashFind(&def->def_uses, newuse->use_id);
1333     if (HashGetValue(he))
1334         TxError("Warning: use %s appears more than once in def!\n", newuse->use_id);
1335     HashSetValue(he, (ClientData)newuse);
1336 }
1337 
1338 /*
1339  * ----------------------------------------------------------------------------
1340  *
1341  * efBuildConnect --
1342  *
1343  * Process a "connect" line from a .ext file.
1344  * Creates a connection record for the names 'nodeName1' and
1345  * 'nodeName2'.
1346  *
1347  * Results:
1348  *	None.
1349  *
1350  * Side effects:
1351  *	Allocates a new connection record, and prepends it to the
1352  *	list for def.
1353  *
1354  * ----------------------------------------------------------------------------
1355  */
1356 
1357 void
efBuildConnect(def,nodeName1,nodeName2,deltaC,av,ac)1358 efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
1359     Def *def;		/* Def to which this connection is to be added */
1360     char *nodeName1;	/* Name of first node in connection */
1361     char *nodeName2;	/* Name of other node in connection */
1362     double deltaC;	/* Adjustment in capacitance */
1363     char **av;		/* Strings for area, perimeter adjustment */
1364     int ac;		/* Number of strings in av */
1365 {
1366     int n;
1367     Connection *conn;
1368     unsigned size = sizeof (Connection)
1369 		    + (efNumResistClasses - 1) * sizeof (EFPerimArea);
1370 
1371     conn = (Connection *) mallocMagic((unsigned)(size));
1372 
1373     if (efConnInitSubs(conn, nodeName1, nodeName2))
1374     {
1375 	conn->conn_cap = (EFCapValue) deltaC;
1376 	conn->conn_next = def->def_conns;
1377 	for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2)
1378 	{
1379 	    conn->conn_pa[n].pa_area = (int)(0.5 + (float)atoi(*av++)
1380 		    * locScale * locScale);
1381 	    conn->conn_pa[n].pa_perim = (int)(0.5 + (float)atoi(*av++) * locScale);
1382 	}
1383 	for ( ; n < efNumResistClasses; n++)
1384 	    conn->conn_pa[n].pa_area = conn->conn_pa[n].pa_perim = 0;
1385 	def->def_conns = conn;
1386     }
1387 }
1388 
1389 /*
1390  * ----------------------------------------------------------------------------
1391  *
1392  * efBuildResistor --
1393  *
1394  * Process a "resistor" line from a .ext file.
1395  * Creates a resistor record for the names 'nodeName1' and
1396  * 'nodeName2'.  Both 'nodeName1' and 'nodeName2' must be non-NULL.
1397  *
1398  * Results:
1399  *	None.
1400  *
1401  * Side effects:
1402  *	Allocates a new connection record, and prepends it to the
1403  *	def_resistors list for def.
1404  *
1405  * ----------------------------------------------------------------------------
1406  */
1407 
1408 void
efBuildResistor(def,nodeName1,nodeName2,resistance)1409 efBuildResistor(def, nodeName1, nodeName2, resistance)
1410     Def *def;		/* Def to which this connection is to be added */
1411     char *nodeName1;	/* Name of first node in resistor */
1412     char *nodeName2;	/* Name of second node in resistor */
1413     int resistance;	/* Resistor value */
1414 {
1415     Connection *conn;
1416 
1417     conn = (Connection *) mallocMagic((unsigned)(sizeof (Connection)));
1418     if (efConnInitSubs(conn, nodeName1, nodeName2))
1419     {
1420 	conn->conn_res = (float)resistance;
1421 	conn->conn_next = def->def_resistors;
1422 	def->def_resistors = conn;
1423     }
1424 }
1425 
1426 /*
1427  * ----------------------------------------------------------------------------
1428  *
1429  * efBuildCap --
1430  *
1431  * Process a "cap" line from a .ext file.
1432  * Creates a capacitor record for the names 'nodeName1' and
1433  * 'nodeName2'.  Both 'nodeName1' and 'nodeName2' must be non-NULL.
1434  *
1435  * Results:
1436  *	None.
1437  *
1438  * Side effects:
1439  *	Allocates a new connection record, and prepends it to the
1440  *	def_caps list for def.
1441  *
1442  * ----------------------------------------------------------------------------
1443  */
1444 
1445 void
efBuildCap(def,nodeName1,nodeName2,cap)1446 efBuildCap(def, nodeName1, nodeName2, cap)
1447     Def *def;		/* Def to which this connection is to be added */
1448     char *nodeName1;	/* Name of first node in capacitor */
1449     char *nodeName2;	/* Name of second node in capacitor */
1450     double cap;		/* Capacitor value */
1451 {
1452     Connection *conn;
1453 
1454     conn = (Connection *) mallocMagic((unsigned)(sizeof (Connection)));
1455     if (efConnInitSubs(conn, nodeName1, nodeName2))
1456     {
1457 	conn->conn_cap = (EFCapValue) cap;
1458 	conn->conn_next = def->def_caps;
1459 	def->def_caps = conn;
1460     }
1461 }
1462 
1463 /*
1464  * ----------------------------------------------------------------------------
1465  *
1466  * efConnInitSubs --
1467  *
1468  * Fill in and check the subscript information for the newly allocated
1469  * Connection 'conn'.
1470  *
1471  * Results:
1472  *	Returns TRUE if successful, FALSE on error.
1473  *
1474  * Side effects:
1475  *	Fills in the two ConnNames conn->conn_1 and conn->conn_2.
1476  *	Frees 'conn' in the event of an error.
1477  *
1478  * ----------------------------------------------------------------------------
1479  */
1480 
1481 bool
efConnInitSubs(conn,nodeName1,nodeName2)1482 efConnInitSubs(conn, nodeName1, nodeName2)
1483     Connection *conn;
1484     char *nodeName1, *nodeName2;
1485 {
1486     ConnName *c1, *c2;
1487     int n;
1488 
1489     c1 = &conn->conn_1;
1490     c2 = &conn->conn_2;
1491     if (!efConnBuildName(c1, nodeName1) || !efConnBuildName(c2, nodeName2))
1492 	goto bad;
1493 
1494     if (c1->cn_nsubs != c2->cn_nsubs)
1495     {
1496 	efReadError("Number of subscripts doesn't match\n");
1497 	goto bad;
1498     }
1499 
1500     for (n = 0; n < c1->cn_nsubs; n++)
1501     {
1502 	if (c1->cn_subs[n].r_hi - c1->cn_subs[n].r_lo
1503 		!= c2->cn_subs[n].r_hi - c2->cn_subs[n].r_lo)
1504 	{
1505 	    efReadError("Subscript %d range mismatch\n", n);
1506 	    goto bad;
1507 	}
1508     }
1509     return TRUE;
1510 
1511 bad:
1512     if (c1->cn_name) freeMagic((char *) c1->cn_name);
1513     if (c2->cn_name) freeMagic((char *) c2->cn_name);
1514     freeMagic((char *) conn);
1515     return FALSE;
1516 }
1517 
1518 /*
1519  * ----------------------------------------------------------------------------
1520  *
1521  * efConnBuildName --
1522  *
1523  * Fill in the fields of 'cnp' from the string 'name'.
1524  * If 'name' contains no trailing subscript ranges (which are
1525  * of the form [lo1:hi1] or [lo1:hi1,lo2:hi2], or [lo1:hi1][lo2:hi2] for
1526  * compatibility with older versions of Magic), we set cnp->cn_nsubs
1527  * to zero and cnp->cn_name to a copy of 'name'.  Otherwise, we decode
1528  * the subscripts and fill in cnp->cn_subs and cnp->cn_nsubs appropriately.
1529  *
1530  * Results:
1531  *	Returns TRUE if successful, FALSE on error.
1532  *
1533  * Side effects:
1534  *	Fills in the fields of the ConnName 'cnp'.
1535  *
1536  * ----------------------------------------------------------------------------
1537  */
1538 
1539 bool
efConnBuildName(cnp,name)1540 efConnBuildName(cnp, name)
1541     ConnName *cnp;
1542     char *name;
1543 {
1544     char *srcp, *dstp, *cp, *dp;
1545     int nsubs;
1546     Range *rp;
1547     char newname[1024];
1548     char c;
1549 
1550     cnp->cn_nsubs = 0;
1551     if (name == NULL)
1552     {
1553 	cnp->cn_name = NULL;
1554 	return TRUE;
1555     }
1556 
1557     cp = name;
1558     /* Make sure it's an array subscript range before treating it specially */
1559 again:
1560     if ((cp = strchr(cp, '[')) == NULL)
1561     {
1562 	cnp->cn_name = StrDup((char **) NULL, name);
1563 	return TRUE;
1564     }
1565     for (dp = cp + 1; *dp && *dp != ':'; dp++)
1566     {
1567 	if (*dp == ']')
1568 	{
1569 	    cp = dp+1;
1570 	    goto again;
1571 	}
1572     }
1573 
1574     /* Copy the initial part of the name */
1575     for (srcp = name, dstp = newname; srcp < cp; *dstp++ = *srcp++)
1576 	/* Nothing */;
1577 
1578     /* Replace each subscript range with %d */
1579     for (nsubs = 0, rp = cnp->cn_subs; (c = *cp) == '[' || c == ','; nsubs++)
1580     {
1581 	if (nsubs >= MAXSUBS)
1582 	{
1583 	    efReadError("Too many array subscripts (maximum=2)\n");
1584 	    return FALSE;
1585 	}
1586 	if (sscanf(++cp, "%d:%d", &rp[nsubs].r_lo, &rp[nsubs].r_hi) != 2)
1587 	{
1588 	    efReadError("Subscript syntax error\n");
1589 	    return FALSE;
1590 	}
1591 	if (rp[nsubs].r_lo > rp[nsubs].r_hi)
1592 	{
1593 	    efReadError("Backwards subscript range [%d:%d]\n",
1594 			rp[nsubs].r_lo, rp[nsubs].r_hi);
1595 	    return FALSE;
1596 	}
1597 
1598 	while (*cp && *cp != ']' && *cp != ',')
1599 	    cp++;
1600 	if (*cp == ']') cp++;
1601     }
1602 
1603     /* Generate format for sprintf */
1604     *dstp++ = '[';
1605     *dstp++ = '%';
1606     *dstp++ = 'd';
1607     if (nsubs == 2)
1608     {
1609 	*dstp++ = ',';
1610 	*dstp++ = '%';
1611 	*dstp++ = 'd';
1612     }
1613     *dstp++ = ']';
1614 
1615     /* Copy remainder of path */
1616     while (*dstp++ = *cp++)
1617 	/* Nothing */;
1618 
1619     cnp->cn_name = StrDup((char **) NULL, newname);
1620     cnp->cn_nsubs = nsubs;
1621     return TRUE;
1622 }
1623 
1624 /*
1625  * ----------------------------------------------------------------------------
1626  *
1627  * efNodeAddName --
1628  *
1629  * Add a name to the list for 'node'.
1630  * We already have a HashEntry for the new name.
1631  * The new name is added to the front of the list
1632  * for 'node' only if it is higher in precedence
1633  * than the name already at the front of the list.
1634  * Sets the value of 'he' to be the newly allocated
1635  * EFNodeName.
1636  *
1637  * Results:
1638  *	None.
1639  *
1640  * Side effects:
1641  *	See above.
1642  *
1643  * ----------------------------------------------------------------------------
1644  */
1645 
1646 void
efNodeAddName(node,he,hn)1647 efNodeAddName(node, he, hn)
1648     EFNode *node;
1649     HashEntry *he;
1650     HierName *hn;
1651 {
1652     EFNodeName *newnn;
1653     EFNodeName *oldnn;
1654     bool topport;	// New node to add is a top-level port
1655 
1656     newnn = (EFNodeName *) mallocMagic((unsigned)(sizeof (EFNodeName)));
1657     newnn->efnn_node = node;
1658     newnn->efnn_hier = hn;
1659     newnn->efnn_port = -1;
1660     newnn->efnn_refc = 0;
1661     HashSetValue(he, (char *) newnn);
1662 
1663     /* If the node is a port of the top level cell, denoted by flag	*/
1664     /* EF_TOP_PORT, then the name given to the port always stays at the	*/
1665     /* head of the list.						*/
1666 
1667     topport = (node->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
1668 
1669     /* Link in the new name */
1670     oldnn = node->efnode_name;
1671     if (oldnn == NULL || (EFHNBest(newnn->efnn_hier, oldnn->efnn_hier) && !topport))
1672     {
1673 	/* New head of list */
1674 	newnn->efnn_next = oldnn;
1675 	node->efnode_name = newnn;
1676     }
1677     else
1678     {
1679 	/* Link it in behind the head of the list */
1680 	newnn->efnn_next = oldnn->efnn_next;
1681 	oldnn->efnn_next = newnn;
1682     }
1683 }
1684 
1685 /*
1686  * ----------------------------------------------------------------------------
1687  *
1688  * efNodeMerge --
1689  *
1690  * Combine two nodes.  The resistances and capacitances are summed.
1691  * The attribute lists are appended.  The location chosen is the
1692  * lower-leftmost, with lowest being considered before leftmost.
1693  * The canonical name of the new node is taken to be the highest
1694  * precedence among the names for all nodes.
1695  *
1696  * One of the nodes will no longer be referenced, so we arbitrarily
1697  * make this node2 and free its memory.
1698  *
1699  * Results:
1700  *	Return 0 if node1 has precedence, 1 if node2 has precedence
1701  *
1702  * Side effects:
1703  *	See above.
1704  *
1705  * ----------------------------------------------------------------------------
1706  */
1707 
1708 void
efNodeMerge(node1ptr,node2ptr)1709 efNodeMerge(node1ptr, node2ptr)
1710     EFNode **node1ptr, **node2ptr;	/* Pointers to hierarchical nodes */
1711 {
1712     EFNodeName *nn, *nnlast;
1713     EFAttr *ap;
1714     int n;
1715     EFNode *keeping, *removing;
1716 
1717     /* Sanity check: ignore if same node */
1718     if (*node1ptr == *node2ptr)
1719 	return;
1720 
1721     /* Keep the node with the greater number of entries, and merge  */
1722     /* the node with fewer entries into it.			    */
1723 
1724     if ((*node1ptr)->efnode_num >= (*node2ptr)->efnode_num)
1725     {
1726 	keeping = *node1ptr;
1727 	removing = *node2ptr;
1728     }
1729     else
1730     {
1731 	keeping = *node2ptr;
1732 	removing = *node1ptr;
1733     }
1734 
1735     if (efWatchNodes)
1736     {
1737 	if (HashLookOnly(&efWatchTable, (char *) keeping->efnode_name->efnn_hier)
1738 	    || (removing->efnode_name
1739 		&& HashLookOnly(&efWatchTable,
1740 				(char *) removing->efnode_name->efnn_hier)))
1741 	{
1742 	    printf("\ncombine: %s\n",
1743 		EFHNToStr(keeping->efnode_name->efnn_hier));
1744 	    printf("  with   %s\n\n",
1745 		removing->efnode_name
1746 		    ? EFHNToStr(removing->efnode_name->efnn_hier)
1747 		    : "(unnamed)");
1748 	}
1749     }
1750 
1751     /* Sum capacitances, perimeters, areas */
1752     keeping->efnode_cap += removing->efnode_cap;
1753     for (n = 0; n < efNumResistClasses; n++)
1754     {
1755 	keeping->efnode_pa[n].pa_area += removing->efnode_pa[n].pa_area;
1756 	keeping->efnode_pa[n].pa_perim += removing->efnode_pa[n].pa_perim;
1757     }
1758 
1759     /* Make all EFNodeNames point to "keeping" */
1760     if (removing->efnode_name)
1761     {
1762 	bool topportk, topportr;
1763 
1764 	for (nn = removing->efnode_name; nn; nn = nn->efnn_next)
1765 	{
1766 	    nnlast = nn;
1767 	    nn->efnn_node = keeping;
1768 	}
1769 
1770 	topportk = (keeping->efnode_flags & EF_TOP_PORT) ?  TRUE : FALSE;
1771 	topportr = (removing->efnode_flags & EF_TOP_PORT) ?  TRUE : FALSE;
1772 
1773 	/* Concatenate list of EFNodeNames, taking into account precedence */
1774 	if ((!keeping->efnode_name) || (!topportk && (topportr
1775 		    || EFHNBest(removing->efnode_name->efnn_hier,
1776 		     keeping->efnode_name->efnn_hier))))
1777 	{
1778 	    /*
1779 	     * New official name is that of "removing".
1780 	     * The new list of names is:
1781 	     *	removing-names, keeping-names
1782 	     */
1783 	    nnlast->efnn_next = keeping->efnode_name;
1784 	    keeping->efnode_name = removing->efnode_name;
1785 
1786 	    /*
1787 	     * Choose the new location only if "removing"'s location is a valid one,
1788 	     * i.e, "removing" wasn't created before it was mentioned.  This is mainly
1789 	     * to deal with new fets, resistors, and capacitors created by resistance
1790 	     * extraction, which appear with their full hierarchical names in the
1791 	     * .ext file for the root cell.
1792 	     *
1793 	     * This code has been moved up from below so that the original
1794 	     * location and type will be prefered when the original name
1795 	     * is preferred.
1796 	     *
1797 	     * I am purposefully subverting the original specification that
1798 	     * the node refer to the bottom corner of the network.  Does
1799 	     * this have any effect on exttosim or exttospice?
1800 	     *
1801 	     *					Tim, 6/14/04
1802 	     */
1803 	    if (removing->efnode_type > 0)
1804 	    {
1805 		keeping->efnode_loc = removing->efnode_loc;
1806 		keeping->efnode_type = removing->efnode_type;
1807 	    }
1808 	}
1809 	else
1810 	{
1811 	    /*
1812 	     * Keep old official name.
1813 	     * The new list of names is:
1814 	     *	keeping-names[0], removing-names, keeping-names[1-]
1815 	     */
1816 	    nnlast->efnn_next = keeping->efnode_name->efnn_next;
1817 	    keeping->efnode_name->efnn_next = removing->efnode_name;
1818 	}
1819     }
1820 
1821     /* Merge list counts */
1822     keeping->efnode_num += removing->efnode_num;
1823 
1824     /* Merge attribute lists */
1825     if (ap = removing->efnode_attrs)
1826     {
1827 	while (ap->efa_next)
1828 	    ap = ap->efa_next;
1829 	ap->efa_next = keeping->efnode_attrs;
1830 	keeping->efnode_attrs = ap;
1831 	removing->efnode_attrs = (EFAttr *) NULL;	/* Sanity */
1832     }
1833 
1834     /* Unlink "removing" from list for def */
1835     removing->efnode_prev->efnhdr_next = removing->efnode_next;
1836     removing->efnode_next->efnhdr_prev = removing->efnode_prev;
1837 
1838     /*
1839      * Only if both nodes were EF_DEVTERM do we keep EF_DEVTERM set
1840      * in the resultant node.
1841      */
1842     if ((removing->efnode_flags & EF_DEVTERM) == 0)
1843 	keeping->efnode_flags &= ~EF_DEVTERM;
1844 
1845     /*
1846      * If "removing" has the EF_PORT flag set, then copy the port
1847      * record in the flags to node1.
1848      */
1849     if (removing->efnode_flags & EF_PORT)
1850 	keeping->efnode_flags |= EF_PORT;
1851     if (removing->efnode_flags & EF_TOP_PORT)
1852 	keeping->efnode_flags |= EF_TOP_PORT;
1853     if (removing->efnode_flags & EF_SUBS_PORT)
1854 	keeping->efnode_flags |= EF_SUBS_PORT;
1855 
1856     /*
1857      * If "removing" has the EF_SUBS_NODE flag set, then copy the port
1858      * record in the flags to "keeping".
1859      */
1860     if (removing->efnode_flags & EF_SUBS_NODE)
1861 	keeping->efnode_flags |= EF_SUBS_NODE;
1862 
1863     /* Get rid of "removing" */
1864     freeMagic((char *) removing);
1865 
1866     /* Make sure that the active node is always node1 */
1867     *node1ptr = keeping;
1868     *node2ptr = (EFNode *)NULL;	    /* Sanity check */
1869 }
1870 
1871 
1872 /*
1873  * ----------------------------------------------------------------------------
1874  *
1875  * efFreeUseTable --
1876  *
1877  * Free the cell IDs allocated for each entry in the use hash table, and
1878  * the memory allocated by the cell use, leaving the hash entry null.
1879  *
1880  * ----------------------------------------------------------------------------
1881  */
1882 
1883 void
efFreeUseTable(table)1884 efFreeUseTable(table)
1885     HashTable *table;
1886 {
1887     HashSearch hs;
1888     HashEntry *he;
1889     Use *use;
1890     HierName *hn;
1891     EFNodeName *nn;
1892 
1893     HashStartSearch(&hs);
1894     while (he = HashNext(table, &hs))
1895 	if (use = (Use *) HashGetValue(he))
1896 	{
1897 	    if (use->use_id != NULL) freeMagic((char *)use->use_id);
1898 	    freeMagic(use);
1899 	}
1900 }
1901 
1902 /*
1903  * ----------------------------------------------------------------------------
1904  *
1905  * efFreeDevTable --
1906  *
1907  * Free the device records allocated for each entry in the device hash table,
1908  * the memory allocated by the device, leaving the hash entry null.
1909  *
1910  * ----------------------------------------------------------------------------
1911  */
1912 
1913 void
efFreeDevTable(table)1914 efFreeDevTable(table)
1915     HashTable *table;
1916 {
1917     Dev *dev;
1918     HashSearch hs;
1919     HashEntry *he;
1920     int n;
1921 
1922     HashStartSearch(&hs);
1923     while (he = HashNext(table, &hs))
1924     {
1925 	dev = (Dev *)HashGetValue(he);
1926 	for (n = 0; n < (int)dev->dev_nterm; n++)
1927 	    if (dev->dev_terms[n].dterm_attrs)
1928 		freeMagic((char *) dev->dev_terms[n].dterm_attrs);
1929 	freeMagic((char *) dev);
1930     }
1931 }
1932 
1933 /*
1934  * ----------------------------------------------------------------------------
1935  *
1936  * efFreeNodeTable --
1937  *
1938  * Free the EFNodeNames (and the HierNames they point to) pointed to by
1939  * the entries in the HashTable 'table'.  Each EFNodeName is assumed to
1940  * be pointed to by exactly one HashEntry, but each HierName can be
1941  * pointed to by many entries (some of which may be in other HashTables).
1942  * As a result, the HierNames aren't freed here; instead, an entry is
1943  * added to efFreeHashTable for each HierName encountered.  Everything
1944  * is then freed at the end by EFDone().
1945  *
1946  * Results:
1947  *	None.
1948  *
1949  * Side effects:
1950  *	Frees memory.
1951  *	Adds an entry to hnTable for each HierName.
1952  *
1953  * ----------------------------------------------------------------------------
1954  */
1955 
1956 void
efFreeNodeTable(table)1957 efFreeNodeTable(table)
1958     HashTable *table;
1959 {
1960     HashSearch hs;
1961     HashEntry *he;
1962     HierName *hn;
1963     EFNodeName *nn;
1964 
1965     HashStartSearch(&hs);
1966     while (he = HashNext(table, &hs))
1967 	if (nn = (EFNodeName *) HashGetValue(he))
1968 	{
1969 	    for (hn = nn->efnn_hier; hn; hn = hn->hn_parent)
1970 		(void) HashFind(&efFreeHashTable, (char *) hn);
1971 
1972 	    /* Node equivalences made by "equiv" statements are	handled	*/
1973 	    /* by reference count.  Don't free the node structure until	*/
1974 	    /* all references have been seen.				*/
1975 
1976 	    if (nn->efnn_refc > 0)
1977 		nn->efnn_refc--;
1978 	    else
1979 		freeMagic((char *) nn);
1980 	}
1981 }
1982 
1983 /*
1984  * ----------------------------------------------------------------------------
1985  *
1986  * efFreeNodeList --
1987  *
1988  * Free the circular list of nodes of which 'head' is the head.
1989  * Don't free 'head' itself, since it's statically allocated.
1990  *
1991  * If the client (e.g., ext2spice, ext2sim, ...) allocates memory for a
1992  * node, then that client needs to provide a function "func" of the form:
1993  *
1994  *              int func(client)
1995  *		    ClientData client;
1996  *		{
1997  *		}
1998  *
1999  * The return value is unused but should be zero for consistency.
2000  *
2001  * Results:
2002  *	None.
2003  *
2004  * Side effects:
2005  *	Frees memory.  Calls func() to free additional memory allocated
2006  *	in the node structure by a client.
2007  *
2008  * ----------------------------------------------------------------------------
2009  */
2010 
2011 void
efFreeNodeList(head,func)2012 efFreeNodeList(head, func)
2013     EFNode *head;
2014     int (*func)();
2015 {
2016     EFNode *node;
2017     EFAttr *ap;
2018 
2019     for (node = (EFNode *) head->efnode_next;
2020 	    node != head;
2021 	    node = (EFNode *) node->efnode_next)
2022     {
2023 	for (ap = node->efnode_attrs; ap; ap = ap->efa_next)
2024 	    freeMagic((char *) ap);
2025 	if (node->efnode_client != (ClientData)NULL)
2026 	{
2027 	    if (func != NULL)
2028 		(*func)(node->efnode_client);
2029 	    freeMagic((char *)node->efnode_client);
2030 	}
2031 	freeMagic((char *) node);
2032     }
2033 }
2034 
2035 /*
2036  * ----------------------------------------------------------------------------
2037  *
2038  * efFreeConn --
2039  *
2040  * Free the Connection *conn.
2041  *
2042  * Results:
2043  *	None.
2044  *
2045  * Side effects:
2046  *	Frees memory.
2047  *
2048  * ----------------------------------------------------------------------------
2049  */
2050 
2051 void
efFreeConn(conn)2052 efFreeConn(conn)
2053     Connection *conn;
2054 {
2055     if (conn->conn_name1) freeMagic(conn->conn_name1);
2056     if (conn->conn_name2) freeMagic(conn->conn_name2);
2057     freeMagic((char *) conn);
2058 }
2059