From 113f0dfb3f5df026127daba209e1252eadc67d8e Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 1 Feb 2022 11:58:11 -0500 Subject: [PATCH] Applied the same method as used in the last commit, to put all cell properties in natural sort order when writing a .mag file. This should remove the last bit of indeterminism in the output of magic database files. --- VERSION | 2 +- database/DBio.c | 157 +++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 143 insertions(+), 16 deletions(-) diff --git a/VERSION b/VERSION index 91354a4c..f3313513 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.264 +8.3.265 diff --git a/database/DBio.c b/database/DBio.c index 21806a22..5823b740 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -2803,7 +2803,7 @@ cucompare(const void *one, const void *two) return strcmpbynum(s1, s2); } -/* Structure used by dbGetCellFunc(). Record a list of cell uses and */ +/* Structure used by dbGetUseFunc(). Record a list of cell uses and */ /* an index into the list. */ struct cellUseList { @@ -2814,11 +2814,19 @@ struct cellUseList { /* * ---------------------------------------------------------------------------- * + * dbGetUseFunc --- + * + * Function to copy an enumerated cell use into a pre-allocated array + * for alphabetical sorting. + * + * Return value: + * Return 0 to keep the search going. + * * ---------------------------------------------------------------------------- */ int -dbGetCellFunc(cellUse, useRec) +dbGetUseFunc(cellUse, useRec) CellUse *cellUse; /* Cell use whose "call" is to be written to a file */ struct cellUseList *useRec; { @@ -2831,11 +2839,19 @@ dbGetCellFunc(cellUse, useRec) /* * ---------------------------------------------------------------------------- * + * dbCountUseFunc --- + * + * Function to count cell uses by incrementing a counter for each + * enumerated use. + * + * Return value: + * Return 0 to keep the search going. + * * ---------------------------------------------------------------------------- */ int -dbCountCellFunc(cellUse, count) +dbCountUseFunc(cellUse, count) CellUse *cellUse; /* Cell use whose "call" is to be written to a file */ int *count; { @@ -2843,6 +2859,99 @@ dbCountCellFunc(cellUse, count) return 0; } +/* Structure used by keycompare to keep the key and value strings of a */ +/* property record. */ + +struct keyValuePair { + char *key; + char *value; +}; + +/* + * ---------------------------------------------------------------------------- + * + * keycompare --- + * + * String comparison of two property keys, for the purpose of sorting + * the properties in a .mag file output in a repeatable way. + * + * ---------------------------------------------------------------------------- + */ + +int +keycompare(const void *one, const void *two) +{ + int cval; + struct keyValuePair *kv1 = *((struct keyValuePair **)one); + struct keyValuePair *kv2 = *((struct keyValuePair **)two); + char *s1 = kv1->key; + char *s2 = kv2->key; + + cval = strcmpbynum(s1, s2); + return cval; +} + +/* Structures used by dbGetPropFunc(). Record a list of property keys */ +/* and values and an index into the lists. */ + +struct cellPropList { + int idx; + struct keyValuePair **keyValueList; +}; + +/* + * ---------------------------------------------------------------------------- + * + * dbGetPropFunc --- + * + * Function to copy the key and value of an enumerated property + * record into a pre-allocated array for alphabetical sorting. + * + * Return value: + * Return 0 to keep the search going. + * + * ---------------------------------------------------------------------------- + */ + +int +dbGetPropFunc(key, value, propRec) + char *key; + ClientData value; + struct cellPropList *propRec; +{ + propRec->keyValueList[propRec->idx] = + (struct keyValuePair *)mallocMagic(sizeof(struct keyValuePair)); + propRec->keyValueList[propRec->idx]->key = key; + propRec->keyValueList[propRec->idx]->value = value; + propRec->idx++; + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * dbCountPropFunc --- + * + * Function to count cell properties by incrementing a counter for each + * enumerated property. + * + * Return value: + * Return 0 to keep the search going. + * + * ---------------------------------------------------------------------------- + */ + +int +dbCountPropFunc(key, value, count) + char *key; + ClientData value; + int *count; /* Client data */ +{ + (*count)++; + return 0; +} + /* * ---------------------------------------------------------------------------- * @@ -2892,7 +3001,7 @@ DBCellWriteFile(cellDef, f) char *propvalue; bool propfound; CellUse **useList; - int i, numUses = 0; + int i, numUses = 0, numProps = 0; struct cellUseList cul; #define FPUTSF(f,s)\ @@ -2976,13 +3085,13 @@ DBCellWriteFile(cellDef, f) /* time the CellDef is written, first collect all of the cells, */ /* then sort them alphabetically, and then write them. */ - DBCellEnum(cellDef, dbCountCellFunc, (ClientData) &numUses); + DBCellEnum(cellDef, dbCountUseFunc, (ClientData) &numUses); if (numUses > 0) { cul.useList = (CellUse **)mallocMagic(numUses * sizeof(CellUse *)); cul.idx = 0; - if (DBCellEnum(cellDef, dbGetCellFunc, (ClientData)&cul)) + if (DBCellEnum(cellDef, dbGetUseFunc, (ClientData)&cul)) goto ioerror; qsort(cul.useList, numUses, sizeof(CellUse *), cucompare); @@ -3144,12 +3253,31 @@ DBCellWriteFile(cellDef, f) } } - if (cellDef->cd_props != (ClientData)NULL) + DBPropEnum(cellDef, dbCountPropFunc, (ClientData)&numProps); + if (numProps > 0) { + struct cellPropList propRec; + + propRec.idx = 0; + propRec.keyValueList = (struct keyValuePair **)mallocMagic(numProps + * sizeof(struct keyValuePair *)); + DBPropEnum(cellDef, dbGetPropFunc, (ClientData)&propRec); + + qsort(propRec.keyValueList, numProps, sizeof(struct keyValuePair *), + keycompare); + FPUTSF(f, "<< properties >>\n"); - DBPropEnum(cellDef, dbWritePropFunc, (ClientData)f); + for (i = 0; i < numProps; i++) + { + dbWritePropFunc(propRec.keyValueList[i]->key, + propRec.keyValueList[i]->value, + (ClientData)f); + freeMagic ((char *)propRec.keyValueList[i]); + } + freeMagic((char *)propRec.keyValueList); } + /* Restore the original values in FIXED_BBOX, if any */ if (propfound) DBPropPut(cellDef, "FIXED_BBOX", propvalue); FPUTSF(f, "<< end >>\n"); @@ -3192,21 +3320,20 @@ ioerror: int dbWritePropFunc(key, value, cdata) char *key; - ClientData value; + char *value; ClientData cdata; { FILE *f = (FILE *)cdata; - char *lstring; - lstring = (char *)mallocMagic(10 + strlen((char *)value) + strlen(key)); - sprintf(lstring, "string %s %s\n", key, (char *)value); - FPUTSR(f, lstring); - freeMagic(lstring); + FPUTSR(f, "string "); + FPUTSR(f, key); + FPUTSR(f, " "); + FPUTSR(f, value); + FPUTSR(f, "\n"); return 0; } - /* * ---------------------------------------------------------------------------- *