From e889336458c85d69a8d55fc0f51e7f3dc95f9924 Mon Sep 17 00:00:00 2001
From: Andrew Johnson <anj@aps.anl.gov>
Date: Wed, 17 Oct 2012 18:08:39 -0500
Subject: [PATCH] db: Undefined alarm limits should return NaN

Where the record doesn't provide get_alarm_double() or for fields
where the default applies, we were still returning 0.
---
 src/db/dbAccess.c |  70 +++++++++++------------
 src/db/recGbl.c   | 140 ++++++++++++++++++++++------------------------
 2 files changed, 98 insertions(+), 112 deletions(-)

diff --git a/src/db/dbAccess.c b/src/db/dbAccess.c
index 94f8a1b79b..d3e47062c7 100644
--- a/src/db/dbAccess.c
+++ b/src/db/dbAccess.c
@@ -27,6 +27,7 @@
 #include "errlog.h"
 #include "cantProceed.h"
 #include "cvtFast.h"
+#include "epicsMath.h"
 #include "epicsTime.h"
 #include "alarm.h"
 #include "ellLib.h"
@@ -281,48 +282,41 @@ static void get_control(DBADDR *paddr, char **ppbuffer,
 }
 
 static void get_alarm(DBADDR *paddr, char **ppbuffer,
-	struct rset *prset,long	*options)
+    struct rset *prset, long *options)
 {
-	struct			dbr_alDouble ald;
-	int			got_data=FALSE;
+    char *pbuffer = *ppbuffer;
+    struct dbr_alDouble ald = {epicsNAN, epicsNAN, epicsNAN, epicsNAN};
+    long no_data = TRUE;
 
-        ald.upper_alarm_limit = ald.upper_warning_limit = 0.0;
-        ald.lower_warning_limit = ald.lower_alarm_limit = 0.0;
-	if( prset && prset->get_alarm_double ) {
-		(*prset->get_alarm_double)(paddr,&ald);
-		got_data=TRUE;
-	}
-	if( (*options) & (DBR_AL_LONG) ) {
-		char	*pbuffer=*ppbuffer;
+    if (prset && prset->get_alarm_double)
+        no_data = prset->get_alarm_double(paddr, &ald);
 
-		if(got_data) {
-		    struct dbr_alLong *pal=(struct dbr_alLong*)pbuffer;
-		    pal->upper_alarm_limit = (epicsInt32)ald.upper_alarm_limit;
-		    pal->upper_warning_limit = (epicsInt32)ald.upper_warning_limit;
-		    pal->lower_warning_limit = (epicsInt32)ald.lower_warning_limit;
-		    pal->lower_alarm_limit = (epicsInt32)ald.lower_alarm_limit;
-		} else {
-		    memset(pbuffer,'\0',dbr_alLong_size);
-		    *options = (*options) ^ DBR_AL_LONG; /*Turn off option*/
-		}
-		*ppbuffer = ((char *)*ppbuffer) + dbr_alLong_size;
-	}
-	if( (*options) & (DBR_AL_DOUBLE) ) {
-		char	*pbuffer=*ppbuffer;
+    if (*options & DBR_AL_LONG) {
+        struct dbr_alLong *pal = (struct dbr_alLong*) pbuffer;
 
-		if(got_data) {
-		    struct dbr_alDouble *pal=(struct dbr_alDouble*)pbuffer;
-		    pal->upper_alarm_limit = ald.upper_alarm_limit;
-		    pal->upper_warning_limit = ald.upper_warning_limit;
-		    pal->lower_warning_limit = ald.lower_warning_limit;
-		    pal->lower_alarm_limit = ald.lower_alarm_limit;
-		} else {
-		    memset(pbuffer,'\0',dbr_alDouble_size);
-		    *options = (*options) ^ DBR_AL_DOUBLE; /*Turn off option*/
-		}
-		*ppbuffer = ((char *)*ppbuffer) + dbr_alDouble_size;
-	}
-	return;
+        pal->upper_alarm_limit   = (epicsInt32) ald.upper_alarm_limit;
+        pal->upper_warning_limit = (epicsInt32) ald.upper_warning_limit;
+        pal->lower_warning_limit = (epicsInt32) ald.lower_warning_limit;
+        pal->lower_alarm_limit   = (epicsInt32) ald.lower_alarm_limit;
+
+        if (no_data)
+            *options ^= DBR_AL_LONG; /*Turn off option*/
+
+        *ppbuffer += dbr_alLong_size;
+    }
+    if (*options & DBR_AL_DOUBLE) {
+        struct dbr_alDouble *pal = (struct dbr_alDouble*) pbuffer;
+
+        pal->upper_alarm_limit   = ald.upper_alarm_limit;
+        pal->upper_warning_limit = ald.upper_warning_limit;
+        pal->lower_warning_limit = ald.lower_warning_limit;
+        pal->lower_alarm_limit   = ald.lower_alarm_limit;
+
+        if (no_data)
+            *options ^= DBR_AL_DOUBLE; /*Turn off option*/
+
+        *ppbuffer += dbr_alDouble_size;
+    }
 }
 
 static void getOptions(DBADDR *paddr,char **poriginal,long *options,void *pflin)
