From f40a50d3b8ac87f25ac1c09d62d6af771b392c4d Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 17 May 2019 11:25:34 -0400 Subject: [PATCH] Corrected property value merging (again). By the rules of the re-worked property command, "critical" properties must match across devices so that all other properties can be combined as specified (addition, parallel combination, or none). The code was still based on the older notion of the "critical" property being the one to add (and thus preventing multiple properties from being added in different ways). This has now been fixed. --- base/netcmp.c | 88 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/base/netcmp.c b/base/netcmp.c index 38272fb..2864b06 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -3782,7 +3782,7 @@ void series_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run) vl = &(obp->instance.props[p]); if (vl->type == PROP_ENDLIST) break; if (vl->key == NULL) continue; - if (!strcmp(vl->key, "S")) { + if ((*matchfunc)(vl->key, "S")) { sval = vl->value.ival; sl = vl; } @@ -3906,7 +3906,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run) vl = &(obp->instance.props[p]); if (vl->type == PROP_ENDLIST) break; if (vl->key == NULL) continue; - if (!strcmp(vl->key, "M")) { + if ((*matchfunc)(vl->key, "M")) { mval = vl->value.ival; ml = vl; } @@ -3952,7 +3952,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run) vl = &(obp->instance.props[p]); if (vl->type == PROP_ENDLIST) break; if (vl->key == NULL) continue; - if (!strcmp(vl->key, "M")) { + if ((*matchfunc)(vl->key, "M")) { mval = vl->value.ival; ml = vl; } @@ -3960,7 +3960,7 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run) if (kl == NULL) continue; /* Ignored property */ if (subs_crit == NULL) subs_crit = vl->key; - if ((subs_crit != NULL) && !strcmp(vl->key, subs_crit)) { + if ((subs_crit != NULL) && (*matchfunc)(vl->key, subs_crit)) { if ((vl->type == PROP_STRING || vl->type == PROP_EXPRESSION) && (kl->type != vl->type)) PromoteProperty(kl, vl); @@ -4338,6 +4338,7 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, { struct objlist *ob2, *obt; struct property *kl, *m_rec, **plist; + unsigned char **clist; struct valuelist ***vlist, *vl, *vl2, *newvlist; proplinkptr plink, ptop; int pcount, p, i, j, k, pmatch, ival, crit, ctype; @@ -4363,7 +4364,6 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, ptop = NULL; pcount = 1; crit = -1; - ctype = -1; kl = (struct property *)HashFirst(&(tp->propdict)); while (kl != NULL) { // Make a linked list so we don't have to iterate through the hash again @@ -4382,13 +4382,9 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, if (series == FALSE) { if (kl->merge & MERGE_P_CRIT) crit = kl->idx; - if (kl->merge & (MERGE_P_ADD | MERGE_P_PAR)) - ctype = kl->merge & (MERGE_P_ADD | MERGE_P_PAR); } else if (series == TRUE) { if (kl->merge & MERGE_S_CRIT) crit = kl->idx; - if (kl->merge & (MERGE_S_ADD | MERGE_S_PAR)) - ctype = kl->merge & (MERGE_S_ADD | MERGE_S_PAR); } kl = (struct property *)HashNext(&(tp->propdict)); @@ -4396,13 +4392,17 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, // Recast the linked list as an array plist = (struct property **)CALLOC(pcount, sizeof(struct property *)); vlist = (struct valuelist ***)CALLOC(pcount, sizeof(struct valuelist **)); - if (m_rec == NULL) + clist = (unsigned char **)CALLOC(pcount, sizeof(unsigned char *)); + if (m_rec == NULL) { vlist[0] = (struct valuelist **)CALLOC(run, sizeof(struct valuelist *)); + clist[0] = (unsigned char *)CALLOC(run, sizeof(unsigned char)); + } while (ptop != NULL) { plist[ptop->prop->idx] = ptop->prop; vlist[ptop->prop->idx] = (struct valuelist **)CALLOC(run, sizeof(struct valuelist *)); + clist[ptop->prop->idx] = (unsigned char *)CALLOC(run, sizeof(unsigned char)); plink = ptop; FREE(ptop); ptop = plink->next; @@ -4436,6 +4436,14 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, } else if (kl != NULL) { vlist[kl->idx][i] = vl; + if (series == FALSE) { + if (kl->merge & (MERGE_P_ADD | MERGE_P_PAR)) + clist[kl->idx][i] = kl->merge & (MERGE_P_ADD | MERGE_P_PAR); + } + else if (series == TRUE) { + if (kl->merge & (MERGE_S_ADD | MERGE_S_PAR)) + clist[kl->idx][i] = kl->merge & (MERGE_S_ADD | MERGE_S_PAR); + } } } if (++i == run) break; @@ -4600,32 +4608,40 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int series, mult = vlist[0][i]->value.ival; if (mult > 1) { changed = 0; - vl = vlist[crit][i]; - if ((ctype == MERGE_S_ADD) || (ctype == MERGE_P_ADD)) { - if (vl->type == PROP_INTEGER) - vl->value.ival *= mult; - else if (vl->type == PROP_DOUBLE) - vl->value.dval *= (double)mult; - vlist[0][i]->value.ival = 1; - changed += mult; - } - else if ((ctype == MERGE_S_PAR) || (ctype == MERGE_P_PAR)) { - /* Technically one should check if divide-by-mult */ - /* reduces the value to < 1 and promote to double */ - /* if so, but that's a very unlikely case. */ - if (vl->type == PROP_INTEGER) - vl->value.ival /= mult; - else if (vl->type == PROP_DOUBLE) - vl->value.dval /= (double)mult; - vlist[0][i]->value.ival = 1; - changed += mult; - } - if (changed > 0) { - if (series) - Printf("Combined %d series devices.\n", changed); - else - Printf("Combined %d parallel devices.\n", changed); + /* For all properties that are not M, S, or crit, */ + /* combine as specified by the merge type of the property. */ + + for (p = 1; p < pcount; p++) { + if (p == crit) continue; /* critical properties never combine */ + vl = vlist[p][i]; + ctype = clist[p][i]; + + if ((ctype == MERGE_S_ADD) || (ctype == MERGE_P_ADD)) { + if (vl->type == PROP_INTEGER) + vl->value.ival *= mult; + else if (vl->type == PROP_DOUBLE) + vl->value.dval *= (double)mult; + vlist[0][i]->value.ival = 1; + changed += mult; + } + else if ((ctype == MERGE_S_PAR) || (ctype == MERGE_P_PAR)) { + /* Technically one should check if divide-by-mult */ + /* reduces the value to < 1 and promote to double */ + /* if so, but that's a very unlikely case. */ + if (vl->type == PROP_INTEGER) + vl->value.ival /= mult; + else if (vl->type == PROP_DOUBLE) + vl->value.dval /= (double)mult; + vlist[0][i]->value.ival = 1; + changed += mult; + } + if (changed > 0) { + if (series) + Printf("Combined %d series devices.\n", changed); + else + Printf("Combined %d parallel devices.\n", changed); + } } } } @@ -4652,9 +4668,11 @@ cleanup: kl = (struct property *)plist[p]; if (kl) kl->idx = 0; FREE(vlist[p]); + FREE(clist[p]); } FREE(plist); FREE(vlist); + FREE(clist); return changed; }