Applied a string sort to the dump of cell uses when writing a .mag

file.  This makes the output of .mag files deterministic (except
possibly for properties, which may also need to be handled this
way).
This commit is contained in:
Tim Edwards 2022-01-31 15:30:24 -05:00
parent 45bb62de2f
commit ea80e30a8e
3 changed files with 95 additions and 8 deletions

View File

@ -1 +1 @@
8.3.262
8.3.263

View File

@ -2777,6 +2777,72 @@ dbFindCellGCFFunc(cellUse, ggcf)
return (*ggcf == 1) ? 1 : 0;
}
/*
* ----------------------------------------------------------------------------
*
* cucompare ---
*
* String comparison of two instance names, for the purpose of sorting
* the instances in a .mag file output in a repeatable way.
*
* ----------------------------------------------------------------------------
*/
int
cucompare(const void *one, const void *two)
{
CellUse *use1, *use2;
char *s1, *s2;
use1 = *((CellUse **)one);
use2 = *((CellUse **)two);
s1 = use1->cu_id;
s2 = use2->cu_id;
return strcmpbynum(s1, s2);
}
/* Structure used by dbGetCellFunc(). Record a list of cell uses and */
/* an index into the list. */
struct cellUseList {
int idx;
CellUse **useList;
};
/*
* ----------------------------------------------------------------------------
*
* ----------------------------------------------------------------------------
*/
int
dbGetCellFunc(cellUse, useRec)
CellUse *cellUse; /* Cell use whose "call" is to be written to a file */
struct cellUseList *useRec;
{
useRec->useList[useRec->idx] = cellUse;
useRec->idx++;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* ----------------------------------------------------------------------------
*/
int
dbCountCellFunc(cellUse, count)
CellUse *cellUse; /* Cell use whose "call" is to be written to a file */
int *count;
{
(*count)++;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -2825,6 +2891,9 @@ DBCellWriteFile(cellDef, f)
char lstring[256];
char *propvalue;
bool propfound;
CellUse **useList;
int i, numUses = 0;
struct cellUseList cul;
#define FPUTSF(f,s)\
{\
@ -2903,12 +2972,29 @@ DBCellWriteFile(cellDef, f)
goto ioerror;
}
/* Now the cell uses */
if (DBCellEnum(cellDef, dbWriteCellFunc, (ClientData) &arg))
goto ioerror;
/* Now the cell uses. To make sure that output is repeatable each */
/* time the CellDef is written, first collect all of the cells, */
/* then sort them alphabetically, and then write them. */
/* Clear flags set in dbWriteCellFunc */
DBCellEnum(cellDef, dbClearCellFunc, (ClientData)NULL);
DBCellEnum(cellDef, dbCountCellFunc, (ClientData) &numUses);
if (numUses > 0)
{
cul.useList = (CellUse **)mallocMagic(numUses * sizeof(CellUse *));
cul.idx = 0;
if (DBCellEnum(cellDef, dbGetCellFunc, (ClientData)&cul))
goto ioerror;
qsort(cul.useList, numUses, sizeof(CellUse *), cucompare);
for (i = 0; i < numUses; i++)
dbWriteCellFunc(cul.useList[i], (ClientData) &arg);
freeMagic((char *)cul.useList);
/* Clear flags set in dbWriteCellFunc */
DBCellEnum(cellDef, dbClearCellFunc, (ClientData)NULL);
}
/* Now labels */
if (cellDef->cd_labels)

View File

@ -208,8 +208,9 @@ extern void dbFreeCellPlane();
extern void dbFreePaintPlane();
extern bool dbTechAddPaint();
extern bool dbTechAddErase();
ClientData dbTechNameLookup();
ClientData dbTechNameLookupExact();
ClientData dbTechNameLookup();
ClientData dbTechNameLookupExact();
extern int strcmpbynum();
/* --------------- Internal database technology variables ------------- */