Compare commits

..

No commits in common. "master" and "8.3.584" have entirely different histories.

4 changed files with 110 additions and 247 deletions

View File

@ -1 +1 @@
8.3.587 8.3.584

View File

@ -27,7 +27,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/magic.h" #include "utils/magic.h"
#include "textio/textio.h" #include "textio/textio.h"
#include "utils/malloc.h"
#include "utils/signals.h" #include "utils/signals.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "tiles/tile.h" #include "tiles/tile.h"
@ -38,12 +37,18 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "commands/commands.h" #include "commands/commands.h"
#include "utils/undo.h" #include "utils/undo.h"
/* The variables below are made global so that they can be used to /* The variables below are made owns so that they can be used to
* pass information to the various search functions. * pass information to the various search functions.
*/ */
static Rect drcSubIntArea; /* Accumulates area of interactions. */
static CellDef *drcSubDef; /* Cell definition we're checking. */
static int drcSubRadius; /* Interaction radius. */
static CellUse *drcCurSub; /* Holds current use while searching for interactions */
static Rect drcSubLookArea; /* Area where we're looking for interactions */
static void (*drcSubFunc)(); /* Error function. */ static void (*drcSubFunc)(); /* Error function. */
static ClientData drcSubClientData; /* To be passed to error function. */ static ClientData drcSubClientData;
/* To be passed to error function. */
/* The cookie below is dummied up to provide an error message for /* The cookie below is dummied up to provide an error message for
* errors that occur because of inexact overlaps between subcells. * errors that occur because of inexact overlaps between subcells.
@ -87,28 +92,6 @@ static DRCCookie drcOffGridCookie = {
extern int DRCErrorType; extern int DRCErrorType;
extern CellDef *DRCErrorDef; extern CellDef *DRCErrorDef;
/* Structure used to hold information about child uses found in the
* search area during DRCFindInteractions(), so these can be
* subsequently searched for sibling interactions.
*/
struct drcLinkedUse {
CellUse *dlu_use; // Use being checked
Rect dlu_area; // Area of use to check (w/halo)
struct drcLinkedUse *dlu_next; // For linked list
};
/* Structure used to pass information to and from drcSubcellFunc() */
struct drcSubcellArg {
CellDef *dsa_def; /* Cell use being checked */
int dsa_radius; /* Halo radius around area to check */
Rect *dsa_searchArea; /* Area of cell use being searched */
Rect *dsa_intArea; /* Total interaction area */
bool dsa_found; /* At least one interacting cell was found */
struct drcLinkedUse *dsa_dlu;
};
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -130,12 +113,12 @@ struct drcSubcellArg {
*/ */
int int
drcFindOtherCells(use, dlu) drcFindOtherCells(use, area)
CellUse *use; CellUse *use;
struct drcLinkedUse *dlu; Rect *area;
{ {
if (use != dlu->dlu_use) if (use != drcCurSub)
GeoInclude(&use->cu_bbox, &dlu->dlu_area); GeoInclude(&use->cu_bbox, area);
return 0; return 0;
} }
@ -245,56 +228,68 @@ drcSubCopyFunc(scx, cdarg)
*/ */
int int
drcSubcellFunc(subUse, dsa) drcSubcellFunc(subUse, flags)
CellUse *subUse; /* Subcell instance found in area. */ CellUse *subUse; /* Subcell instance. */
struct drcSubcellArg *dsa; /* Information needed for funtion and to pass int *flags; /* Information to propagate up */
* back to the caller.
*/
{ {
Rect area, haloArea, intArea; Rect area, haloArea, intArea, subIntArea, locIntArea;
int i; int i;
/* Record that a subcell has been seen in the search area. */ /* A subcell has been seen, so set the "cell found" flag */
dsa->dsa_found = TRUE; *flags |= CELLFOUND_FLAG;
/* To determine interactions, find the bounding box of /* To determine interactions, find the bounding box of
* all paint and other subcells within one halo of this * all paint and other subcells within one halo of this
* subcell (and also within the original area where * subcell (and also within the original area where
* we're recomputing errors). * we're recomputing errors).
*/ */
area = subUse->cu_bbox; area = subUse->cu_bbox;
GEO_EXPAND(&area, dsa->dsa_radius, &haloArea); GEO_EXPAND(&area, drcSubRadius, &haloArea);
GeoClip(&haloArea, dsa->dsa_searchArea); GeoClip(&haloArea, &drcSubLookArea);
intArea = GeoNullRect; intArea = GeoNullRect;
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++) for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
{ {
(void) DBSrPaintArea((Tile *) NULL, dsa->dsa_def->cd_planes[i], (void) DBSrPaintArea((Tile *) NULL, drcSubDef->cd_planes[i],
&haloArea, &DBAllButSpaceBits, drcIncludeArea, &haloArea, &DBAllButSpaceBits, drcIncludeArea,
(ClientData) &intArea); (ClientData) &intArea);
} }
/* To check sibling interactions, DBSrCellPlaneArea() must not be /* DRC error tiles in a subcell are automatically pulled into the */
* called from within itself, so save the information about this /* interaction area of the parent. Ultimately this is recursive as */
* cell and its area in a linked list. If haloArea is already /* all cells are checked and errors propagate to the top level. */
* inside intArea, then do nothing.
*/
if (!GEO_SURROUND(&intArea, &haloArea)) subIntArea = GeoNullRect;
{
struct drcLinkedUse *newdlu; #if (0)
newdlu = (struct drcLinkedUse *)mallocMagic(sizeof(struct drcLinkedUse)); /* NOTE: DRC errors inside a subcell should be ignored for */
newdlu->dlu_use = subUse; /* the purpose of finding interactions. Errors should only */
newdlu->dlu_area = haloArea; /* be copied up into the parent when in a non-interaction */
newdlu->dlu_next = dsa->dsa_dlu; /* area. This is done below in DRCFindInteractions(). */
dsa->dsa_dlu = newdlu; /* (Method added by Tim, 10/15/2020) */
}
/* Maybe S and PS errors should be pulled here? */
DBSrPaintArea((Tile *) NULL, subUse->cu_def->cd_planes[PL_DRC_ERROR],
&TiPlaneRect, &DBAllButSpaceBits, drcIncludeArea,
(ClientData) &subIntArea);
GeoTransRect(&(subUse->cu_transform), &subIntArea, &locIntArea);
GeoInclude(&locIntArea, &intArea);
#endif
if (!GEO_RECTNULL(&subIntArea)) *flags |= PROPAGATE_FLAG;
drcCurSub = subUse;
(void) DBSrCellPlaneArea(drcSubDef->cd_cellPlane, &haloArea,
drcFindOtherCells, (ClientData)(&intArea));
if (GEO_RECTNULL(&intArea)) return 0; if (GEO_RECTNULL(&intArea)) return 0;
GEO_EXPAND(&intArea, dsa->dsa_radius, &intArea); GEO_EXPAND(&intArea, drcSubRadius, &intArea);
GeoClip(&intArea, &haloArea); GeoClip(&intArea, &haloArea);
(void) GeoInclude(&intArea, dsa->dsa_intArea); (void) GeoInclude(&intArea, &drcSubIntArea);
return 0; return 0;
} }
@ -418,11 +413,10 @@ DRCFindInteractions(def, area, radius, interaction)
int i; int i;
CellUse *use; CellUse *use;
SearchContext scx; SearchContext scx;
Rect searchArea, intArea;
int flags; int flags;
struct drcSubcellArg dsa;
struct drcLinkedUse *curDLU;
drcSubDef = def;
drcSubRadius = radius;
DRCDummyUse->cu_def = def; DRCDummyUse->cu_def = def;
/* Find all the interactions in the area and compute the /* Find all the interactions in the area and compute the
@ -432,53 +426,11 @@ DRCFindInteractions(def, area, radius, interaction)
* each cell has material everywhere within its bounding box. * each cell has material everywhere within its bounding box.
*/ */
GEO_EXPAND(area, radius, &searchArea); drcSubIntArea = GeoNullRect;
intArea = GeoNullRect; GEO_EXPAND(area, radius, &drcSubLookArea);
flags = 0;
/* Copy drcSubLookArea to a local Rect structure because it (void) DBSrCellPlaneArea(def->cd_cellPlane, &drcSubLookArea,
* gets modified by drcSubcellFunc(). drcSubcellFunc, (ClientData)(&flags));
*/
dsa.dsa_def = def;
dsa.dsa_radius = radius;
dsa.dsa_searchArea = &searchArea;
dsa.dsa_intArea = &intArea;
dsa.dsa_found = FALSE;
dsa.dsa_dlu = (struct drcLinkedUse *)NULL;
(void) DBSrCellPlaneArea(def->cd_cellPlane, &searchArea,
drcSubcellFunc, (ClientData)&dsa);
/* If no subcells were in the search area, there is nothing
* more to do.
*/
if (dsa.dsa_found == FALSE) return -1;
/* If drcSubcellFunc() returned a list of uses, then check
* the area of each use for interacting sibling uses, and
* add the overlap to the potential interaction area.
*/
curDLU = dsa.dsa_dlu;
while (curDLU != NULL)
{
Rect subIntArea, subSearchArea;
struct drcLinkedUse *nextdlu = curDLU->dlu_next;
subSearchArea = curDLU->dlu_area;
curDLU->dlu_area = GeoNullRect;
(void) DBSrCellPlaneArea(def->cd_cellPlane, &subSearchArea,
drcFindOtherCells, (ClientData)curDLU);
/* Re-clip interaction area to subcell halo area */
GEO_EXPAND(&curDLU->dlu_area, radius, &curDLU->dlu_area);
GeoClip(&curDLU->dlu_area, &subSearchArea);
(void) GeoInclude(&curDLU->dlu_area, &intArea);
/* Free entry and move to next entry in linked list */
freeMagic((char *)curDLU);
curDLU = nextdlu;
}
/* If there seems to be an interaction area, make a second pass /* If there seems to be an interaction area, make a second pass
* to make sure there's more than one cell with paint in the * to make sure there's more than one cell with paint in the
@ -486,7 +438,8 @@ DRCFindInteractions(def, area, radius, interaction)
* have overlapping bounding boxes without overlapping paint. * have overlapping bounding boxes without overlapping paint.
*/ */
if (GEO_RECTNULL(&intArea)) return 0; if (!(flags & CELLFOUND_FLAG)) return -1;
if (GEO_RECTNULL(&drcSubIntArea)) return 0;
use = NULL; use = NULL;
/* If errors are being propagated up from child to parent, */ /* If errors are being propagated up from child to parent, */
@ -497,7 +450,7 @@ DRCFindInteractions(def, area, radius, interaction)
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++) for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
{ {
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[i], if (DBSrPaintArea((Tile *) NULL, def->cd_planes[i],
&intArea, &DBAllButSpaceBits, drcAlwaysOne, &drcSubIntArea, &DBAllButSpaceBits, drcAlwaysOne,
(ClientData) NULL) != 0) (ClientData) NULL) != 0)
{ {
use = (CellUse *) -1; use = (CellUse *) -1;
@ -506,14 +459,14 @@ DRCFindInteractions(def, area, radius, interaction)
} }
scx.scx_use = DRCDummyUse; scx.scx_use = DRCDummyUse;
scx.scx_trans = GeoIdentityTransform; scx.scx_trans = GeoIdentityTransform;
scx.scx_area = intArea; scx.scx_area = drcSubIntArea;
if (DBTreeSrCells(&scx, 0, drcSubCheckPaint, (ClientData) &use) == 0) if (DBTreeSrCells(&scx, 0, drcSubCheckPaint, (ClientData) &use) == 0)
return 0; return 0;
} }
/* OK, no more excuses, there's really an interaction area here. */ /* OK, no more excuses, there's really an interaction area here. */
*interaction = intArea; *interaction = drcSubIntArea;
GeoClip(interaction, area); GeoClip(interaction, area);
if (GEO_RECTNULL(interaction)) return 0; if (GEO_RECTNULL(interaction)) return 0;
return 1; return 1;

