Finally got around to modifying the "cellname [list] top" command

so that it returns cellnames in "natural sort" alphabetical order
instead of the random order produced by scanning the hash table
of cell names.  Since this command is used by the "cell manager"
window code, which was also not doing any sorting, then this fixes
the same issue in the "cell manager".
This commit is contained in:
Tim Edwards 2021-04-19 10:08:58 -04:00
parent 4aa7e21a64
commit 04fca92bf0
2 changed files with 111 additions and 25 deletions

View File

@ -1 +1 @@
8.3.153
8.3.154

View File

@ -21,7 +21,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#endif /* not lint */
#include <stdio.h>
#include <stdlib.h> /* for qsort() */
#include <string.h>
#include <ctype.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
@ -598,6 +600,67 @@ DBTopPrint(mw, dolist)
}
}
/*
* ----------------------------------------------------------------------------
* Simple natural sort routine
* https://stackoverflow.com/questions/34518/natural-sorting-algorithm
* By Norman Ramsey, edited for style.
* ----------------------------------------------------------------------------
*/
int strcmpbynum(const char *s1, const char *s2)
{
/* Like strcmp() but compare sequences of digits numerically */
for (;;)
{
if (*s2 == '\0')
return *s1 != '\0';
else if (*s1 == '\0')
return 1;
else if (!(isdigit(*s1) && isdigit(*s2)))
{
if (*s1 != *s2)
return (int)*s1 - (int)*s2;
else
{
++s1;
++s2;
}
}
else
{
char *lim1, *lim2;
unsigned long n1 = strtoul(s1, &lim1, 10);
unsigned long n2 = strtoul(s2, &lim2, 10);
if (n1 > n2)
return 1;
else if (n1 < n2)
return -1;
s1 = lim1;
s2 = lim2;
}
}
}
/*
* ----------------------------------------------------------------------------
* Sort routine for qsort() to be used by DBCellPrint(). Sorts in alphabetical
* order using the natural sort routine above. List is reverse sorted since
* the code below prints from the end to the beginning of the list.
* ----------------------------------------------------------------------------
*/
int
qcompare(const void *one, const void *two)
{
int cval;
char *s1 = *((char **)one);
char *s2 = *((char **)two);
cval = strcmpbynum(s1, s2);
return -cval;
}
/*
* ----------------------------------------------------------------------------
*
@ -625,11 +688,12 @@ DBCellPrint(CellName, who, dolist)
int who;
bool dolist;
{
int found;
int found, numcells;
HashSearch hs;
HashEntry *entry;
CellDef *celldef;
CellUse *celluse;
char **celllist;
if (!dolist)
{
@ -657,6 +721,11 @@ DBCellPrint(CellName, who, dolist)
* CDMODIFIED flag set.
*/
numcells = dbCellDefTable.ht_nEntries;
if (numcells == 0) numcells = 1;
celllist = (char **)mallocMagic(numcells * sizeof(char *));
numcells = 0;
HashStartSearch(&hs);
while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{
@ -666,28 +735,39 @@ DBCellPrint(CellName, who, dolist)
if (((celldef->cd_flags & CDINTERNAL) != CDINTERNAL) &&
((who != MODIFIED) ||
(celldef->cd_flags & CDMODIFIED)))
{
if (celldef->cd_name != NULL)
{
if (dolist)
#ifdef MAGIC_WRAPPER
Tcl_AppendElement(magicinterp, celldef->cd_name);
#else
TxPrintf("%s ", celldef->cd_name);
#endif
else
TxPrintf(" %s\n", celldef->cd_name);
}
}
celllist[numcells++] = celldef->cd_name;
}
}
qsort(celllist, numcells, sizeof(char *), qcompare);
while (--numcells >= 0)
{
if (dolist)
#ifdef MAGIC_WRAPPER
Tcl_AppendElement(magicinterp, celllist[numcells]);
#else
TxPrintf("%s ", celllist[numcells]);
#endif
else
TxPrintf(" %s\n", celllist[numcells]);
}
freeMagic(celllist);
break;
case TOPCELLS:
/*
* Print the name of all the 'top' cells.
* Print the name of all the 'top' cells. Sort alphabetically.
*/
numcells = dbCellDefTable.ht_nEntries;
if (numcells == 0) numcells = 1;
celllist = (char **)mallocMagic(numcells * sizeof(char *));
numcells = 0;
HashStartSearch(&hs);
while( (entry = HashNext(&dbCellDefTable, &hs)) != NULL)
{
@ -712,19 +792,25 @@ DBCellPrint(CellName, who, dolist)
}
}
if ( (found == 0) && (celldef->cd_name != NULL) )
{
if (dolist)
#ifdef MAGIC_WRAPPER
Tcl_AppendElement(magicinterp, celldef->cd_name);
#else
TxPrintf("%s ", celldef->cd_name);
#endif
else
TxPrintf(" %s\n", celldef->cd_name);
}
celllist[numcells++] = celldef->cd_name;
}
}
}
qsort(celllist, numcells, sizeof(char *), qcompare);
while (--numcells >= 0)
{
if (dolist)
#ifdef MAGIC_WRAPPER
Tcl_AppendElement(magicinterp, celllist[numcells]);
#else
TxPrintf("%s ", celllist[numcells]);
#endif
else
TxPrintf(" %s\n", celllist[numcells]);
}
freeMagic(celllist);
break;
default: