From 7dc2eec5aaa80c9c4525358b6d72f4c14d23dfa6 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 26 Oct 2006 16:05:23 +0000 Subject: [PATCH] Permit breakpoint tables to run any direction as long as the slope doesn't change sign. Reduced memory requirement by making the table a contiguous array rather than an array of pointers to intervals. Improved error reporting. --- src/db/cvtBpt.c | 250 +++++++++++++++++++++-------------- src/dbStatic/dbBase.h | 2 +- src/dbStatic/dbLexRoutines.c | 95 +++++++------ src/dbStatic/dbStaticLib.c | 29 ++-- 4 files changed, 219 insertions(+), 157 deletions(-) diff --git a/src/db/cvtBpt.c b/src/db/cvtBpt.c index 2362c4849..350392b10 100644 --- a/src/db/cvtBpt.c +++ b/src/db/cvtBpt.c @@ -15,11 +15,7 @@ * Date: 04OCT95 * This is adaptation of old bldCvtTable */ -#include -#include -#include -#include "ellLib.h" #include "dbBase.h" #include "dbStaticLib.h" #include "epicsPrint.h" @@ -27,125 +23,181 @@ #define epicsExportSharedSymbols #include "dbAccess.h" #include "cvtTable.h" - + static brkTable *findBrkTable(short linr) { dbMenu *pdbMenu; pdbMenu = dbFindMenu(pdbbase,"menuConvert"); - if(!pdbMenu) { - epicsPrintf("findBrkTable: menuConvert does not exist\n"); - return(0); + if (!pdbMenu) { + epicsPrintf("findBrkTable: menuConvert not loaded!\n"); + return NULL; } - if(linr<0 || linr>=pdbMenu->nChoice) { - epicsPrintf("findBrkTable linr %d but menuConvert has %d choices\n", + if (linr < 0 || linr >= pdbMenu->nChoice) { + epicsPrintf("findBrkTable: linr=%d but menuConvert only has %d choices\n", linr,pdbMenu->nChoice); - return(0); + return NULL; } - return(dbFindBrkTable(pdbbase,pdbMenu->papChoiceValue[linr])); + return dbFindBrkTable(pdbbase,pdbMenu->papChoiceValue[linr]); } - -long epicsShareAPI cvtRawToEngBpt(double *pval,short linr,short init, void **ppbrk, - short *plbrk) -{ - double val=*pval; - long status=0; + +/* Used by both ao and ai record types */ +long epicsShareAPI cvtRawToEngBpt(double *pval, short linr, short init, + void **ppbrk, short *plbrk) +{ + double val = *pval; + long status = 0; brkTable *pbrkTable; - brkInt *pInt; - brkInt *pnxtInt; + brkInt *pInt, *nInt; short lbrk; int number; + if (linr < 2) + return -1; - if(linr < 2) return(-1); - if(init==TRUE || *ppbrk == NULL) { /*must find breakpoint table*/ + if (init || *ppbrk == NULL) { pbrkTable = findBrkTable(linr); - if(!pbrkTable) return(S_dbLib_badField); + if (!pbrkTable) + return S_dbLib_badField; + *ppbrk = (void *)pbrkTable; - /* Just start at the beginning */ - *plbrk=0; - } - pbrkTable = (struct brkTable *)*ppbrk; + *plbrk = 0; + } else + pbrkTable = (brkTable *)*ppbrk; + number = pbrkTable->number; lbrk = *plbrk; - /*make sure we dont go off end of table*/ - if( (lbrk+1) >= number ) lbrk--; - pInt = pbrkTable->papBrkInt[lbrk]; - pnxtInt = pbrkTable->papBrkInt[lbrk+1]; - /* find entry for increased value */ - while( (pnxtInt->raw) <= val ) { - lbrk++; - pInt = pbrkTable->papBrkInt[lbrk]; - if( lbrk >= number-1) { - status=1; - break; - } - pnxtInt = pbrkTable->papBrkInt[lbrk+1]; - } - while( (pInt->raw) > val) { - if(lbrk==0) { - status=1; - break; - } - lbrk--; - pInt = pbrkTable->papBrkInt[lbrk]; + + /* Limit index to the size of the table */ + if (lbrk < 0) + lbrk = 0; + else if (lbrk > number-2) + lbrk = number-2; + + pInt = & pbrkTable->paBrkInt[lbrk]; + nInt = pInt + 1; + + if (nInt->raw > pInt->raw) { + /* raw values increase down the table */ + while (val > nInt->raw) { + lbrk++; + pInt = nInt++; + if (lbrk > number-2) { + status = 1; + break; + } + } + while (val < pInt->raw) { + if (lbrk <= 0) { + status = 1; + break; + } + lbrk--; + nInt = pInt--; + } + } else { + /* raw values decrease down the table */ + while (val <= nInt->raw) { + lbrk++; + pInt = nInt++; + if (lbrk > number-2) { + status = 1; + break; + } + } + while(val > pInt->raw) { + if (lbrk <= 0) { + status = 1; + break; + } + lbrk--; + nInt = pInt--; + } } + *plbrk = lbrk; *pval = pInt->eng + (val - pInt->raw) * pInt->slope; - return(status); + + return status; } - -long epicsShareAPI cvtEngToRawBpt(double *pval,short linr,short init, - void **ppbrk,short *plbrk) -{ - double val=*pval; - long status=0; - brkTable *pbrkTable; - brkInt *pInt; - brkInt *pnxtInt; - short lbrk; - int number; +/* Used by the ao record type */ +long epicsShareAPI cvtEngToRawBpt(double *pval, short linr, short init, + void **ppbrk, short *plbrk) +{ + double val = *pval; + long status = 0; + brkTable *pbrkTable; + brkInt *pInt, *nInt; + short lbrk; + int number; - if(linr < 2) return(-1); - if(init==TRUE || *ppbrk == NULL) { /*must find breakpoint table*/ + if (linr < 2) + return -1; + + if (init || *ppbrk == NULL) { /*must find breakpoint table*/ pbrkTable = findBrkTable(linr); - if(!pbrkTable) return(S_dbLib_badField); + if (!pbrkTable) + return S_dbLib_badField; + *ppbrk = (void *)pbrkTable; - /* Just start at the beginning */ - *plbrk=0; - } - pbrkTable = (struct brkTable *)*ppbrk; - number = pbrkTable->number; - lbrk = *plbrk; - /*make sure we dont go off end of table*/ - if( (lbrk+1) >= number ) lbrk--; - pInt = pbrkTable->papBrkInt[lbrk]; - pnxtInt = pbrkTable->papBrkInt[lbrk+1]; - /* find entry for increased value */ - while( (pnxtInt->eng) <= val ) { - lbrk++; - pInt = pbrkTable->papBrkInt[lbrk]; - if( lbrk >= number-1) { - status=1; - break; - } - pnxtInt = pbrkTable->papBrkInt[lbrk+1]; - } - while( (pInt->eng) > val) { - if(lbrk==0) { - status=1; - break; - } - lbrk--; - pInt = pbrkTable->papBrkInt[lbrk]; - } - if(pInt->slope!=0){ - *plbrk = lbrk; - *pval = pInt->raw + (val - pInt->eng) / pInt->slope; - } - else { - return(status); - } - return(0); + /* start at the beginning */ + *plbrk = 0; + } else + pbrkTable = (brkTable *)*ppbrk; + + number = pbrkTable->number; + lbrk = *plbrk; + + /* Limit index to the size of the table */ + if (lbrk < 0) + lbrk = 0; + else if (lbrk > number-2) + lbrk = number-2; + + pInt = & pbrkTable->paBrkInt[lbrk]; + nInt = pInt + 1; + + if (nInt->eng > pInt->eng) { + /* eng values increase down the table */ + while (val > nInt->eng) { + lbrk++; + pInt = nInt++; + if (lbrk > number-2) { + status = 1; + break; + } + } + while (val < pInt->eng) { + if (lbrk <= 0) { + status = 1; + break; + } + lbrk--; + nInt = pInt--; + } + } else { + /* eng values decrease down the table */ + while (val <= nInt->eng) { + lbrk++; + pInt = nInt++; + if (lbrk > number-2) { + status = 1; + break; + } + } + while (val > pInt->eng) { + if (lbrk <= 0) { + status = 1; + break; + } + lbrk--; + nInt = pInt--; + } + } + + *plbrk = lbrk; + *pval = pInt->raw + (val - pInt->eng) / pInt->slope; + + return status; } diff --git a/src/dbStatic/dbBase.h b/src/dbStatic/dbBase.h index 38ba2d8c7..7f4bc148b 100644 --- a/src/dbStatic/dbBase.h +++ b/src/dbStatic/dbBase.h @@ -65,7 +65,7 @@ typedef struct brkTable { /* breakpoint table */ ELLNODE node; char *name; /*breakpoint table name */ long number; /*number of brkInt in this table*/ - struct brkInt **papBrkInt; /* ptr to array of ptr to brkInt */ + struct brkInt *paBrkInt; /* ptr to array of brkInts */ }brkTable; typedef struct dbFldDes{ /* field description */ diff --git a/src/dbStatic/dbLexRoutines.c b/src/dbStatic/dbLexRoutines.c index a1aeaa2f0..73152e774 100644 --- a/src/dbStatic/dbLexRoutines.c +++ b/src/dbStatic/dbLexRoutines.c @@ -823,77 +823,84 @@ static void dbBreakHead(char *name) static void dbBreakItem(char *value) { - if(duplicate) return; + double dummy; + if (duplicate) return; + if (epicsScanDouble(value, &dummy) != 1) { + yyerrorAbort("Non-numeric value in breaktable"); + } allocTemp(epicsStrDup(value)); } static void dbBreakBody(void) { brkTable *pnewbrkTable; + brkInt *paBrkInt; brkTable *pbrkTable; - int number; + int number, down=0; int i,choice; GPHENTRY *pgphentry; - if(duplicate) { + if (duplicate) { duplicate = FALSE; return; } pnewbrkTable = (brkTable *)popFirstTemp(); - pnewbrkTable->number = number = ellCount(&tempList)/2; - if(number*2 != ellCount(&tempList)) - yyerrorAbort("dbBreakBody: Odd number of values"); - pnewbrkTable->papBrkInt = dbCalloc(number,sizeof(brkInt)); - for(i=0; inumber = number; + pnewbrkTable->paBrkInt = paBrkInt = dbCalloc(number, sizeof(brkInt)); + for (i=0; ipapBrkInt[i] = dbCalloc(1,sizeof(brkInt)); - pnewbrkTable->papBrkInt[i]->raw = raw; - pnewbrkTable->papBrkInt[i]->eng = eng; + str = (char *)popFirstTemp(); + epicsScanDouble(str, &paBrkInt[i].raw); + free(str); + + str = (char *)popFirstTemp(); + epicsScanDouble(str, &paBrkInt[i].eng); + free(str); } /* Compute slopes */ - for(i=0; ipapBrkInt[i]->slope = - (pnewbrkTable->papBrkInt[i+1]->eng - pnewbrkTable->papBrkInt[i]->eng)/ - (pnewbrkTable->papBrkInt[i+1]->raw - pnewbrkTable->papBrkInt[i]->raw); - } - if(number>1) { - pnewbrkTable->papBrkInt[number-1]->slope = - pnewbrkTable->papBrkInt[number-2]->slope; + for (i=0; ibptList); - while(pbrkTable) { - choice = strcmp(pbrkTable->name,pnewbrkTable->name); - if(choice==0) { - ellInsert(&pdbbase->bptList,ellPrevious((ELLNODE *)pbrkTable), - (ELLNODE *)pnewbrkTable); - gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList); - ellDelete(&pdbbase->bptList,(ELLNODE *)pbrkTable); - break; - } else if(choice>0) { - ellInsert(&pdbbase->bptList,ellPrevious((ELLNODE *)pbrkTable), + while (pbrkTable) { + if (strcmp(pbrkTable->name, pnewbrkTable->name) > 0) { + ellInsert(&pdbbase->bptList, ellPrevious((ELLNODE *)pbrkTable), (ELLNODE *)pnewbrkTable); break; } pbrkTable = (brkTable *)ellNext(&pbrkTable->node); } + if (!pbrkTable) ellAdd(&pdbbase->bptList, &pnewbrkTable->node); pgphentry = gphAdd(pdbbase->pgpHash,pnewbrkTable->name,&pdbbase->bptList); - if(!pgphentry) { - yyerrorAbort("gphAdd failed"); - } else { - pgphentry->userPvt = pnewbrkTable; + if (!pgphentry) { + yyerrorAbort("dbBreakBody: gphAdd failed"); + return; } - if(!pbrkTable) ellAdd(&pdbbase->bptList,&pnewbrkTable->node); + pgphentry->userPvt = pnewbrkTable; } static void dbRecordHead(char *recordType,char *name, int visible) diff --git a/src/dbStatic/dbStaticLib.c b/src/dbStatic/dbStaticLib.c index e60425477..28c4cabcc 100644 --- a/src/dbStatic/dbStaticLib.c +++ b/src/dbStatic/dbStaticLib.c @@ -716,8 +716,7 @@ void epicsShareAPI dbFreeBase(dbBase *pdbbase) gphDelete(pdbbase->pgpHash,pbrkTable->name,&pdbbase->bptList); ellDelete(&pdbbase->bptList,&pbrkTable->node); free(pbrkTable->name); - for(i=0; inumber; i++) - free((void *)(pbrkTable->papBrkInt[i])); + free((void *)pbrkTable->paBrkInt); free((void *)pbrkTable); pbrkTable = pbrkTableNext; } @@ -1225,18 +1224,20 @@ long epicsShareAPI dbWriteBreaktableFP(DBBASE *pdbbase,FILE *fp) { brkTable *pbrkTable; brkInt *pbrkInt; - int ind; + int i; - if(!pdbbase) { + if (!pdbbase) { fprintf(stderr,"pdbbase not specified\n"); return(-1); } - for(pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList); - pbrkTable; pbrkTable = (brkTable *)ellNext(&pbrkTable->node)) { + for (pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList); + pbrkTable; + pbrkTable = (brkTable *)ellNext(&pbrkTable->node)) { fprintf(fp,"breaktable(%s) {\n",pbrkTable->name); - for(ind=0; indnumber; ind++) { - pbrkInt = pbrkTable->papBrkInt[ind]; - fprintf(fp,"\t%e %e\n",pbrkInt->raw,pbrkInt->eng); + pbrkInt = pbrkTable->paBrkInt; + for(i=0; i < pbrkTable->number; i++) { + fprintf(fp,"\t%e, %e\n",pbrkInt->raw,pbrkInt->eng); + pbrkInt++; } fprintf(fp,"}\n"); } @@ -3856,11 +3857,13 @@ void epicsShareAPI dbDumpBreaktable(DBBASE *pdbbase,const char *name) } for(pbrkTable = (brkTable *)ellFirst(&pdbbase->bptList); pbrkTable; pbrkTable = (brkTable *)ellNext(&pbrkTable->node)) { - if(name && strcmp(name,pbrkTable->name)!=0) continue; + if (name && strcmp(name,pbrkTable->name)!=0) continue; printf("breaktable(%s) {\n",pbrkTable->name); - for(ind=0; indnumber; ind++) { - pbrkInt = pbrkTable->papBrkInt[ind]; - printf("\t%f %e %f\n",pbrkInt->raw,pbrkInt->slope,pbrkInt->eng); + pbrkInt = pbrkTable->paBrkInt; + for(ind=0; ind < pbrkTable->number; ind++) { + printf("\traw=%f slope=%e eng=%f\n", + pbrkInt->raw, pbrkInt->slope, pbrkInt->eng); + pbrkInt++; } printf("}\n"); }