View File

@ -242,20 +242,9 @@ spcHierWriteParams(
/* Write all requested parameters to the subcircuit call. */ /* Write all requested parameters to the subcircuit call. */
bool checkme = FALSE;
if ((!strcmp(EFDevTypes[dev->dev_type], "pfet_06v0_dss")) ||
(!strcmp(EFDevTypes[dev->dev_type], "nfet_06v0_dss")))
{
checkme = TRUE;
TxPrintf("Diagnostic: Parameter list for %s\n", EFDevTypes[dev->dev_type]);
}
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]); plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
while (plist != NULL) while (plist != NULL)
{ {
if (checkme) TxPrintf("Plist entry %s %s\n", plist->parm_name, plist->parm_type);
switch (plist->parm_type[0]) switch (plist->parm_type[0])
{ {
case 'a': case 'a':
@ -356,7 +345,6 @@ spcHierWriteParams(
// Check for device length vs. terminal length // Check for device length vs. terminal length
if (plist->parm_type[1] == '\0' || plist->parm_type[1] == '0') if (plist->parm_type[1] == '\0' || plist->parm_type[1] == '0')
{ {
if (checkme) TxPrintf("Handling entry l or l0\n");
fprintf(esSpiceF, " %s=", plist->parm_name); fprintf(esSpiceF, " %s=", plist->parm_name);
if (esScale < 0) if (esScale < 0)
fprintf(esSpiceF, "%g", l * scale); fprintf(esSpiceF, "%g", l * scale);
@ -371,10 +359,8 @@ spcHierWriteParams(
{ {
/* l1, l2, etc. used to indicate the length of the terminal */ /* l1, l2, etc. used to indicate the length of the terminal */
/* Find value in dev_params */ /* Find value in dev_params */
if (checkme) TxPrintf("Handling entry l1 or l2\n");
for (dparam = dev->dev_params; dparam; dparam = dparam->parm_next) for (dparam = dev->dev_params; dparam; dparam = dparam->parm_next)
{ {
if (checkme) TxPrintf("Checking dev_params entry %s\n", dparam->parm_name);
if ((strlen(dparam->parm_name) > 2) && if ((strlen(dparam->parm_name) > 2) &&
(dparam->parm_name[0] == 'l') && (dparam->parm_name[0] == 'l') &&
(dparam->parm_name[1] == plist->parm_type[1]) && (dparam->parm_name[1] == plist->parm_type[1]) &&
@ -383,8 +369,6 @@ spcHierWriteParams(
int dval; int dval;
if (sscanf(&dparam->parm_name[3], "%d", &dval) == 1) if (sscanf(&dparam->parm_name[3], "%d", &dval) == 1)
{ {
if (checkme) TxPrintf("Handling dev_params entry %s (to be "
"culled at end)\n", dparam->parm_name);
fprintf(esSpiceF, " %s=", plist->parm_name); fprintf(esSpiceF, " %s=", plist->parm_name);
if (esScale < 0) if (esScale < 0)
fprintf(esSpiceF, "%g", dval * scale); fprintf(esSpiceF, "%g", dval * scale);
@ -394,7 +378,6 @@ spcHierWriteParams(
else else
esSIvalue(esSpiceF, (dval + plist->parm_offset) esSIvalue(esSpiceF, (dval + plist->parm_offset)
* scale * esScale * 1.0E-6); * scale * esScale * 1.0E-6);
/* Why is this here? */
dparam->parm_name[0] = '\0'; dparam->parm_name[0] = '\0';
break; break;
} }

View File

@ -602,26 +602,6 @@ efBuildEquiv(def, nodeName1, nodeName2, resist, isspice)
if (!strcasecmp(nodeName1, nodeName2)) equalByCase = TRUE; if (!strcasecmp(nodeName1, nodeName2)) equalByCase = TRUE;
} }
if (!equalByCase) if (!equalByCase)
{
/* If one of the nodes has been generated from the
* other by "extract unique", then this is a case where
* the "extract unique" algorithm is blind to shorts
* through subcell hierarchy and has made a name unique
* unnecessarily. In that case, merge the node instead
* of generating a short.
*/
char *uniqstr1, *uniqstr2;
bool isuniq;
uniqstr1 = strstr(nodeName1, "_uq");
uniqstr2 = strstr(nodeName2, "_uq");
if (uniqstr1) *uniqstr1 = '\0';
if (uniqstr2) *uniqstr2 = '\0';
isuniq = !strcmp(nodeName1, nodeName2);
if (uniqstr1) *uniqstr1 = '_';
if (uniqstr2) *uniqstr2 = '_';
if (!isuniq)
{ {
if ((EFOutputFlags & EF_SHORT_MASK) != EF_SHORT_NONE) if ((EFOutputFlags & EF_SHORT_MASK) != EF_SHORT_NONE)
{ {
@ -647,16 +627,12 @@ efBuildEquiv(def, nodeName1, nodeName2, resist, isspice)
return; return;
} }
else if (!resist) else if (!resist)
TxError("Warning: Ports \"%s\" and \"%s\" are electrically " TxError("Warning: Ports \"%s\" and \"%s\" are electrically shorted.\n",
"shorted.\n", nodeName1, nodeName2); nodeName1, nodeName2);
else else
/* Do not merge the nodes when folding in extresist parasitics */ /* Do not merge the nodes when folding in extresist parasitics */
return; return;
} }
else if (resist)
/* Do not merge the nodes when folding in extresist parasitics */
return;
}
} }
/* If both names exist and are for different nodes, merge them */ /* If both names exist and are for different nodes, merge them */
@ -676,6 +652,8 @@ efBuildEquiv(def, nodeName1, nodeName2, resist, isspice)
if (efWarn) if (efWarn)
efReadError("Merged nodes %s and %s\n", nodeName1, nodeName2); efReadError("Merged nodes %s and %s\n", nodeName1, nodeName2);
lostnode = efNodeMerge(&nn1->efnn_node, &nn2->efnn_node); lostnode = efNodeMerge(&nn1->efnn_node, &nn2->efnn_node);
if (nn1->efnn_port > 0) nn2->efnn_port = nn1->efnn_port;
else if (nn2->efnn_port > 0) nn1->efnn_port = nn2->efnn_port;
/* Check if there are any device terminals pointing to the /* Check if there are any device terminals pointing to the
* node that was just removed. * node that was just removed.
@ -926,22 +904,20 @@ efBuildDevice(
/* Parse initial arguments for parameters */ /* Parse initial arguments for parameters */
while ((pptr = strchr(argv[argstart], '=')) != NULL) while ((pptr = strchr(argv[argstart], '=')) != NULL)
{ {
/* If the parameter is in the parameter list "devp", then save // Check if this parameter is in the table.
* the value as appropriate. If not, then the entire phrase // If so, handle appropriately. Otherwise, the
* will be output verbatim, so just save the whole string. // parameter gets saved verbatim locally. The
* // "parameters" line comes before any "device" line
* The "parameters" line comes before any "device" line in the // in the .ext file, so the table should be complete.
* .ext file, so the "devp" list should be complete.
*/
*pptr = '\0'; *pptr = '\0';
for (sparm = devp; sparm; sparm = sparm->parm_next) for (sparm = devp; sparm; sparm = sparm->parm_next)
if (!strncasecmp(sparm->parm_type, argv[argstart], 2)) if (!strcasecmp(sparm->parm_type, argv[argstart]))
break; break;
*pptr = '='; *pptr = '=';
if (sparm == NULL) if (sparm == NULL)
{ {
/* Copy the whole string into dev_params */ /* Copy the parameter into dev_params */
/* (parm_type and parm_scale records are not used) */ /* (parm_type and parm_scale records are not used) */
newparm = (DevParam *)mallocMagic(sizeof(DevParam)); newparm = (DevParam *)mallocMagic(sizeof(DevParam));
newparm->parm_name = StrDup((char **)NULL, argv[argstart]); newparm->parm_name = StrDup((char **)NULL, argv[argstart]);
@ -956,59 +932,30 @@ efBuildDevice(
{ {
case 'a': case 'a':
if ((pptr - argv[argstart]) == 2) if ((pptr - argv[argstart]) == 2)
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr) devtmp.dev_area = atoi(pptr);
* locScale * locScale);
else else
{ {
/* Check for a0, a1, a2, ... If a0, handle like "a".
* Otherwise, don't handle it here.
*/
pn = *(argv[argstart] + 1) - '0'; pn = *(argv[argstart] + 1) - '0';
if (pn == 0) if (pn == 0)
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr) devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
* locScale * locScale); * locScale * locScale);
/* Otherwise, punt */
} }
break; break;
case 'p': case 'p':
if ((pptr - argv[argstart]) == 2) if ((pptr - argv[argstart]) == 2)
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale); devtmp.dev_perim = atoi(pptr);
else else
{ {
/* Check for p0, p1, p2, ... If p0, handle like "p".
* Otherwise, don't handle it here.
*/
pn = *(argv[argstart] + 1) - '0'; pn = *(argv[argstart] + 1) - '0';
if (pn == 0) if (pn == 0)
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale); devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
/* Otherwise, use verbatim */
} }
break; break;
case 'l': case 'l':
if ((pptr - argv[argstart]) == 2)
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale); devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
else
{
/* Check for l0, l1, l2, ... If l0, handle like "l".
* Otherwise, save it verbatim like an unknown parameter,
* because its value will not be calculated from terminal
* values like "a1, a2, ..." or "p1, p2, ...".
*/
pn = *(argv[argstart] + 1) - '0';
if (pn == 0)
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
else
{
/* Copy the whole string into dev_params */
newparm = (DevParam *)mallocMagic(sizeof(DevParam));
newparm->parm_name = StrDup((char **)NULL, argv[argstart]);
newparm->parm_next = devtmp.dev_params;
devtmp.dev_params = newparm;
}
}
break; break;
case 'w': case 'w':
devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale); devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
break; break;
@ -1599,25 +1546,7 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
unsigned size = sizeof (Connection) unsigned size = sizeof (Connection)
+ (efNumResistClasses - 1) * sizeof (EFPerimArea); + (efNumResistClasses - 1) * sizeof (EFPerimArea);
/* If one of the nodes has been generated from the if ((EFOutputFlags & EF_SHORT_MASK) != EF_SHORT_NONE)
* other by "extract unique", then this is a case where
* the "extract unique" algorithm is blind to shorts
* through subcell hierarchy and has made a name unique
* unnecessarily. In that case, merge the node instead
* of generating a short.
*/
char *uniqstr1, *uniqstr2;
bool isuniq;
uniqstr1 = strstr(nodeName1, "_uq");
uniqstr2 = strstr(nodeName2, "_uq");
if (uniqstr1) *uniqstr1 = '\0';
if (uniqstr2) *uniqstr2 = '\0';
isuniq = !strcmp(nodeName1, nodeName2);
if (uniqstr1) *uniqstr1 = '_';
if (uniqstr2) *uniqstr2 = '_';
if (!isuniq && ((EFOutputFlags & EF_SHORT_MASK) != EF_SHORT_NONE))
{ {
/* Handle the case where two ports on different nets get merged. /* Handle the case where two ports on different nets get merged.
* If "extract short resistor" or "extract short voltage" has * If "extract short resistor" or "extract short voltage" has
@ -2020,10 +1949,8 @@ efNodeMerge(node1ptr, node2ptr)
if (*node1ptr == *node2ptr) if (*node1ptr == *node2ptr)
return NULL; return NULL;
/* /* Keep the node with the greater number of entries, and merge */
* Keep the node with the greater number of entries, and merge /* the node with fewer entries into it. */
* the node with fewer entries into it.
*/
if ((*node1ptr)->efnode_num >= (*node2ptr)->efnode_num) if ((*node1ptr)->efnode_num >= (*node2ptr)->efnode_num)
{ {
@ -2063,7 +1990,7 @@ efNodeMerge(node1ptr, node2ptr)
/* Make all EFNodeNames point to "keeping" */ /* Make all EFNodeNames point to "keeping" */
if (removing->efnode_name) if (removing->efnode_name)
{ {
bool topportk, topportr, bestname; bool topportk, topportr;
for (nn = removing->efnode_name; nn; nn = nn->efnn_next) for (nn = removing->efnode_name; nn; nn = nn->efnn_next)
{ {
@ -2075,9 +2002,9 @@ efNodeMerge(node1ptr, node2ptr)
topportr = (removing->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE; topportr = (removing->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
/* Concatenate list of EFNodeNames, taking into account precedence */ /* Concatenate list of EFNodeNames, taking into account precedence */
if ((!keeping->efnode_name) || (!topportk && topportr) if ((!keeping->efnode_name) || (!topportk && (topportr
|| EFHNBest(removing->efnode_name->efnn_hier, || EFHNBest(removing->efnode_name->efnn_hier,
keeping->efnode_name->efnn_hier)) keeping->efnode_name->efnn_hier))))
{ {
/* /*
* New official name is that of "removing". * New official name is that of "removing".