diff --git a/src/db/recGbl.c b/src/db/recGbl.c
index 7cdf69a19d..2d58c9dab3 100644
--- a/src/db/recGbl.c
+++ b/src/db/recGbl.c
@@ -21,6 +21,7 @@
 #include <limits.h>
 
 #include "dbDefs.h"
+#include "epicsMath.h"
 #include "epicsTime.h"
 #include "epicsPrint.h"
 #include "dbBase.h"
@@ -107,64 +108,56 @@ void epicsShareAPI recGblRecSupError(long status, const struct dbAddr *paddr,
     return;
 }
 
-void epicsShareAPI recGblGetPrec(const struct dbAddr *paddr,long *precision)
+void epicsShareAPI recGblGetPrec(const struct dbAddr *paddr, long *precision)
 {
     dbFldDes *pdbFldDes = paddr->pfldDes;
 
-    switch(pdbFldDes->field_type){
-    case(DBF_SHORT):
-         *precision = 0;
-         break;
-    case(DBF_USHORT):
-         *precision = 0;
-         break;
-    case(DBF_LONG):
-         *precision = 0;
-         break;
-    case(DBF_ULONG):
-         *precision = 0;
-         break;
-    case(DBF_FLOAT):
-    case(DBF_DOUBLE):
-	 if(*precision<0 || *precision>15) *precision=15;
-         break;
+    switch (pdbFldDes->field_type) {
+    case DBF_CHAR:
+    case DBF_UCHAR:
+    case DBF_SHORT:
+    case DBF_USHORT:
+    case DBF_LONG:
+    case DBF_ULONG:
+        *precision = 0;
+        break;
+
+    case DBF_FLOAT:
+    case DBF_DOUBLE:
+        if (*precision < 0 || *precision > 15)
+            *precision = 15;
+        break;
+
     default:
          break;
     }
-    return;
 }
 
-void epicsShareAPI recGblGetGraphicDouble(
-    const struct dbAddr *paddr,struct dbr_grDouble *pgd)
+void epicsShareAPI recGblGetGraphicDouble(const struct dbAddr *paddr,
+    struct dbr_grDouble *pgd)
 {
     dbFldDes *pdbFldDes = paddr->pfldDes;
 
-    getMaxRangeValues(pdbFldDes->field_type,&pgd->upper_disp_limit,
-	&pgd->lower_disp_limit);
-
-    return;
+    getMaxRangeValues(pdbFldDes->field_type,
+        &pgd->upper_disp_limit, &pgd->lower_disp_limit);
 }
 
-void epicsShareAPI recGblGetAlarmDouble(
-    const struct dbAddr *paddr,struct dbr_alDouble *pad)
+void epicsShareAPI recGblGetAlarmDouble(const struct dbAddr *paddr,
+    struct dbr_alDouble *pad)
 {
-    pad->upper_alarm_limit = 0;
-    pad->upper_warning_limit = 0;
-    pad->lower_warning_limit = 0;
-    pad->lower_alarm_limit = 0;
-
-    return;
+    pad->upper_alarm_limit   = epicsNAN;
+    pad->upper_warning_limit = epicsNAN;
+    pad->lower_warning_limit = epicsNAN;
+    pad->lower_alarm_limit   = epicsNAN;
 }
 
-void epicsShareAPI recGblGetControlDouble(
-    const struct dbAddr *paddr,struct dbr_ctrlDouble *pcd)
+void epicsShareAPI recGblGetControlDouble(const struct dbAddr *paddr,
+    struct dbr_ctrlDouble *pcd)
 {
-    dbFldDes *pdbFldDes=paddr->pfldDes;
-
-    getMaxRangeValues(pdbFldDes->field_type,&pcd->upper_ctrl_limit,
-	&pcd->lower_ctrl_limit);
+    dbFldDes *pdbFldDes = paddr->pfldDes;
 
-    return;
+    getMaxRangeValues(pdbFldDes->field_type,
+        &pcd->upper_ctrl_limit, &pcd->lower_ctrl_limit);
 }
 
 int  epicsShareAPI recGblInitConstantLink(
@@ -319,40 +312,39 @@ static void getMaxRangeValues(short field_type, double *pupper_limit,
     double *plower_limit)
 {
     switch(field_type){
-    case(DBF_CHAR):
-         *pupper_limit = -128.0;
-         *plower_limit = 127.0;
-         break;
-    case(DBF_UCHAR):
-         *pupper_limit = 255.0;
-         *plower_limit = 0.0;
-         break;
-    case(DBF_SHORT):
-         *pupper_limit = (double)SHRT_MAX;
-         *plower_limit = (double)SHRT_MIN;
-         break;
-    case(DBF_ENUM):
-    case(DBF_USHORT):
-         *pupper_limit = (double)USHRT_MAX;
-         *plower_limit = (double)0;
-         break;
-    case(DBF_LONG):
-	/* long did not work using cast to double */
-         *pupper_limit = 2147483647.;
-         *plower_limit = -2147483648.;
-         break;
-    case(DBF_ULONG):
-         *pupper_limit = (double)ULONG_MAX;
-         *plower_limit = (double)0;
-         break;
-    case(DBF_FLOAT):
-         *pupper_limit = (double)1e+30;
-         *plower_limit = (double)-1e30;
-         break;
-    case(DBF_DOUBLE):
-         *pupper_limit = (double)1e+30;
-         *plower_limit = (double)-1e30;
-         break;
+    case DBF_CHAR:
+        *pupper_limit = -128.0;
+        *plower_limit = 127.0;
+        break;
+    case DBF_UCHAR:
+        *pupper_limit = 255.0;
+        *plower_limit = 0.0;
+        break;
+    case DBF_SHORT:
+        *pupper_limit = (double) SHRT_MAX;
+        *plower_limit = (double) SHRT_MIN;
+        break;
+    case DBF_ENUM:
+    case DBF_USHORT:
+        *pupper_limit = (double) USHRT_MAX;
+        *plower_limit = 0.0;
+        break;
+    case DBF_LONG:
+        *pupper_limit = 2147483647.0;
+        *plower_limit = -2147483648.0;
+        break;
+    case DBF_ULONG:
+        *pupper_limit = (double) 0xffffffffU;
+        *plower_limit = 0.0;
+        break;
+    case DBF_FLOAT:
+        *pupper_limit = 1e30;
+        *plower_limit = -1e30;
+        break;
+    case DBF_DOUBLE:
+        *pupper_limit = 1e300;
+        *plower_limit = -1e300;
+        break;
     }
     return;
 }
-- 
GitLab