Implement 64-bit database field types.

Incorporates major reworking of the dbConvert.c file.
if the 64-bit stuff gets rejected most of that should
get pulled in anyway.
This commit is contained in:
Andrew Johnson
2014-07-10 18:13:28 -05:00
parent e95fcb2e06
commit 2fb0b0763d
19 changed files with 3142 additions and 5417 deletions

View File

@@ -78,6 +78,8 @@ static short mapDBFToDBR[DBF_NTYPES] = {
/* DBF_USHORT => */ DBR_USHORT,
/* DBF_LONG => */ DBR_LONG,
/* DBF_ULONG => */ DBR_ULONG,
/* DBF_INT64 => */ DBR_INT64,
/* DBF_UINT64 => */ DBR_UINT64,
/* DBF_FLOAT => */ DBR_FLOAT,
/* DBF_DOUBLE => */ DBR_DOUBLE,
/* DBF_ENUM, => */ DBR_ENUM,
@@ -693,6 +695,8 @@ long dbValueSize(short dbr_type)
sizeof(epicsUInt16), /* USHORT */
sizeof(epicsInt32), /* LONG */
sizeof(epicsUInt32), /* ULONG */
sizeof(epicsInt64), /* INT64 */
sizeof(epicsUInt64), /* UINT64 */
sizeof(epicsFloat32), /* FLOAT */
sizeof(epicsFloat64), /* DOUBLE */
sizeof(epicsEnum16)}; /* ENUM */

View File

@@ -454,6 +454,8 @@ static short mapDBFToDBR[DBF_NTYPES] =
/* DBF_USHORT => */DBR_USHORT,
/* DBF_LONG => */DBR_LONG,
/* DBF_ULONG => */DBR_ULONG,
/* DBF_INT64 => */DBR_INT64,
/* DBF_UINT64 => */DBR_UINT64,
/* DBF_FLOAT => */DBR_FLOAT,
/* DBF_DOUBLE => */DBR_DOUBLE,
/* DBF_ENUM, => */DBR_ENUM,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,7 @@
#include <string.h>
#include <ctype.h>
#include "cvtFast.h"
#include "dbDefs.h"
#include "ellLib.h"
#include "epicsMutex.h"
@@ -72,13 +73,13 @@ static void dbpr_msg_flush(TAB_BUFFER *pMsgBuff,int tab_size);
static char *dbf[DBF_NTYPES] = {
"STRING","CHAR","UCHAR","SHORT","USHORT","LONG","ULONG",
"FLOAT","DOUBLE","ENUM","MENU","DEVICE",
"INT64","UINT64","FLOAT","DOUBLE","ENUM","MENU","DEVICE",
"INLINK","OUTLINK","FWDLINK","NOACCESS"
};
static char *dbr[DBR_ENUM+2] = {
"STRING","CHAR","UCHAR","SHORT","USHORT","LONG","ULONG",
"FLOAT","DOUBLE","ENUM","NOACCESS"
"INT64","UINT64","FLOAT","DOUBLE","ENUM","NOACCESS"
};
long dba(const char*pname)
@@ -484,6 +485,16 @@ long dbtgf(const char *pname)
status = dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements,NULL);
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements,pMsgBuff,tab_size);
dbr_type = DBR_INT64;
no_elements = MIN(addr.no_elements,((sizeof(buffer))/sizeof(epicsInt64)));
status = dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements,NULL);
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements,pMsgBuff,tab_size);
dbr_type = DBR_UINT64;
no_elements = MIN(addr.no_elements,((sizeof(buffer))/sizeof(epicsUInt64)));
status = dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements,NULL);
printBuffer(status,dbr_type,pbuffer,0L,0L,no_elements,pMsgBuff,tab_size);
dbr_type = DBR_FLOAT;
no_elements = MIN(addr.no_elements,((sizeof(buffer))/sizeof(epicsFloat32)));
status = dbGetField(&addr,dbr_type,pbuffer,&ret_options,&no_elements,NULL);
@@ -510,17 +521,7 @@ long dbtpf(const char *pname, const char *pvalue)
long buffer[100];
long *pbuffer = buffer;
DBADDR addr;
long status = 0;
long options, no_elements;
char *pend;
long val_long;
int validLong;
unsigned long val_ulong;
int validULong;
int valid = 1;
int put_type;
epicsFloat32 fvalue;
epicsFloat64 dvalue;
static TAB_BUFFER msg_Buff;
TAB_BUFFER *pMsgBuff = &msg_Buff;
char *pmsg = pMsgBuff->message;
@@ -530,91 +531,90 @@ long dbtpf(const char *pname, const char *pvalue)
printf("Usage: dbtpf \"pv name\", \"value\"\n");
return 1;
}
if (nameToAddr(pname, &addr))
return -1;
val_long = strtol(pvalue, &pend, 10);
validLong = (*pend == 0);
val_ulong = strtoul(pvalue, &pend, 10);
validULong = (*pend == 0);
for (put_type = DBR_STRING; put_type <= DBF_ENUM; put_type++) {
union {
epicsInt8 i8;
epicsUInt8 u8;
epicsInt16 i16;
epicsUInt16 u16;
epicsInt32 i32;
epicsUInt32 u32;
epicsInt64 i64;
epicsUInt64 u64;
epicsFloat32 f32;
epicsFloat64 f64;
epicsEnum16 e16;
} val;
const void *pval = &val;
int valid = 1;
switch (put_type) {
case DBR_STRING:
status = dbPutField(&addr, put_type, pvalue, 1L);
pval = pvalue;
break;
case DBR_CHAR:
if ((valid = validLong)) {
epicsInt8 val_i8 = (epicsInt8)val_long;
status = dbPutField(&addr, put_type, &val_i8, 1L);
}
valid = !epicsParseInt8(pvalue, &val.i8, 10, NULL);
break;
case DBR_UCHAR:
if ((valid = validULong)) {
epicsUInt8 val_u8 = (epicsUInt8)val_ulong;
status = dbPutField(&addr, put_type, &val_u8, 1L);
}
valid = !epicsParseUInt8(pvalue, &val.u8, 10, NULL);
break;
case DBR_SHORT:
if ((valid = validLong)) {
epicsInt16 val_i16 = (epicsInt16) val_long;
status = dbPutField(&addr, put_type, &val_i16,1L);
}
valid = !epicsParseInt16(pvalue, &val.i16, 10, NULL);
break;
case DBR_USHORT:
if ((valid = validULong)) {
epicsUInt16 val_u16 = (epicsUInt16) val_ulong;
status = dbPutField(&addr, put_type, &val_u16, 1L);
}
valid = !epicsParseUInt16(pvalue, &val.u16, 10, NULL);
break;
case DBR_LONG:
if ((valid = validLong)) {
epicsInt32 val_i32 = val_long;
status = dbPutField(&addr, put_type,&val_i32,1L);
}
valid = !epicsParseInt32(pvalue, &val.i32, 10, NULL);
break;
case DBR_ULONG:
if ((valid = validULong)) {
epicsUInt32 val_u32 = val_ulong;
status = dbPutField(&addr, put_type, &val_u32, 1L);
}
valid = !epicsParseUInt32(pvalue, &val.u32, 10, NULL);
break;
case DBR_INT64:
valid = !epicsParseInt64(pvalue, &val.i64, 10, NULL);
break;
case DBR_UINT64:
valid = !epicsParseUInt64(pvalue, &val.u64, 10, NULL);
break;
case DBR_FLOAT:
if ((valid = epicsScanFloat(pvalue, &fvalue) == 1))
status = dbPutField(&addr, put_type, &fvalue, 1L);
valid = !epicsParseFloat32(pvalue, &val.f32, NULL);
break;
case DBR_DOUBLE:
if ((valid = epicsScanDouble(pvalue, &dvalue) == 1))
status = dbPutField(&addr, put_type, &dvalue, 1L);
valid = !epicsParseFloat64(pvalue, &val.f64, NULL);
break;
case DBR_ENUM:
if ((valid = validULong)) {
epicsEnum16 val_e16 = (epicsEnum16) val_ulong;
status = dbPutField(&addr, put_type, &val_e16, 1L);
}
valid = !epicsParseUInt16(pvalue, &val.e16, 10, NULL);
break;
}
if (valid) {
long status = dbPutField(&addr, put_type, pval, 1);
if (status) {
printf("Put as DBR_%s Failed.\n", dbr[put_type]);
} else {
printf("Put as DBR_%-6s Ok, result as ", dbr[put_type]);
no_elements = MIN(addr.no_elements,
printf("Put as DBR_%-6s Failed.\n", dbr[put_type]);
}
else {
long options = 0;
long no_elements = MIN(addr.no_elements,
((sizeof(buffer))/addr.field_size));
options = 0;
printf("Put as DBR_%-6s Ok, result as ", dbr[put_type]);
status = dbGetField(&addr, addr.dbr_field_type, pbuffer,
&options, &no_elements, NULL);
printBuffer(status, addr.dbr_field_type, pbuffer, 0L, 0L,
no_elements, pMsgBuff, tab_size);
}
}
else {
printf("Cvt to DBR_%s failed.\n", dbr[put_type]);
}
}
pmsg[0] = '\0';
dbpr_msgOut(pMsgBuff, tab_size);
return(0);
return 0;
}
long dbior(const char *pdrvName,int interest_level)
@@ -732,10 +732,8 @@ static void printBuffer(
long status, short dbr_type, void *pbuffer, long reqOptions,
long retOptions, long no_elements, TAB_BUFFER *pMsgBuff, int tab_size)
{
epicsInt32 val_i32;
epicsUInt32 val_u32;
char *pmsg = pMsgBuff->message;
size_t i, len;
int i;
if (reqOptions & DBR_STATUS) {
if (retOptions & DBR_STATUS) {
@@ -898,221 +896,166 @@ static void printBuffer(
if (no_elements == 0)
return;
switch (dbr_type) {
case (DBR_STRING):
if (no_elements == 1)
sprintf(pmsg, "DBR_STRING: ");
else
sprintf(pmsg, "DBR_STRING[%ld]: ", no_elements);
dbpr_msgOut(pMsgBuff, tab_size);
if (status != 0) {
sprintf(pmsg, "DBR_STRING: failed.");
dbpr_msgOut(pMsgBuff, tab_size);
break;
}
if (no_elements == 1)
sprintf(pmsg, "DBF_%s: ", dbr[dbr_type]);
else
sprintf(pmsg, "DBF_%s[%ld]: ", dbr[dbr_type], no_elements);
dbpr_msgOut(pMsgBuff, tab_size);
for(i=0; i<no_elements; i++) {
len = strlen(pbuffer);
if (len > 0) {
sprintf(pmsg, " \"%s\"", (char *)pbuffer);
if (status != 0) {
strcpy(pmsg, "failed.");
dbpr_msgOut(pMsgBuff, tab_size);
}
else {
switch (dbr_type) {
case DBR_STRING:
for(i=0; i<no_elements; i++) {
size_t len = strlen(pbuffer);
strcpy(pmsg, "\"");
epicsStrnEscapedFromRaw(pmsg+1, MAXLINE - 3,
(char *)pbuffer, len);
strcat(pmsg, "\"");
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + MAX_STRING_SIZE;
}
pbuffer = (char *)pbuffer + MAX_STRING_SIZE;
}
break;
case (DBR_CHAR):
if (no_elements == 1)
sprintf(pmsg, "DBR_CHAR: ");
else
sprintf(pmsg, "DBR_CHAR[%ld]: ", no_elements);
dbpr_msgOut(pMsgBuff, tab_size);
if (status != 0) {
sprintf(pmsg, " failed.");
dbpr_msgOut(pMsgBuff, tab_size);
break;
}
if (no_elements == 1) {
val_i32 = *(epicsInt8 *) pbuffer;
sprintf(pmsg, "%-9d 0x%-9x", val_i32, val_i32);
dbpr_msgOut(pMsgBuff, tab_size);
}
else {
for (i = 0; i < no_elements; i+= MAXLINE - 5) {
int width = no_elements - i;
if (width > MAXLINE - 5) width = MAXLINE - 5;
sprintf(pmsg, " \"%.*s\"", width, (char *)pbuffer + i);
if (i + MAXLINE - 5 < no_elements) strcat(pmsg, " +");
case DBR_CHAR:
if (no_elements == 1) {
epicsInt32 val = *(epicsInt8 *) pbuffer;
if (isprint(val))
sprintf(pmsg, "%d = 0x%x = '%c'", val, val & 0xff, val);
else
sprintf(pmsg, "%d = 0x%x", val, val & 0xff);
dbpr_msgOut(pMsgBuff, tab_size);
} else {
size_t len = epicsStrnLen(pbuffer, no_elements);
i = 0;
while (len > 0) {
int chunk = (len > MAXLINE - 5) ? MAXLINE - 5 : len;
sprintf(pmsg, "\"%.*s\"", chunk, (char *)pbuffer + i);
len -= chunk;
if (len > 0)
strcat(pmsg, " +");
dbpr_msgOut(pMsgBuff, tab_size);
}
}
}
break;
break;
case (DBR_UCHAR):
if (no_elements == 1)
sprintf(pmsg, "DBR_UCHAR: ");
else
sprintf(pmsg, "DBR_UCHAR[%ld]: ", no_elements);
dbpr_msgOut(pMsgBuff, tab_size);
if (status != 0) {
sprintf(pmsg, " failed.");
case DBR_UCHAR:
for (i = 0; i < no_elements; i++) {
epicsUInt32 val = *(epicsUInt8 *) pbuffer;
sprintf(pmsg, "%u = 0x%x", val, val);
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsUInt8);
}
break;
case DBR_SHORT:
for (i = 0; i < no_elements; i++) {
epicsInt32 val = *(epicsInt16 *) pbuffer;
sprintf(pmsg, "%hd = 0x%hx", val, val);
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsInt16);
}
break;
case DBR_USHORT:
for (i = 0; i < no_elements; i++) {
epicsUInt32 val = *(epicsUInt16 *) pbuffer;
sprintf(pmsg, "%hu = 0x%hx", val, val);
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsUInt16);
}
break;
case DBR_LONG:
for (i = 0; i < no_elements; i++) {
epicsInt32 val = *(epicsInt32 *) pbuffer;
sprintf(pmsg, "%d = 0x%x", val, val);
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsInt32);
}
break;
case DBR_ULONG:
for (i = 0; i < no_elements; i++) {
epicsUInt32 val = *(epicsUInt32 *) pbuffer;
sprintf(pmsg, "%u = 0x%x", val, val);
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsUInt32);
}
break;
case DBR_INT64:
for (i = 0; i < no_elements; i++) {
epicsInt64 val = *(epicsInt64 *) pbuffer;
pmsg += cvtInt64ToString(val, pmsg);
strcpy(pmsg, " = ");
pmsg += 3;
cvtInt64ToHexString(val, pmsg);
dbpr_msgOut(pMsgBuff, tab_size);
pmsg = pMsgBuff->message;
pbuffer = (char *)pbuffer + sizeof(epicsInt64);
}
break;
case DBR_UINT64:
for (i = 0; i < no_elements; i++) {
epicsUInt64 val = *(epicsUInt64 *) pbuffer;
pmsg += cvtUInt64ToString(val, pmsg);
strcpy(pmsg, " = ");
pmsg += 3;
cvtUInt64ToHexString(val, pmsg);
dbpr_msgOut(pMsgBuff, tab_size);
pmsg = pMsgBuff->message;
pbuffer = (char *)pbuffer + sizeof(epicsUInt64);
}
break;
case DBR_FLOAT:
for (i = 0; i < no_elements; i++) {
sprintf(pmsg, "%.6g", *((epicsFloat32 *) pbuffer));
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsFloat32);
}
break;
case DBR_DOUBLE:
for (i = 0; i < no_elements; i++) {
sprintf(pmsg, "%.12g", *((epicsFloat64 *) pbuffer));
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsFloat64);
}
break;
case DBR_ENUM:
for (i = 0; i < no_elements; i++) {
sprintf(pmsg, "%u", *((epicsEnum16 *) pbuffer));
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsEnum16);
}
break;
default:
sprintf(pmsg, "Bad DBR type %d", dbr_type);
dbpr_msgOut(pMsgBuff, tab_size);
break;
}
for (i = 0; i < no_elements; i++) {
val_u32 = *(epicsUInt8 *) pbuffer;
sprintf(pmsg, "%-9u 0x%-9x", val_u32, val_u32);
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsUInt8);
}
break;
case (DBR_SHORT):
if (no_elements == 1)
sprintf(pmsg, "DBR_SHORT: ");
else
sprintf(pmsg, "DBR_SHORT[%ld]: ", no_elements);
dbpr_msgOut(pMsgBuff, tab_size);
if (status != 0) {
sprintf(pmsg, " failed.");
dbpr_msgOut(pMsgBuff, tab_size);
break;
}
for (i = 0; i < no_elements; i++) {
val_i32 = *(epicsInt16 *) pbuffer;
sprintf(pmsg, "%-9d 0x%-9x", val_i32, val_i32);
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsInt16);
}
break;
case (DBR_USHORT):
if (no_elements == 1)
sprintf(pmsg, "DBR_USHORT: ");
else
sprintf(pmsg, "DBR_USHORT[%ld]: ", no_elements);
dbpr_msgOut(pMsgBuff, tab_size);
if (status != 0) {
sprintf(pmsg, " failed.");
dbpr_msgOut(pMsgBuff, tab_size);
break;
}
for (i = 0; i < no_elements; i++) {
val_u32 = *(epicsUInt16 *) pbuffer;
sprintf(pmsg, "%-9u 0x%-9x", val_u32, val_u32);
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsUInt16);
}
break;
case (DBR_LONG):
if (no_elements == 1)
sprintf(pmsg, "DBR_LONG: ");
else
sprintf(pmsg, "DBR_LONG[%ld]: ", no_elements);
dbpr_msgOut(pMsgBuff, tab_size);
if (status != 0) {
sprintf(pmsg, " failed.");
dbpr_msgOut(pMsgBuff, tab_size);
break;
}
for (i = 0; i < no_elements; i++) {
val_i32 = *(epicsInt32 *) pbuffer;
sprintf(pmsg, "%-9d 0x%-9x", val_i32, val_i32);
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsInt32);
}
break;
case (DBR_ULONG):
if (no_elements == 1)
sprintf(pmsg, "DBR_ULONG: ");
else
sprintf(pmsg, "DBR_ULONG[%ld]: ", no_elements);
dbpr_msgOut(pMsgBuff, tab_size);
if (status != 0) {
sprintf(pmsg, " failed.");
dbpr_msgOut(pMsgBuff, tab_size);
break;
}
for (i = 0; i < no_elements; i++) {
val_u32 = *(epicsUInt32 *) pbuffer;
sprintf(pmsg, "%-9u 0x%-9x", val_u32, val_u32);
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsUInt32);
}
break;
case (DBR_FLOAT):
if (no_elements == 1)
sprintf(pmsg, "DBR_FLOAT: ");
else
sprintf(pmsg, "DBR_FLOAT[%ld]: ", no_elements);
dbpr_msgOut(pMsgBuff, tab_size);
if (status != 0) {
sprintf(pmsg, " failed.");
dbpr_msgOut(pMsgBuff, tab_size);
break;
}
for (i = 0; i < no_elements; i++) {
sprintf(pmsg, "%-13.6g", *((epicsFloat32 *) pbuffer));
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsFloat32);
}
break;
case (DBR_DOUBLE):
if (no_elements == 1)
sprintf(pmsg, "DBR_DOUBLE: ");
else
sprintf(pmsg, "DBR_DOUBLE[%ld]: ", no_elements);
dbpr_msgOut(pMsgBuff, tab_size);
if (status != 0) {
sprintf(pmsg, " failed.");
dbpr_msgOut(pMsgBuff, tab_size);
break;
}
for (i = 0; i < no_elements; i++) {
sprintf(pmsg, "%-13.6g", *((epicsFloat64 *) pbuffer));
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsFloat64);
}
break;
case (DBR_ENUM):
if (no_elements == 1)
sprintf(pmsg, "DBR_ENUM: ");
else
sprintf(pmsg, "DBR_ENUM[%ld]: ", no_elements);
dbpr_msgOut(pMsgBuff, tab_size);
if (status != 0) {
sprintf(pmsg, " failed.");
dbpr_msgOut(pMsgBuff, tab_size);
break;
}
for (i = 0; i < no_elements; i++) {
sprintf(pmsg, "%-9u", *((epicsEnum16 *) pbuffer));
dbpr_msgOut(pMsgBuff, tab_size);
pbuffer = (char *)pbuffer + sizeof(epicsEnum16);
}
break;
default:
printf(" illegal request type.");
break;
}
dbpr_msg_flush(pMsgBuff, tab_size);
return;
}
static int dbpr_report(
@@ -1144,7 +1087,6 @@ static int dbpr_report(
pfield = ((char *)paddr->precord) + pdbFldDes->offset;
if (pdbFldDes->interest > interest_level )
continue;
switch (pdbFldDes->field_type) {
case DBF_STRING:
case DBF_USHORT:
@@ -1155,6 +1097,8 @@ static int dbpr_report(
case DBF_SHORT:
case DBF_LONG:
case DBF_ULONG:
case DBF_INT64:
case DBF_UINT64:
case DBF_DOUBLE:
case DBF_MENU:
case DBF_DEVICE:

View File

@@ -23,8 +23,8 @@ epicsShareExtern struct dbBase *pdbbase;
epicsShareExtern volatile int interruptAccept;
/*Definitions that allow old database access to use new conversion routines*/
#define newDBF_DEVICE 11
#define newDBR_ENUM 9
#define newDBF_DEVICE 13
#define newDBR_ENUM 11
epicsShareExtern long (*dbGetConvertRoutine[newDBF_DEVICE+1][newDBR_ENUM+1])
(struct dbAddr *paddr, void *pbuffer,long nRequest,
long no_elements, long offset);
@@ -43,11 +43,11 @@ epicsShareExtern unsigned short dbDBRnewToDBRold[newDBR_ENUM+1];
epicsShareDef unsigned short dbDBRoldToDBFnew[DBR_DOUBLE+1] = {
0, /*DBR_STRING to DBF_STRING*/
3, /*DBR_INT to DBF_SHORT*/
7, /*DBR_FLOAT to DBF_FLOAT*/
9, /*DBR_ENUM to DBF_ENUM*/
9, /*DBR_FLOAT to DBF_FLOAT*/
11, /*DBR_ENUM to DBF_ENUM*/
1, /*DBR_CHAR to DBF_CHAR*/
5, /*DBR_LONG to DBF_LONG*/
8 /*DBR_DOUBLE to DBF_DOUBLE*/
10 /*DBR_DOUBLE to DBF_DOUBLE*/
};
epicsShareDef unsigned short dbDBRnewToDBRold[newDBR_ENUM+1] = {
0, /*DBR_STRING to DBR_STRING*/
@@ -57,6 +57,8 @@ epicsShareDef unsigned short dbDBRnewToDBRold[newDBR_ENUM+1] = {
5, /*DBR_USHORT to DBR_LONG*/
5, /*DBR_LONG to DBR_LONG*/
6, /*DBR_ULONG to DBR_DOUBLE*/
6, /*DBR_INT64 to DBR_DOUBLE*/
6, /*DBR_UINT64 to DBR_DOUBLE*/
2, /*DBR_FLOAT to DBR_FLOAT*/
6, /*DBR_DOUBLE to DBR_DOUBLE*/
3, /*DBR_ENUM to DBR_ENUM*/

View File

@@ -1,10 +1,9 @@
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE Versions 3.13.7
# and higher are distributed subject to a Software License Agreement found
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
menu(menuFtype) {
@@ -15,6 +14,8 @@ menu(menuFtype) {
choice(menuFtypeUSHORT,"USHORT")
choice(menuFtypeLONG,"LONG")
choice(menuFtypeULONG,"ULONG")
choice(menuFtypeINT64,"INT64")
choice(menuFtypeUINT64,"UINT64")
choice(menuFtypeFLOAT,"FLOAT")
choice(menuFtypeDOUBLE,"DOUBLE")
choice(menuFtypeENUM,"ENUM")

View File

@@ -120,6 +120,8 @@ void recGblGetPrec(const struct dbAddr *paddr, long *precision)
case DBF_USHORT:
case DBF_LONG:
case DBF_ULONG:
case DBF_INT64:
case DBF_UINT64:
*precision = 0;
break;
@@ -325,7 +327,15 @@ static void getMaxRangeValues(short field_type, double *pupper_limit,
*plower_limit = -2147483648.0;
break;
case DBF_ULONG:
*pupper_limit = (double) 0xffffffffU;
*pupper_limit = 4294967295.0;
*plower_limit = 0.0;
break;
case DBF_INT64:
*pupper_limit = 9223372036854775808.0;
*plower_limit = -9223372036854775808.0;
break;
case DBF_UINT64:
*pupper_limit = 18446744073709551615.0;
*plower_limit = 0.0;
break;
case DBF_FLOAT:

View File

@@ -29,6 +29,8 @@ typedef enum {
DBF_USHORT,
DBF_LONG,
DBF_ULONG,
DBF_INT64,
DBF_UINT64,
DBF_FLOAT,
DBF_DOUBLE,
DBF_ENUM,
@@ -56,6 +58,8 @@ epicsShareDef mapdbfType pamapdbfType[DBF_NTYPES] = {
{"DBF_USHORT",DBF_USHORT},
{"DBF_LONG",DBF_LONG},
{"DBF_ULONG",DBF_ULONG},
{"DBF_INT64",DBF_INT64},
{"DBF_UINT64",DBF_UINT64},
{"DBF_FLOAT",DBF_FLOAT},
{"DBF_DOUBLE",DBF_DOUBLE},
{"DBF_ENUM",DBF_ENUM},
@@ -76,6 +80,8 @@ epicsShareDef mapdbfType pamapdbfType[DBF_NTYPES] = {
#define DBR_USHORT DBF_USHORT
#define DBR_LONG DBF_LONG
#define DBR_ULONG DBF_ULONG
#define DBR_INT64 DBF_INT64
#define DBR_UINT64 DBF_UINT64
#define DBR_FLOAT DBF_FLOAT
#define DBR_DOUBLE DBF_DOUBLE
#define DBR_ENUM DBF_ENUM

View File

@@ -227,7 +227,7 @@ void dbMsgPrint(DBENTRY *pdbentry, const char *fmt, ...)
va_end(args);
}
static void ulongToHexString(epicsUInt32 source,char *pdest)
static void ulongToHexString(epicsUInt32 source, char *pdest)
{
static const char hex_digit_to_ascii[16] = "0123456789abcdef";
epicsUInt32 val,temp;
@@ -1854,6 +1854,8 @@ char * dbGetString(DBENTRY *pdbentry)
case DBF_ENUM:
case DBF_LONG:
case DBF_ULONG:
case DBF_INT64:
case DBF_UINT64:
case DBF_FLOAT:
case DBF_DOUBLE:
case DBF_MENU:
@@ -2011,60 +2013,72 @@ char *dbGetStringNum(DBENTRY *pdbentry)
cvttype = pflddes->base;
switch (pflddes->field_type) {
case DBF_CHAR:
if (cvttype==CT_DECIMAL)
cvtCharToString(*(char*)pfield, message);
if (cvttype == CT_DECIMAL)
cvtCharToString(*(char *) pfield, message);
else
ulongToHexString((epicsUInt32)(*(char*)pfield),message);
ulongToHexString(*(char *) pfield, message);
break;
case DBF_UCHAR:
if (cvttype==CT_DECIMAL)
cvtUcharToString(*(unsigned char*)pfield, message);
cvtUcharToString(*(epicsUInt8 *) pfield, message);
else
ulongToHexString((epicsUInt32)(*(unsigned char*)pfield),message);
ulongToHexString(*(epicsUInt8 *) pfield, message);
break;
case DBF_SHORT:
if (cvttype==CT_DECIMAL)
cvtShortToString(*(short*)pfield, message);
cvtShortToString(*(epicsInt16 *) pfield, message);
else
ulongToHexString((epicsUInt32)(*(short*)pfield),message);
ulongToHexString(*(epicsInt16 *) pfield, message);
break;
case DBF_USHORT:
case DBF_ENUM:
if (cvttype==CT_DECIMAL)
cvtUshortToString(*(unsigned short*)pfield, message);
cvtUshortToString(*(epicsUInt16 *) pfield, message);
else
ulongToHexString((epicsUInt32)(*(unsigned short*)pfield),message);
ulongToHexString(*(epicsUInt16 *) pfield, message);
break;
case DBF_LONG:
if (cvttype==CT_DECIMAL)
cvtLongToString(*(epicsInt32*)pfield, message);
cvtLongToString(*(epicsInt32 *) pfield, message);
else
ulongToHexString((epicsUInt32)(*(epicsInt32*)pfield), message);
ulongToHexString(*(epicsInt32 *) pfield, message);
break;
case DBF_ULONG:
if (cvttype==CT_DECIMAL)
cvtUlongToString(*(epicsUInt32 *)pfield, message);
cvtUlongToString(*(epicsUInt32 *) pfield, message);
else
ulongToHexString(*(epicsUInt32*)pfield, message);
ulongToHexString(*(epicsUInt32 *) pfield, message);
break;
case DBF_INT64:
if (cvttype==CT_DECIMAL)
cvtInt64ToString(*(epicsInt64 *) pfield, message);
else
cvtInt64ToHexString(*(epicsInt64 *) pfield, message);
break;
case DBF_UINT64:
if (cvttype==CT_DECIMAL)
cvtUInt64ToString(*(epicsUInt32 *) pfield, message);
else
cvtUInt64ToHexString(*(epicsUInt32 *) pfield, message);
break;
case DBF_FLOAT:
floatToString(*(float *)pfield,message);
floatToString(*(epicsFloat32 *) pfield, message);
break;
case DBF_DOUBLE:
doubleToString(*(double *)pfield,message);
doubleToString(*(epicsFloat64 *) pfield, message);
break;
case DBF_MENU:
{
dbMenu *pdbMenu = (dbMenu *)pflddes->ftPvt;
short choice_ind;
char *pchoice;
dbMenu *pdbMenu = (dbMenu *)pflddes->ftPvt;
epicsEnum16 choice_ind;
char *pchoice;
if (!pfield) {
dbMsgCpy(pdbentry, "Field not found");
return message;
}
choice_ind = *((short *) pdbentry->pfield);
if (!pdbMenu || choice_ind<0 || choice_ind>=pdbMenu->nChoice)
choice_ind = *((epicsEnum16 *) pdbentry->pfield);
if (!pdbMenu || choice_ind < 0 || choice_ind >= pdbMenu->nChoice)
return NULL;
pchoice = pdbMenu->papChoiceValue[choice_ind];
dbMsgCpy(pdbentry, pchoice);
@@ -2072,9 +2086,9 @@ char *dbGetStringNum(DBENTRY *pdbentry)
break;
case DBF_DEVICE:
{
dbDeviceMenu *pdbDeviceMenu;
char *pchoice;
short choice_ind;
dbDeviceMenu *pdbDeviceMenu;
epicsEnum16 choice_ind;
char *pchoice;
if (!pfield) {
dbMsgCpy(pdbentry, "Field not found");
@@ -2083,7 +2097,7 @@ char *dbGetStringNum(DBENTRY *pdbentry)
pdbDeviceMenu = dbGetDeviceMenu(pdbentry);
if (!pdbDeviceMenu)
return NULL;
choice_ind = *((short *) pdbentry->pfield);
choice_ind = *((epicsEnum16 *) pdbentry->pfield);
if (choice_ind<0 || choice_ind>=pdbDeviceMenu->nChoice)
return NULL;
pchoice = pdbDeviceMenu->papChoice[choice_ind];
@@ -2483,9 +2497,11 @@ long dbPutString(DBENTRY *pdbentry,const char *pstring)
case DBF_CHAR:
case DBF_SHORT:
case DBF_LONG:
case DBF_INT64:
case DBF_UCHAR:
case DBF_USHORT:
case DBF_ULONG:
case DBF_UINT64:
case DBF_ENUM:
case DBF_FLOAT:
case DBF_DOUBLE:
@@ -2536,189 +2552,6 @@ long dbPutString(DBENTRY *pdbentry,const char *pstring)
return(status);
}
char * dbVerify(DBENTRY *pdbentry,const char *pstring)
{
dbFldDes *pflddes = pdbentry->pflddes;
char *message;
int stringHasMacro=FALSE;
stringHasMacro = strstr(pstring,"$(") || strstr(pstring,"${");
message = getpMessage(pdbentry);
if(!pflddes) {strcpy(message,"fldDes not found"); return(message);}
if(strstr(pstring,"$(") || strstr(pstring,"${")) return(NULL);
switch (pflddes->field_type) {
case DBF_STRING: {
size_t length;
length=strlen(pstring);
if(length>=pflddes->size) {
sprintf(message,"string to big. max=%hd",pflddes->size);
return(message);
}
if((pflddes->special == SPC_CALC) && !stringHasMacro) {
char rpcl[RPCL_LEN];
short err;
long status;
status = postfix(pstring,rpcl,&err);
if(status) {
sprintf(message,"%s in CALC expression '%s'",
calcErrorStr(err), pstring);
return(message);
}
}
}
return(NULL);
case DBF_CHAR :
case DBF_SHORT :
case DBF_LONG:{
long value;
char *endp;
value = strtol(pstring,&endp,0);
if(*endp!=0) {
strcpy(message,"not an integer number");
return(message);
}
switch (pflddes->field_type) {
case DBF_CHAR :
if(value<-128 || value>127) {
strcpy(message,"must have -128<=value<=127");
return(message);
}
return(NULL);
case DBF_SHORT :
if(value<-32768 || value>32767) {
strcpy(message,"must have -32768<=value<=32767");
return(message);
}
return(NULL);
case DBF_LONG : return(NULL);
default:
errPrintf(-1,__FILE__, __LINE__,"Logic Error\n");
return(NULL);
}
}
case DBF_UCHAR:
case DBF_USHORT:
case DBF_ULONG:
case DBF_ENUM:{
unsigned long value;
char *endp;
if(strchr(pstring,'-')) {
strcpy(message,"not an unsigned number");
return(message);
}
value = strtoul(pstring,&endp,0);
if(*endp!=0) {
strcpy(message,"not an integer number");
return(message);
}
switch (pflddes->field_type) {
case DBF_UCHAR :
if(value>255) {
strcpy(message,"must have 0<=value<=255");
return(message);
}
return(NULL);
case DBF_ENUM:
case DBF_USHORT :
if(value>65535) {
strcpy(message,"must have 0<=value<=65535");
return(message);
}
return(NULL);
case DBF_ULONG : return(NULL);
default:
errPrintf(-1,__FILE__, __LINE__,"Logic Error\n");
return(NULL);
}
}
case DBF_FLOAT:
case DBF_DOUBLE: {
char *endp;
(void) epicsStrtod(pstring,&endp);
if(*endp!=0) {
strcpy(message,"not a number");
return(message);
}
return(NULL);
}
case DBF_MENU: {
dbMenu *pdbMenu = (dbMenu *)pflddes->ftPvt;
char *pchoice;
int i;
if(!pdbMenu) return(NULL);
for (i = 0; i < pdbMenu->nChoice; i++) {
if(!(pchoice = pdbMenu->papChoiceValue[i])) continue;
if(strcmp(pchoice, pstring) == 0) {
return(NULL);
}
}
}
strcpy(message,"Not a valid menu choice");
return (message);
case DBF_DEVICE: {
dbDeviceMenu *pdbDeviceMenu;
char *pchoice;
int i;
pdbDeviceMenu = dbGetDeviceMenu(pdbentry);
if(!pdbDeviceMenu) return(NULL);
if(pdbDeviceMenu->nChoice == 0) return(NULL);
for (i = 0; i < pdbDeviceMenu->nChoice; i++) {
if (!(pchoice = pdbDeviceMenu->papChoice[i]))
continue;
if (strcmp(pchoice, pstring) == 0) {
return(NULL);
}
}
}
strcpy(message,"Not a valid menu choice");
return (message);
case DBF_INLINK:
case DBF_OUTLINK:
case DBF_FWDLINK:
return(NULL);
default: break;
}
strcpy(message,"Not a valid field type");
return (message);
}
char *dbGetRange(DBENTRY *pdbentry)
{
dbFldDes *pflddes = pdbentry->pflddes;
char *message;
message = getpMessage(pdbentry);
if(!pflddes) {strcpy(message,"fldDes not found"); return(message);}
switch (pflddes->field_type) {
case DBF_STRING: {strcpy(message,"STRING"); return(message);}
case DBF_CHAR : {strcpy(message,"CHAR"); return(message);}
case DBF_SHORT : {strcpy(message,"SHORT");return(message);}
case DBF_LONG: {strcpy(message,"LONG"); return(message);}
case DBF_UCHAR: {strcpy(message,"UCHAR");return(message);}
case DBF_USHORT:{strcpy(message,"USHORT");return(message);}
case DBF_ULONG:{strcpy(message,"ULONG:");return(message);}
case DBF_ENUM: {strcpy(message,"ENUM");return(message);}
case DBF_FLOAT: {strcpy(message,"FLOAT");return(message);}
case DBF_DOUBLE: {strcpy(message,"DOUBLE");return(message);}
case DBF_MENU: {strcpy(message,"MENU");return(message);}
case DBF_DEVICE: {strcpy(message,"DEVICE");return(message);}
case DBF_INLINK: {strcpy(message,"INLINK");return(message);}
case DBF_OUTLINK: {strcpy(message,"OUTLINK");return(message);}
case DBF_FWDLINK: {strcpy(message,"FWDLINK");return(message);}
default:
errPrintf(-1,__FILE__, __LINE__,"Logic Error\n");
}
strcpy(message,"Not a valid field type");
return (message);
}
long dbFirstInfo(DBENTRY *pdbentry)
{
dbRecordNode *precnode = pdbentry->precnode;

View File

@@ -119,6 +119,8 @@ long dbAllocRecord(DBENTRY *pdbentry,const char *precordName)
case DBF_USHORT:
case DBF_LONG:
case DBF_ULONG:
case DBF_INT64:
case DBF_UINT64:
case DBF_FLOAT:
case DBF_DOUBLE:
case DBF_ENUM:
@@ -204,277 +206,291 @@ int dbIsMacroOk(DBENTRY *pdbentry) { return(FALSE); }
epicsShareFunc int dbIsDefaultValue(DBENTRY *pdbentry)
{
dbFldDes *pflddes = pdbentry->pflddes;
void *pfield = pdbentry->pfield;
dbFldDes *pflddes = pdbentry->pflddes;
void *pfield = pdbentry->pfield;
if (!pflddes || !pfield)
return FALSE;
if(!pflddes) return(FALSE);
if(!pfield) return(FALSE);
switch (pflddes->field_type) {
case (DBF_STRING) : {
char *p = (char *)pfield;
if(!pflddes->initial) return((strlen(p)==0) ? TRUE : FALSE);
return((strcmp(pflddes->initial,p)==0) ? TRUE : FALSE);
}
case DBF_CHAR: {
char field = *(char *)pfield;
long ltemp;
if(pflddes->initial) {
ltemp = strtol(pflddes->initial,NULL,0);
return((field==ltemp));
}
return((field==0));
}
case DBF_UCHAR: {
unsigned char field = *(unsigned char *)pfield;
unsigned long ltemp;
case DBF_STRING: {
char *p = (char *)pfield;
if(pflddes->initial) {
ltemp = strtoul(pflddes->initial,NULL,0);
return((field==ltemp));
}
return((field==0));
}
case DBF_SHORT: {
short field = *(short *)pfield;
long ltemp;
return pflddes->initial ? ! strcmp(pflddes->initial, p)
: ! strlen(p);
}
case DBF_CHAR: {
epicsInt8 field = *(epicsInt8 *)pfield;
epicsInt8 def;
if(pflddes->initial) {
ltemp = strtol(pflddes->initial,NULL,0);
return((field==ltemp));
}
return((field==0));
}
case DBF_USHORT: {
unsigned short field = *(unsigned short *)pfield;
unsigned long ltemp;
if (!pflddes->initial)
return field == 0;
if(pflddes->initial) {
ltemp = strtoul(pflddes->initial,NULL,0);
return((field==ltemp));
}
return((field==0));
}
case DBF_LONG: {
long field = *(long *)pfield;
long ltemp;
return ! epicsParseInt8(pflddes->initial, &def, 0, NULL)
&& field == def;
}
case DBF_UCHAR: {
epicsUInt8 field = *(epicsUInt8 *)pfield;
epicsUInt8 def;
if(pflddes->initial) {
ltemp = strtol(pflddes->initial,NULL,0);
return((field==ltemp));
}
return((field==0));
}
case DBF_ULONG: {
unsigned long field = *(unsigned long *)pfield;
unsigned long ltemp;
if (!pflddes->initial)
return field == 0;
if(pflddes->initial) {
ltemp = strtoul(pflddes->initial,NULL,0);
return((field==ltemp));
}
return((field==0));
}
case DBF_FLOAT: {
float field = *(float *)pfield;
double dtemp;
return ! epicsParseUInt8(pflddes->initial, &def, 0, NULL)
&& field == def;
}
case DBF_SHORT: {
epicsInt16 field = *(epicsInt16 *)pfield;
epicsInt16 def;
if(pflddes->initial) {
dtemp = epicsStrtod(pflddes->initial,NULL);
return((field==dtemp));
}
return((field==0.0));
}
case DBF_DOUBLE: {
double field = *(double *)pfield;
double dtemp;
if (!pflddes->initial)
return field == 0;
if(pflddes->initial) {
dtemp = epicsStrtod(pflddes->initial,NULL);
return((field==dtemp));
}
return((field==0.0));
}
case DBF_ENUM: {
unsigned short field = *(unsigned short *)pfield;
unsigned long ltemp;
return ! epicsParseInt16(pflddes->initial, &def, 0, NULL)
&& field == def;
}
case DBF_ENUM:
case DBF_USHORT: {
epicsUInt16 field = *(epicsUInt16 *)pfield;
epicsUInt16 def;
if(pflddes->initial) {
ltemp = strtoul(pflddes->initial,NULL,0);
return((field==ltemp));
}
return((field==0));
}
case DBF_MENU: {
unsigned short field = *(unsigned short *)pfield;
long value;
char *endp;
if (!pflddes->initial)
return field == 0;
if(pflddes->initial) {
value = dbGetMenuIndexFromString(pdbentry,pflddes->initial);
if(value==-1) {
value = strtol(pflddes->initial,&endp,0);
if(*endp!='\0') return(FALSE);
}
} else {
value = 0;
}
if((unsigned short)value == field) return(TRUE);
return(FALSE);
}
case DBF_DEVICE: {
dbRecordType *precordType = pdbentry->precordType;
return ! epicsParseUInt16(pflddes->initial, &def, 0, NULL)
&& field == def;
}
case DBF_LONG: {
epicsInt32 field = *(epicsInt32 *)pfield;
epicsInt32 def;
if(!precordType) {
epicsPrintf("dbIsDefaultValue: pdbRecordType is NULL??\n");
return(FALSE);
}
if(ellCount(&precordType->devList)==0) return(TRUE);
return(FALSE);
}
case DBF_INLINK:
case DBF_OUTLINK:
case DBF_FWDLINK: {
struct link *plink = (struct link *)pfield;
if (!pflddes->initial)
return field == 0;
if(!plink) return(FALSE);
if(plink->type!=CONSTANT) return(FALSE);
if(plink->value.constantStr == 0) return(TRUE);
if(!pflddes->initial) return(FALSE);
if(strcmp(plink->value.constantStr,pflddes->initial)==0)
return(TRUE);
return(FALSE);
}
default:
return(TRUE);
return ! epicsParseInt32(pflddes->initial, &def, 0, NULL)
&& field == def;
}
case DBF_ULONG: {
epicsUInt32 field = *(epicsUInt32 *)pfield;
epicsUInt32 def;
if (!pflddes->initial)
return field == 0;
return ! epicsParseUInt32(pflddes->initial, &def, 0, NULL)
&& field == def;
}
case DBF_INT64: {
epicsInt64 field = *(epicsInt64 *)pfield;
epicsInt64 def;
if (!pflddes->initial)
return field == 0;
return ! epicsParseInt64(pflddes->initial, &def, 0, NULL)
&& field == def;
}
case DBF_UINT64: {
epicsUInt64 field = *(epicsUInt64 *)pfield;
epicsUInt64 def;
if (!pflddes->initial)
return field == 0;
return ! epicsParseUInt64(pflddes->initial, &def, 0, NULL)
&& field == def;
}
case DBF_FLOAT: {
epicsFloat32 field = *(epicsFloat32 *)pfield;
epicsFloat32 def;
if (!pflddes->initial)
return field == 0;
return ! epicsParseFloat32(pflddes->initial, &def, NULL)
&& field == def;
}
case DBF_DOUBLE: {
epicsFloat64 field = *(epicsFloat64 *)pfield;
epicsFloat64 def;
if (!pflddes->initial)
return field == 0;
return ! epicsParseFloat64(pflddes->initial, &def, NULL)
&& field == def;
}
case DBF_MENU: {
epicsEnum16 field = *(epicsEnum16 *)pfield;
epicsEnum16 def;
int index;
if (!pflddes->initial)
return field == 0;
index = dbGetMenuIndexFromString(pdbentry, pflddes->initial);
if (index < 0) {
if (epicsParseUInt16(pflddes->initial, &def, 0, NULL))
return FALSE;
}
else
def = index;
return field == def;
}
case DBF_DEVICE: {
dbRecordType *precordType = pdbentry->precordType;
if (!precordType) {
epicsPrintf("dbIsDefaultValue: pdbRecordType is NULL??\n");
return FALSE;
}
return ellCount(&precordType->devList) == 0;
}
case DBF_INLINK:
case DBF_OUTLINK:
case DBF_FWDLINK: {
struct link *plink = (struct link *)pfield;
if (!plink || plink->type != CONSTANT)
return FALSE;
/* These conditions don't make a lot of sense... */
if (!plink->value.constantStr)
return TRUE;
if (!pflddes->initial) /* Default value for a link field? */
return FALSE;
return !strcmp(plink->value.constantStr, pflddes->initial);
}
default:
return TRUE;
}
return(FALSE);
}
long dbPutStringNum(DBENTRY *pdbentry,const char *pstring)
long dbPutStringNum(DBENTRY *pdbentry, const char *pstring)
{
dbFldDes *pflddes = pdbentry->pflddes;
void *pfield = pdbentry->pfield;
long status=0;
dbFldDes *pflddes = pdbentry->pflddes;
void *pfield = pdbentry->pfield;
if (!pfield)
return S_dbLib_fieldNotFound;
if(!pfield) return(S_dbLib_fieldNotFound);
switch (pflddes->field_type) {
case DBF_CHAR :
case DBF_SHORT :
case DBF_LONG:{
long value;
char *endp;
case DBF_CHAR:
return epicsParseInt8(pstring, pfield, 0, NULL);
value = strtol(pstring,&endp,0);
if(*endp!=0) status = S_dbLib_badField;
switch (pflddes->field_type) {
case DBF_CHAR : *(char *)pfield = (char)value; break;
case DBF_SHORT : *(short *)pfield = (short)value; break;
case DBF_LONG : *(epicsInt32 *)pfield = (epicsInt32)value; break;
default: epicsPrintf("Logic error in dbPutStringNum\n");
}
}
break;
case DBF_UCHAR:
return epicsParseUInt8(pstring, pfield, 0, NULL);
case DBF_SHORT:
return epicsParseInt16(pstring, pfield, 0, NULL);
case DBF_USHORT:
case DBF_ENUM:
return epicsParseUInt16(pstring, pfield, 0, NULL);
case DBF_LONG:
return epicsParseInt32(pstring, pfield, 0, NULL);
case DBF_ULONG:
case DBF_ENUM:{
unsigned long value;
char *endp;
return epicsParseUInt32(pstring, pfield, 0, NULL);
case DBF_INT64:
return epicsParseInt64(pstring, pfield, 0, NULL);
case DBF_UINT64:
return epicsParseUInt64(pstring, pfield, 0, NULL);
value = strtoul(pstring,&endp,0);
if(*endp!=0) status = S_dbLib_badField;
switch (pflddes->field_type) {
case DBF_UCHAR : *(unsigned char *)pfield = (unsigned char)value; break;
case DBF_USHORT:
case DBF_ENUM: *(unsigned short *)pfield = (unsigned short)value; break;
case DBF_ULONG : *(epicsUInt32 *)pfield = (epicsUInt32)value; break;
default: epicsPrintf("Logic error in dbPutStringNum\n");
}
}
break;
case DBF_FLOAT:
case DBF_DOUBLE: {
double value;
char *endp;
return epicsParseFloat32(pstring, pfield, NULL);
case DBF_DOUBLE:
return epicsParseFloat64(pstring, pfield, NULL);
value = epicsStrtod(pstring,&endp);
if(*endp!=0) status = S_dbLib_badField;
if(pflddes->field_type == DBF_FLOAT)
*(float *)pfield = (float)value;
else
*(double *)pfield = value;
}
break;
case DBF_MENU:
case DBF_DEVICE: {/*Must allow value that is choice or index*/
unsigned short *field= (unsigned short*)pfield;
int ind;
long value;
char *endp;
case DBF_DEVICE: {
epicsEnum16 *field = (epicsEnum16 *) pfield;
int index = dbGetMenuIndexFromString(pdbentry, pstring);
if (index < 0) {
epicsEnum16 value;
long status = epicsParseUInt16(pstring, &value, 0, NULL);
if (status)
return status;
index = dbGetNMenuChoices(pdbentry);
if (value > index && index > 0)
return S_dbLib_badField;
*field = value;
}
else
*field = index;
return 0;
}
ind = dbGetMenuIndexFromString(pdbentry,pstring);
if(ind==-1) {
value = strtol(pstring,&endp,0);
if(*endp!='\0') return(S_dbLib_badField);
ind = value;
/*Check that ind is withing range*/
if(!dbGetMenuStringFromIndex(pdbentry,ind))
return(S_dbLib_badField);
}
*field = (unsigned short)ind;
}
return (0);
default:
return (S_dbLib_badField);
return S_dbLib_badField;
}
return(status);
}
epicsShareFunc int dbGetMenuIndex(DBENTRY *pdbentry)
{
dbFldDes *pflddes = pdbentry->pflddes;
void *pfield = pdbentry->pfield;
dbFldDes *pflddes = pdbentry->pflddes;
void *pfield = pdbentry->pfield;
if (!pflddes || !pfield)
return -1;
if(!pflddes) return(-1);
if(!pfield) return(-1);
switch (pflddes->field_type) {
case (DBF_MENU):
case (DBF_DEVICE):
return((int)(*(unsigned short *)pfield));
default:
errPrintf(-1,__FILE__, __LINE__,"Logic Error\n");
case DBF_MENU:
case DBF_DEVICE:
return * (epicsEnum16 *) pfield;
default:
epicsPrintf("dbGetMenuIndex: Called for field type %d\n",
pflddes->field_type);
}
return(-1);
return -1;
}
epicsShareFunc long dbPutMenuIndex(DBENTRY *pdbentry,int index)
{
dbFldDes *pflddes = pdbentry->pflddes;
unsigned short *pfield = pdbentry->pfield;
if(!pflddes) return(S_dbLib_flddesNotFound);
if(!pfield) return(S_dbLib_fieldNotFound);
epicsShareFunc long dbPutMenuIndex(DBENTRY *pdbentry, int index)
{
dbFldDes *pflddes = pdbentry->pflddes;
epicsEnum16 *pfield = pdbentry->pfield;
if (!pflddes)
return S_dbLib_flddesNotFound;
if (!pfield)
return S_dbLib_fieldNotFound;
switch (pflddes->field_type) {
case DBF_MENU: {
dbMenu *pdbMenu = (dbMenu *)pflddes->ftPvt;
dbMenu *pdbMenu = (dbMenu *) pflddes->ftPvt;
if(!pdbMenu) return(S_dbLib_menuNotFound);
if(index<0 || index>=pdbMenu->nChoice) return(S_dbLib_badField);
*pfield = (unsigned short)index;
return(0);
}
case DBF_DEVICE: {
dbDeviceMenu *pdbDeviceMenu;
if (!pdbMenu)
return S_dbLib_menuNotFound;
if (index < 0 || index >= pdbMenu->nChoice)
return S_dbLib_badField;
pdbDeviceMenu = dbGetDeviceMenu(pdbentry);
if(!pdbDeviceMenu) return(S_dbLib_menuNotFound);
if(index<0 || index>=pdbDeviceMenu->nChoice)
return(S_dbLib_badField);
return(dbPutString(pdbentry,pdbDeviceMenu->papChoice[index]));
}
default:
break;
*pfield = index;
return 0;
}
return (S_dbLib_badField);
case DBF_DEVICE: {
dbDeviceMenu *pdbDeviceMenu = dbGetDeviceMenu(pdbentry);
if (!pdbDeviceMenu)
return S_dbLib_menuNotFound;
if (index < 0 || index >= pdbDeviceMenu->nChoice)
return S_dbLib_badField;
return dbPutString(pdbentry, pdbDeviceMenu->papChoice[index]);
}
default:
break;
}
return S_dbLib_badField;
}

View File

@@ -1,73 +1,62 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* Very efficient routines to convert numbers to strings
* Author: Bob Dalesio wrote cvtFloatToString (called FF_TO_STR)
* Code is same for cvtDoubleToString
* Marty Kraimer wrote cvtCharToString,cvtUcharToString
* cvtShortToString,cvtUshortToString,
* cvtLongToString, and cvtUlongToString
* Mark Anderson wrote cvtLongToHexString, cvtLongToOctalString,
* adopted cvt[Float/Double]ExpString and
* cvt[Float/Double]CompactString from fToEStr
* and fixed calls to gcvt
*
* Date: 12 January 1993
/* Fast numeric to string conversions
*
* Original Authors:
* Bob Dalesio, Mark Anderson and Marty Kraimer
* Date: 12 January 1993
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h> /* XPG2/XPG3/POSIX.1/FIPS151-1/ANSI-C */
#include <string.h>
#include <limits.h>
#define epicsExportSharedSymbols
#include "cvtFast.h"
#include "epicsMath.h"
/*
* This routine converts numbers less than 10,000,000. It defers to f_to_str for
* numbers requiring more than 8 places of precision. There are only eight decimal
*/
static epicsInt32 frac_multiplier[] =
{1,10,100,1000,10000,100000,1000000,10000000,100000000};
#include "epicsStdio.h"
int epicsShareAPI cvtFloatToString(
float flt_value,
char *pstr_value,
unsigned short precision)
/*
* These routines convert numbers up to +/- 10,000,000.
* They defer to sprintf() for numbers requiring more than
* 8 places of precision.
*/
static epicsInt32 frac_multiplier[] =
{1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
int cvtFloatToString(float flt_value, char *pdest,
epicsUInt16 precision)
{
unsigned short got_one,i;
epicsInt32 whole,iplace,number,fraction,fplace;
int got_one, i;
epicsInt32 whole, iplace, number, fraction, fplace;
float ftemp;
char *startAddr;
/* can this routine handle this conversion */
if (isnan(flt_value) || precision > 8 || flt_value > 10000000.0 || flt_value < -10000000.0) {
sprintf(pstr_value,"%12.5e",(double)flt_value);
return((int)strlen(pstr_value));
sprintf(pdest,"%12.5e",(double)flt_value);
return((int)strlen(pdest));
}
startAddr = pstr_value;
startAddr = pdest;
/* determine the sign */
if (flt_value < 0){
*pstr_value++ = '-';
*pdest++ = '-';
flt_value = -flt_value;
};
/* remove the whole number portion */
/* remove the whole number portion */
whole = (epicsInt32)flt_value;
ftemp = flt_value - whole;
/* multiplier to convert fractional portion to integer */
fplace = frac_multiplier[precision];
fraction = (epicsInt32)(ftemp * fplace * 10);
fraction = (epicsInt32)(ftemp * fplace * 10);
fraction = (fraction + 5) / 10; /* round up */
/* determine rounding into the whole number portion */
@@ -83,41 +72,41 @@ int epicsShareAPI cvtFloatToString(
got_one = 1;
number = whole / iplace;
whole = whole - (number * iplace);
*pstr_value = number + '0';
pstr_value++;
*pdest = number + '0';
pdest++;
}else if (got_one){
*pstr_value = '0';
pstr_value++;
*pdest = '0';
pdest++;
}
}
if (!got_one){
*pstr_value = '0';
pstr_value++;
*pdest = '0';
pdest++;
}
/* fraction */
if (precision > 0){
/* convert fractional portional to ASCII */
*pstr_value = '.';
pstr_value++;
*pdest = '.';
pdest++;
for (fplace /= 10, i = precision; i > 0; fplace /= 10,i--){
number = fraction / fplace;
fraction -= number * fplace;
*pstr_value = number + '0';
pstr_value++;
*pdest = number + '0';
pdest++;
}
}
*pstr_value = 0;
*pdest = 0;
return((int)(pstr_value - startAddr));
return((int)(pdest - startAddr));
}
int epicsShareAPI cvtDoubleToString(
int cvtDoubleToString(
double flt_value,
char *pstr_value,
unsigned short precision)
char *pdest,
epicsUInt16 precision)
{
unsigned short got_one,i;
epicsUInt16 got_one,i;
epicsInt32 whole,iplace,number,fraction,fplace;
double ftemp;
char *startAddr;
@@ -126,23 +115,23 @@ int epicsShareAPI cvtDoubleToString(
if (isnan(flt_value) || precision > 8 || flt_value > 10000000.0 || flt_value < -10000000.0) {
if (precision > 8 || flt_value > 1e16 || flt_value < -1e16) {
if(precision>17) precision=17;
sprintf(pstr_value,"%*.*e",precision+7,precision,
sprintf(pdest,"%*.*e",precision+7,precision,
flt_value);
} else {
if(precision>3) precision=3;
sprintf(pstr_value,"%.*f",precision,flt_value);
sprintf(pdest,"%.*f",precision,flt_value);
}
return((int)strlen(pstr_value));
return((int)strlen(pdest));
}
startAddr = pstr_value;
startAddr = pdest;
/* determine the sign */
if (flt_value < 0){
*pstr_value++ = '-';
*pdest++ = '-';
flt_value = -flt_value;
};
/* remove the whole number portion */
/* remove the whole number portion */
whole = (epicsInt32)flt_value;
ftemp = flt_value - whole;
@@ -164,432 +153,364 @@ int epicsShareAPI cvtDoubleToString(
got_one = 1;
number = whole / iplace;
whole = whole - (number * iplace);
*pstr_value = number + '0';
pstr_value++;
*pdest = number + '0';
pdest++;
}else if (got_one){
*pstr_value = '0';
pstr_value++;
*pdest = '0';
pdest++;
}
}
if (!got_one){
*pstr_value = '0';
pstr_value++;
*pdest = '0';
pdest++;
}
/* fraction */
if (precision > 0){
/* convert fractional portional to ASCII */
*pstr_value = '.';
pstr_value++;
*pdest = '.';
pdest++;
for (fplace /= 10, i = precision; i > 0; fplace /= 10,i--){
number = fraction / fplace;
fraction -= number * fplace;
*pstr_value = number + '0';
pstr_value++;
*pdest = number + '0';
pdest++;
}
}
*pstr_value = 0;
*pdest = 0;
return((int)(pstr_value - startAddr));
return((int)(pdest - startAddr));
}
/*
* These routines are provided for backwards compatibility,
* extensions such as MEDM, edm and histtool use them.
*/
/*
* cvtFloatToExpString
*
* converts floating point numbers to E-format NULL terminated strings
* Converts a float to a %e formatted string
*/
int epicsShareAPI cvtFloatToExpString(
float f_value,
char *pstr_value,
unsigned short f_precision)
int cvtFloatToExpString(float val, char *pdest, epicsUInt16 precision)
{
/*sunos uses char*sprint as function prototype*/
sprintf(pstr_value,"%.*e",(int)f_precision,(double)f_value);
return((int)strlen(pstr_value));
return epicsSnprintf(pdest, MAX_STRING_SIZE, "%.*e", precision, val);
}
/*
* cvtFloatToCompactString
*
* Converts floating point numbers to %g format NULL terminated strings,
* resulting in the most "compact" expression of the value
* ("f" notation if 10-4 < |value| < 10+4, otherwise "e" notation)
* Converts a float to a %g formatted string.
* The result uses %f notation for 10e-4 < |value| < 10e+4,
* otherwise %e notation.
*/
int epicsShareAPI cvtFloatToCompactString(
float f_value,
char *pstr_value,
unsigned short f_precision )
int cvtFloatToCompactString(float val, char *pdest, epicsUInt16 precision)
{
if ((f_value < 1.e4 && f_value > 1.e-4) ||
(f_value > -1.e4 && f_value < -1.e-4) || f_value == 0.0) {
return(cvtFloatToString(f_value,pstr_value,f_precision));
} else {
return(cvtFloatToExpString(f_value,pstr_value,f_precision));
}
}
if ((val < 1.e4 && val > 1.e-4) ||
(val > -1.e4 && val < -1.e-4) ||
val == 0.0)
return cvtFloatToString(val, pdest, precision);
return cvtFloatToExpString(val, pdest, precision);
}
/*
* cvtDoubleToExpString
*
* converts double precision floating point numbers to E-format NULL
* terminated strings
* Converts a double to a %e formatted string
*/
int epicsShareAPI cvtDoubleToExpString(
double f_value,
char *pstr_value,
unsigned short f_precision )
int cvtDoubleToExpString(double val, char *pdest, epicsUInt16 precision)
{
sprintf(pstr_value,"%.*e",(int)f_precision,f_value);
return((int)strlen(pstr_value));
return epicsSnprintf(pdest, MAX_STRING_SIZE, "%.*e", precision, val);
}
/*
* cvtDoubleToCompactString
*
* Converts double precision floating point numbers to %g format NULL
* terminated strings, resulting in the most "compact" expression
* of the value ("f" notation if 10-4 < |value| < 10+4, otherwise
* "e" notation)
* Converts a double to %g formatted string.
* The result uses %f notation for 10e-4 < |value| < 10e+4,
* otherwise %e notation.
*/
int epicsShareAPI cvtDoubleToCompactString(
double f_value,
char *pstr_value,
unsigned short f_precision )
int cvtDoubleToCompactString(double val, char *pdest, epicsUInt16 precision)
{
if ((f_value < 1.e4 && f_value > 1.e-4) ||
(f_value > -1.e4 && f_value < -1.e-4) || f_value == 0.0) {
return(cvtDoubleToString(f_value,pstr_value,f_precision));
} else {
return(cvtDoubleToExpString(f_value,pstr_value,f_precision));
}
if ((val < 1.e4 && val > 1.e-4) ||
(val > -1.e4 && val < -1.e-4) ||
val == 0.0)
return cvtDoubleToString(val, pdest, precision);
return cvtDoubleToExpString(val, pdest, precision);
}
/* Convert various integer types to ascii */
static char digit_to_ascii[10]={'0','1','2','3','4','5','6','7','8','9'};
int epicsShareAPI cvtCharToString(
signed char source,
char *pdest)
/* Integer conversion primitives */
static size_t
UInt32ToDec(epicsUInt32 val, char *pdest)
{
unsigned char val,temp;
char digit[3];
int i,j;
char *startAddr = pdest;
int i;
char digit[10];
size_t len;
if(source==0) {
*pdest++ = '0';
*pdest = 0;
return((int)(pdest-startAddr));
}
if(source<0) {
if(source == CHAR_MIN) {
sprintf(pdest,"%d",CHAR_MIN);
return((int)strlen(pdest));
}
*pdest++ = '-';
source = -source;
}
val = source;
for(i=0; val!=0; i++) {
temp = val/10;
digit[i] = digit_to_ascii[val - temp*10];
val = temp;
}
for(j=i-1; j>=0; j--) {
*pdest++ = digit[j];
for (i = 0; val; i++) {
epicsUInt32 tenth = val / 10;
digit[i] = val - tenth * 10 + '0';
val = tenth;
}
len = i;
while (i > 0)
*pdest++ = digit[--i];
*pdest = 0;
return((int)(pdest-startAddr));
return len;
}
int epicsShareAPI cvtUcharToString(
unsigned char source,
char *pdest)
static size_t
UInt32ToBase(epicsUInt32 val, char *pdest, int base)
{
unsigned char val,temp;
char digit[3];
int i,j;
char *startAddr = pdest;
int i;
char digit, digits[32];
size_t len;
if(source==0) {
*pdest++ = '0';
*pdest = 0;
return((int)(pdest-startAddr));
}
val = source;
for(i=0; val!=0; i++) {
temp = val/10;
digit[i] = digit_to_ascii[val - temp*10];
val = temp;
}
for(j=i-1; j>=0; j--) {
*pdest++ = digit[j];
for (i = 0; val; i++) {
epicsUInt32 tenth = val / base;
digit = val - tenth * base;
digits[i] = digit < 10 ? digit + '0' : digit - 10 + 'a';
val = tenth;
}
len = i;
while (i > 0)
*pdest++ = digits[--i];
*pdest = 0;
return((int)(pdest-startAddr));
return len;
}
int epicsShareAPI cvtShortToString(
short source,
char *pdest)
static size_t
UInt64ToDec(epicsUInt64 val, char *pdest)
{
short val,temp;
char digit[6];
int i,j;
char *startAddr = pdest;
int i;
char digit[20];
size_t len;
if(source==0) {
*pdest++ = '0';
*pdest = 0;
return((int)(pdest-startAddr));
}
if(source<0) {
if(source == SHRT_MIN) {
sprintf(pdest,"%d",SHRT_MIN);
return((int)(strlen(pdest)));
}
*pdest++ = '-';
source = -source;
}
val = source;
for(i=0; val!=0; i++) {
temp = val/10;
digit[i] = digit_to_ascii[val - temp*10];
val = temp;
}
for(j=i-1; j>=0; j--) {
*pdest++ = digit[j];
for (i = 0; val; i++) {
epicsUInt64 tenth = val / 10;
digit[i] = val - tenth * 10 + '0';
val = tenth;
}
len = i;
while (i > 0)
*pdest++ = digit[--i];
*pdest = 0;
return((int)(pdest-startAddr));
return len;
}
int epicsShareAPI cvtUshortToString(
unsigned short source,
char *pdest)
static size_t
UInt64ToBase(epicsUInt64 val, char *pdest, int base)
{
unsigned short val,temp;
char digit[5];
int i,j;
char *startAddr = pdest;
int i;
char digit, digits[64];
size_t len;
if(source==0) {
*pdest++ = '0';
*pdest = 0;
return((int)(pdest-startAddr));
}
val = source;
for(i=0; val!=0; i++) {
temp = val/10;
digit[i] = digit_to_ascii[val - temp*10];
val = temp;
}
for(j=i-1; j>=0; j--) {
*pdest++ = digit[j];
for (i = 0; val; i++) {
epicsUInt64 tenth = val / base;
digit = val - tenth * base;
digits[i] = digit < 10 ? digit + '0' : digit - 10 + 'a';
val = tenth;
}
len = i;
while (i > 0)
*pdest++ = digits[--i];
*pdest = 0;
return((int)(pdest-startAddr));
return len;
}
int epicsShareAPI cvtLongToString(
epicsInt32 source,
char *pdest)
{
epicsInt32 val,temp;
char digit[11];
int i,j;
char *startAddr = pdest;
/* Integer conversion routines */
if(source==0) {
*pdest++ = '0';
*pdest = 0;
return((int)(pdest-startAddr));
size_t
cvtUInt32ToString(epicsUInt32 val, char *pdest)
{
if (val == 0) {
*pdest++ = '0';
*pdest = 0;
return 1;
}
if(source<0) {
if(source == INT_MIN) {
sprintf(pdest,"%d",source);
return((int)strlen(pdest));
}
*pdest++ = '-';
source = -source;
return UInt32ToDec(val, pdest);
}
size_t
cvtInt32ToString(epicsInt32 val, char *pdest)
{
if (val == 0) {
*pdest++ = '0';
*pdest = 0;
return 1;
}
val = source;
for(i=0; val!=0; i++) {
temp = val/10;
digit[i] = digit_to_ascii[val - temp*10];
val = temp;
if (val > 0)
return UInt32ToDec(val, pdest);
if (val == -0x80000000) {
strcpy(pdest, "-2147483648");
return strlen(pdest);
}
for(j=i-1; j>=0; j--) {
*pdest++ = digit[j];
}
*pdest = 0;
return((int)(pdest-startAddr));
*pdest++ = '-';
return 1 + UInt32ToDec(-val, pdest);
}
int epicsShareAPI cvtUlongToString(
epicsUInt32 source,
char *pdest)
size_t
cvtUInt64ToString(epicsUInt64 val, char *pdest)
{
epicsUInt32 val,temp;
char digit[10];
int i,j;
char *startAddr = pdest;
if (val == 0) {
*pdest++ = '0';
*pdest = 0;
return 1;
}
if(source==0) {
*pdest++ = '0';
*pdest = 0;
return((int)(pdest-startAddr));
return UInt64ToDec(val, pdest);
}
size_t
cvtInt64ToString(epicsInt64 val, char *pdest)
{
if (val == 0) {
*pdest++ = '0';
*pdest = 0;
return 1;
}
val = source;
for(i=0; val!=0; i++) {
temp = val/10;
digit[i] = digit_to_ascii[val - temp*10];
val = temp;
if (val > 0)
return UInt64ToDec(val, pdest);
if (val == -0x8000000000000000LL) {
strcpy(pdest, "-9223372036854775808");
return strlen(pdest);
}
for(j=i-1; j>=0; j--) {
*pdest++ = digit[j];
}
*pdest = 0;
return((int)(pdest-startAddr));
*pdest++ = '-';
return 1 + UInt64ToDec(-val, pdest);
}
/* Convert hex digits to ascii */
static char hex_digit_to_ascii[16]={'0','1','2','3','4','5','6','7','8','9',
'a','b','c','d','e','f'};
int epicsShareAPI cvtLongToHexString(
epicsInt32 source,
char *pdest)
size_t
cvtInt32ToHexString(epicsInt32 val, char *pdest)
{
epicsInt32 val,temp;
char digit[10];
int i,j;
char *startAddr = pdest;
if (val < 0)
*pdest++ = '-';
if(source==0) {
*pdest++ = '0';
*pdest = 0;
return((int)(pdest-startAddr));
}
if(source<0) {
if(source == INT_MIN) {
sprintf(pdest,"-0x%x",source);
return((int)strlen(pdest));
}
*pdest++ = '-';
source = -source;
}
*pdest++ = '0'; *pdest++ = 'x';
val = source;
for(i=0; val!=0; i++) {
temp = val/16;
digit[i] = hex_digit_to_ascii[val - temp*16];
val = temp;
}
for(j=i-1; j>=0; j--) {
*pdest++ = digit[j];
}
*pdest = 0;
return((int)(pdest-startAddr));
}
int epicsShareAPI cvtLongToOctalString(
epicsInt32 source,
char *pdest)
{
epicsInt32 val,temp;
char digit[16];
int i,j;
char *startAddr = pdest;
if(source==0) {
*pdest++ = '0';
*pdest = 0;
return((int)(pdest-startAddr));
}
if(source<0) {
if(source == INT_MIN) {
sprintf(pdest,"-0%o",source);
return((int)strlen(pdest));
}
*pdest++ = '-';
source = -source;
}
*pdest++ = '0';
val = source;
for(i=0; val!=0; i++) {
temp = val/8;
/* reuse digit_to_ascii since octal is a subset of decimal */
digit[i] = digit_to_ascii[val - temp*8];
val = temp;
*pdest++ = 'x';
if (val == 0) {
*pdest++ = '0';
*pdest = 0;
return 3;
}
for(j=i-1; j>=0; j--) {
*pdest++ = digit[j];
if (val > 0)
return 2 + UInt32ToBase(val, pdest, 16);
if (val == -0x80000000) {
strcpy(pdest, "80000000");
return 11;
}
*pdest = 0;
return((int)(pdest-startAddr));
return 3 + UInt32ToBase(-val, pdest, 16);
}
/*
*
* cvtBitsToUlong()
*
* extract a bit field from the source epicsUInt32
*/
epicsUInt32 epicsShareAPI cvtBitsToUlong(
epicsUInt32 src,
unsigned bitFieldOffset,
unsigned bitFieldLength)
size_t
cvtUInt32ToHexString(epicsUInt32 val, char *pdest)
{
epicsUInt32 mask;
*pdest++ = '0';
*pdest++ = 'x';
src = src >> bitFieldOffset;
if (val == 0) {
*pdest++ = '0';
*pdest = 0;
return 3;
}
mask = (1<<bitFieldLength)-1;
src = src & mask;
return src;
return 2 + UInt32ToBase(val, pdest, 16);
}
/*
*
* cvtUlongToBits()
*
* insert a bit field from the source epicsUInt32
* into the destination epicsUInt32
*/
epicsUInt32 epicsShareAPI cvtUlongToBits(
epicsUInt32 src,
epicsUInt32 dest,
unsigned bitFieldOffset,
unsigned bitFieldLength)
size_t
cvtInt32OctalString(epicsInt32 val, char *pdest)
{
epicsUInt32 mask;
if (val == 0) {
*pdest++ = '0';
*pdest = 0;
return 1;
}
mask = (1<<bitFieldLength)-1;
mask = mask << bitFieldOffset;
src = src << bitFieldOffset;
dest = (dest & ~mask) | (src & mask);
if (val > 0) {
*pdest++ = '0';
return 1 + UInt32ToBase(val, pdest, 8);
}
return dest;
if (val == -0x80000000) {
strcpy(pdest, "-020000000000");
return strlen(pdest);
}
*pdest++ = '-';
*pdest++ = '0';
return 2 + UInt32ToBase(-val, pdest, 8);
}
size_t
cvtInt64ToHexString(epicsInt64 val, char *pdest)
{
if (val < 0)
*pdest++ = '-';
*pdest++ = '0';
*pdest++ = 'x';
if (val == 0) {
*pdest++ = '0';
*pdest = 0;
return 3;
}
if (val > 0)
return 2 + UInt64ToBase(val, pdest, 16);
if (val == -0x8000000000000000LL) {
strcpy(pdest, "8000000000000000");
return 19;
}
return 3 + UInt64ToBase(-val, pdest, 16);
}
size_t
cvtUInt64ToHexString(epicsUInt64 val, char *pdest)
{
*pdest++ = '0';
*pdest++ = 'x';
if (val == 0) {
*pdest++ = '0';
*pdest = 0;
return 3;
}
return 2 + UInt64ToBase(val, pdest, 16);
}

View File

@@ -1,30 +1,23 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Very efficient routines to convert numbers to strings
* Fast numeric to string conversions
*
* Author: Bob Dalesio wrote cvtFloatToString (called FF_TO_STR)
* Code is same for cvtDoubleToString
* Marty Kraimer wrote cvtCharToString,cvtUcharToString
* cvtShortToString,cvtUshortToString,
* cvtLongToString, and cvtUlongToString
* Mark Anderson wrote cvtLongToHexString, cvtLongToOctalString,
* adopted cvt[Float/Double]ExpString and
* cvt[Float/Double]CompactString from fToEStr
* and fixed calls to gcvt
* Date: 12-9-92
* Original Authors:
* Bob Dalesio, Mark Anderson and Marty Kraimer
* Date: 12 January 1993
*/
#ifndef INCcvtFasth
#define INCcvtFasth
#include <string.h>
#include <stddef.h>
#include "epicsTypes.h"
#include "shareLib.h"
@@ -34,46 +27,54 @@ extern "C" {
#endif
/*
* each of these functions return the number of characters "transmitted"
* (as in ANSI-C/POSIX.1/XPG3 sprintf() functions)
* All functions return the number of characters in the output
*/
epicsShareFunc int epicsShareAPI
cvtFloatToString(float value, char *pstring, unsigned short precision);
epicsShareFunc int epicsShareAPI
cvtDoubleToString(double value, char *pstring, unsigned short precision);
epicsShareFunc int epicsShareAPI
cvtFloatToExpString(float value, char *pstring, unsigned short precision);
epicsShareFunc int epicsShareAPI
cvtDoubleToExpString(double value, char *pstring, unsigned short precision);
epicsShareFunc int epicsShareAPI
cvtFloatToCompactString(float value, char *pstring, unsigned short precision);
epicsShareFunc int epicsShareAPI
cvtDoubleToCompactString(double value, char *pstring, unsigned short precision);
epicsShareFunc int epicsShareAPI
cvtCharToString(signed char value, char *pstring);
epicsShareFunc int epicsShareAPI
cvtUcharToString(unsigned char value, char *pstring);
epicsShareFunc int epicsShareAPI
cvtShortToString(short value, char *pstring);
epicsShareFunc int epicsShareAPI
cvtUshortToString(unsigned short value, char *pstring);
epicsShareFunc int epicsShareAPI
cvtLongToString(epicsInt32 value, char *pstring);
epicsShareFunc int epicsShareAPI
cvtUlongToString(epicsUInt32 value, char *pstring);
epicsShareFunc int epicsShareAPI
cvtLongToHexString(epicsInt32 value, char *pstring);
epicsShareFunc int epicsShareAPI
cvtLongToOctalString(epicsInt32 value, char *pstring);
epicsShareFunc epicsUInt32 epicsShareAPI cvtBitsToUlong(
epicsUInt32 src,
unsigned bitFieldOffset,
unsigned bitFieldLength);
epicsShareFunc epicsUInt32 epicsShareAPI cvtUlongToBits(
epicsUInt32 src,
epicsUInt32 dest,
unsigned bitFieldOffset,
unsigned bitFieldLength);
epicsShareFunc int
cvtFloatToString(float val, char *pdest, epicsUInt16 prec);
epicsShareFunc int
cvtDoubleToString(double val, char *pdest, epicsUInt16 prec);
epicsShareFunc int
cvtFloatToExpString(float val, char *pdest, epicsUInt16 prec);
epicsShareFunc int
cvtDoubleToExpString(double val, char *pdest, epicsUInt16 prec);
epicsShareFunc int
cvtFloatToCompactString(float val, char *pdest, epicsUInt16 prec);
epicsShareFunc int
cvtDoubleToCompactString(double val, char *pdest, epicsUInt16 prec);
epicsShareFunc size_t
cvtInt32ToString(epicsInt32 val, char *pdest);
epicsShareFunc size_t
cvtUInt32ToString(epicsUInt32 val, char *pdest);
epicsShareFunc size_t
cvtInt64ToString(epicsInt64 val, char *pdest);
epicsShareFunc size_t
cvtUInt64ToString(epicsUInt64 val, char *pdest);
epicsShareFunc size_t
cvtInt32ToHexString(epicsInt32 val, char *pdest);
epicsShareFunc size_t
cvtUInt32ToHexString(epicsUInt32 val, char *pdest);
epicsShareFunc size_t
cvtInt32ToOctalString(epicsInt32 val, char *pdest);
epicsShareFunc size_t
cvtInt64ToHexString(epicsInt64 val, char *pdest);
epicsShareFunc size_t
cvtUInt64ToHexString(epicsUInt64 val, char *pdest);
/* Support the original names */
#define cvtCharToString(val, str) cvtInt32ToString(val, str)
#define cvtUcharToString(val, str) cvtUInt32ToString(val, str)
#define cvtShortToString(val, str) cvtInt32ToString(val, str)
#define cvtUshortToString(val, str) cvtUInt32ToString(val, str)
#define cvtLongToString(val, str) cvtInt32ToString(val, str)
#define cvtUlongToString(val, str) cvtUInt32ToString(val, str)
#define cvtLongToHexString(val, str) cvtInt32ToHexString(val, str)
#define cvtULongToHexString(val, str) cvtUInt32ToHexString(val, str)
#define cvtLongToOctalString(val, str) cvtInt32ToOctalString(val, str)
#ifdef __cplusplus
}

View File

@@ -256,7 +256,7 @@ epicsParseInt32(const char *str, epicsInt32 *to, int base, char **units)
return S_stdlib_overflow;
#endif
*to = value;
*to = (epicsInt32) value;
return 0;
}
@@ -274,7 +274,7 @@ epicsParseUInt32(const char *str, epicsUInt32 *to, int base, char **units)
return S_stdlib_overflow;
#endif
*to = value;
*to = (epicsUInt32) value;
return 0;
}
@@ -292,7 +292,7 @@ epicsParseInt64(const char *str, epicsInt64 *to, int base, char **units)
if (status)
return status;
*to = value;
*to = (epicsInt64) value;
return 0;
}
@@ -310,7 +310,7 @@ epicsParseUInt64(const char *str, epicsUInt64 *to, int base, char **units)
if (status)
return status;
*to = value;
*to = (epicsUInt64) value;
return 0;
}

View File

@@ -1,3 +0,0 @@
The source files here are vxWorks dependent.

View File

@@ -1,11 +1,11 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Saskatchewan
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* This header is included as part of epicsString.h and epicsStdlib.h
* This header is included by epicsString.h and epicsStdlib.h
*/
#ifdef __cplusplus
@@ -15,7 +15,7 @@ extern "C" {
/*
* epicsStrtod() for systems with broken strtod() routine
*/
epicsShareFunc double epicsStrtod(const char *str, char **endp);
double epicsStrtod(const char *str, char **endp);
/*
* VxWorks doesn't provide these routines, so for now we do

View File

@@ -176,6 +176,11 @@ macDefExpandTest_SRCS += macDefExpandTest.c
testHarness_SRCS += macDefExpandTest.c
TESTS += macDefExpandTest
TESTPROD_HOST += cvtFastTest
cvtFastTest_SRCS += cvtFastTest.cpp
testHarness_SRCS += cvtFastTest.cpp
TESTS += cvtFastTest
TESTPROD_HOST += macLibTest
macLibTest_SRCS += macLibTest.c
testHarness_SRCS += macLibTest.c

View File

@@ -0,0 +1,457 @@
/*************************************************************************\
* Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* cvtFastTest.c
*
* Test the string converters in libCom/cvtFast/cvtFast.c
*
* To Do: Test Char/Uchar/Short/Ushort/Long/Ulong versions
*/
#include <math.h>
#include <float.h>
#include "epicsUnitTest.h"
#include "cvtFast.h"
#include "epicsStdlib.h"
#include "testMain.h"
#define tryIString(typ, lit, siz) \
len = cvt##typ##ToString(lit, buf); \
if (!testOk(len == siz, "cvt"#typ"ToString(" #lit ") == " #siz)) \
testDiag("length returned was %u", (unsigned) len); \
status = epicsParse##typ(buf, &val_##typ, 10, NULL); \
testOk(!status, "epicsParse"#typ"('%s') OK", buf); \
testOk(val_##typ == lit, #lit " => '%s'", buf);
#define tryFString(typ, lit, prec, siz) \
len = cvt##typ##ToString(lit, buf, prec); \
if (!testOk(len == siz, "cvt"#typ"ToString(" #lit ", %d) == " #siz, prec)) \
testDiag("length returned was %u", (unsigned) len); \
status = epicsParse##typ(buf, &val_##typ, NULL); \
testOk(!status, "epicsParse"#typ"('%s') OK", buf); \
testOk(fabs(val_##typ - lit) < 0.5 * pow(10, -prec), #lit " => '%s'", buf);
MAIN(cvtFastTest)
{
char buf[80];
size_t len;
long status;
epicsUInt32 val_UInt32;
epicsInt32 val_Int32;
epicsUInt64 val_UInt64;
epicsInt64 val_Int64;
epicsFloat32 val_Float;
epicsFloat64 val_Double;
#if defined(WIN32) && (!defined(_MINGW) || __MSVCRT_VERSION__ >= 0x0800)
_set_output_format(_TWO_DIGIT_EXPONENT);
#endif
testPlan(1062);
/* Arguments: type, value, num chars */
testDiag("------------------------------------------------------");
testDiag("** Positive Int32 **");
tryIString(Int32, 0, 1);
tryIString(Int32, 1, 1);
tryIString(Int32, 10, 2);
tryIString(Int32, 100, 3);
tryIString(Int32, 254, 3);
tryIString(Int32, 255, 3);
tryIString(Int32, 256, 3);
tryIString(Int32, 257, 3);
tryIString(Int32, 1000, 4);
tryIString(Int32, 10000, 5);
tryIString(Int32, 32766, 5);
tryIString(Int32, 32767, 5);
tryIString(Int32, 32768, 5);
tryIString(Int32, 32769, 5);
tryIString(Int32, 65534, 5);
tryIString(Int32, 65535, 5);
tryIString(Int32, 65536, 5);
tryIString(Int32, 65537, 5);
tryIString(Int32, 2147483646, 10);
tryIString(Int32, 2147483647, 10);
testDiag("------------------------------------------------------");
testDiag("** Negative Int32 **");
tryIString(Int32, -1, 2);
tryIString(Int32, -10, 3);
tryIString(Int32, -100, 4);
tryIString(Int32, -254, 4);
tryIString(Int32, -255, 4);
tryIString(Int32, -256, 4);
tryIString(Int32, -257, 4);
tryIString(Int32, -1000, 5);
tryIString(Int32, -10000, 6);
tryIString(Int32, -32766, 6);
tryIString(Int32, -32767, 6);
tryIString(Int32, -32768, 6);
tryIString(Int32, -32769, 6);
tryIString(Int32, -65534, 6);
tryIString(Int32, -65535, 6);
tryIString(Int32, -65536, 6);
tryIString(Int32, -65537, 6);
tryIString(Int32, -2147483647, 11);
tryIString(Int32, -2147483648LL, 11);
testDiag("------------------------------------------------------");
testDiag("** UInt32 **");
tryIString(UInt32, 0, 1);
tryIString(UInt32, 1, 1);
tryIString(UInt32, 10, 2);
tryIString(UInt32, 100, 3);
tryIString(UInt32, 254, 3);
tryIString(UInt32, 255, 3);
tryIString(UInt32, 256, 3);
tryIString(UInt32, 257, 3);
tryIString(UInt32, 1000, 4);
tryIString(UInt32, 10000, 5);
tryIString(UInt32, 32766, 5);
tryIString(UInt32, 32767, 5);
tryIString(UInt32, 32768, 5);
tryIString(UInt32, 32769, 5);
tryIString(UInt32, 65534, 5);
tryIString(UInt32, 65535, 5);
tryIString(UInt32, 65536, 5);
tryIString(UInt32, 65537, 5);
tryIString(UInt32, 2147483646ULL, 10);
tryIString(UInt32, 2147483647ULL, 10);
tryIString(UInt32, 2147483648ULL, 10);
tryIString(UInt32, 4294967294ULL, 10);
tryIString(UInt32, 4294967295ULL, 10);
testDiag("------------------------------------------------------");
testDiag("** Positive Int64 **");
tryIString(Int64, 0, 1);
tryIString(Int64, 1, 1);
tryIString(Int64, 10, 2);
tryIString(Int64, 100, 3);
tryIString(Int64, 254, 3);
tryIString(Int64, 255, 3);
tryIString(Int64, 256, 3);
tryIString(Int64, 257, 3);
tryIString(Int64, 1000, 4);
tryIString(Int64, 10000, 5);
tryIString(Int64, 32766, 5);
tryIString(Int64, 32767, 5);
tryIString(Int64, 32768, 5);
tryIString(Int64, 32769, 5);
tryIString(Int64, 65534, 5);
tryIString(Int64, 65535, 5);
tryIString(Int64, 65536, 5);
tryIString(Int64, 65537, 5);
tryIString(Int64, 2147483646, 10);
tryIString(Int64, 2147483647, 10);
tryIString(Int64, 2147483648LL, 10);
tryIString(Int64, 9223372036854775806LL, 19);
tryIString(Int64, 9223372036854775807LL, 19);
testDiag("------------------------------------------------------");
testDiag("** Negative Int64 **");
tryIString(Int64, -1, 2);
tryIString(Int64, -10, 3);
tryIString(Int64, -100, 4);
tryIString(Int64, -254, 4);
tryIString(Int64, -255, 4);
tryIString(Int64, -256, 4);
tryIString(Int64, -257, 4);
tryIString(Int64, -1000, 5);
tryIString(Int64, -10000, 6);
tryIString(Int64, -32766, 6);
tryIString(Int64, -32767, 6);
tryIString(Int64, -32768, 6);
tryIString(Int64, -32769, 6);
tryIString(Int64, -65534, 6);
tryIString(Int64, -65535, 6);
tryIString(Int64, -65536, 6);
tryIString(Int64, -65537, 6);
tryIString(Int64, -2147483647, 11);
tryIString(Int64, -2147483648LL, 11);
tryIString(Int64, -2147483649LL, 11);
tryIString(Int64, -9223372036854775806LL, 20);
tryIString(Int64, -9223372036854775807LL, 20);
tryIString(Int64, -9223372036854775807LL-1, 20);
testDiag("------------------------------------------------------");
testDiag("** UInt64 **");
tryIString(UInt64, 0, 1);
tryIString(UInt64, 1, 1);
tryIString(UInt64, 10, 2);
tryIString(UInt64, 100, 3);
tryIString(UInt64, 254, 3);
tryIString(UInt64, 255, 3);
tryIString(UInt64, 256, 3);
tryIString(UInt64, 257, 3);
tryIString(UInt64, 1000, 4);
tryIString(UInt64, 10000, 5);
tryIString(UInt64, 32766, 5);
tryIString(UInt64, 32767, 5);
tryIString(UInt64, 32768, 5);
tryIString(UInt64, 32769, 5);
tryIString(UInt64, 65534, 5);
tryIString(UInt64, 65535, 5);
tryIString(UInt64, 65536, 5);
tryIString(UInt64, 65537, 5);
tryIString(UInt64, 2147483646, 10);
tryIString(UInt64, 2147483647, 10);
tryIString(UInt64, 2147483648U, 10);
tryIString(UInt64, 2147483649U, 10);
tryIString(UInt64, 4294967294U, 10);
tryIString(UInt64, 4294967295U, 10);
tryIString(UInt64, 4294967296ULL, 10);
tryIString(UInt64, 4294967297ULL, 10);
tryIString(UInt64, 9223372036854775806ULL, 19);
tryIString(UInt64, 9223372036854775807ULL, 19);
tryIString(UInt64, 9223372036854775808ULL, 19);
tryIString(UInt64, 18446744073709551614ULL, 20);
tryIString(UInt64, 18446744073709551615ULL, 20);
/* Arguments: type, value, precision, num chars */
testDiag("------------------------------------------------------");
testDiag("** Positive Float fixed-point **");
tryFString(Float, 0, 0, 1);
tryFString(Float, 0, 1, 3);
tryFString(Float, 0, 2, 4);
tryFString(Float, 0, 3, 5);
tryFString(Float, 0, 4, 6);
tryFString(Float, 0, 5, 7);
tryFString(Float, 0, 6, 8);
tryFString(Float, 0, 7, 9);
tryFString(Float, 0, 8, 10);
tryFString(Float, FLT_MIN, 0, 1);
tryFString(Float, FLT_MIN, 1, 3);
tryFString(Float, FLT_MIN, 2, 4);
tryFString(Float, FLT_MIN, 3, 5);
tryFString(Float, FLT_MIN, 4, 6);
tryFString(Float, FLT_MIN, 5, 7);
tryFString(Float, FLT_MIN, 6, 8);
tryFString(Float, FLT_MIN, 7, 9);
tryFString(Float, FLT_MIN, 8, 10);
tryFString(Float, 0.000000004999999, 8, 10);
tryFString(Float, 0.000000005000001, 8, 10);
tryFString(Float, 0.00000004999999, 7, 9);
tryFString(Float, 0.00000005000001, 7, 9);
tryFString(Float, 0.0000004999999, 6, 8);
tryFString(Float, 0.0000005000001, 6, 8);
tryFString(Float, 0.000004999999, 5, 7);
tryFString(Float, 0.000005000001, 5, 7);
tryFString(Float, 0.00004999999, 4, 6);
tryFString(Float, 0.00005000001, 4, 6);
tryFString(Float, 0.0004999999, 3, 5);
tryFString(Float, 0.0005000001, 3, 5);
tryFString(Float, 0.004999999, 2, 4);
tryFString(Float, 0.005000001, 2, 4);
tryFString(Float, 0.04999999, 1, 3);
tryFString(Float, 0.05000001, 1, 3);
tryFString(Float, 0.4999999, 0, 1);
tryFString(Float, 0.5000001, 0, 1);
tryFString(Float, 1, 0, 1);
tryFString(Float, 1, 1, 3);
tryFString(Float, 1, 2, 4);
tryFString(Float, 1, 3, 5);
tryFString(Float, 1, 4, 6);
tryFString(Float, 1, 5, 7);
tryFString(Float, 1, 6, 8);
tryFString(Float, 1, 7, 9);
tryFString(Float, 1, 8, 10);
tryFString(Float, 1.0500001, 1, 3);
tryFString(Float, 1.1, 1, 3);
tryFString(Float, 1.1499999, 1, 3);
tryFString(Float, 9.5000001, 0, 2);
tryFString(Float, 10, 0, 2);
tryFString(Float, 10, 1, 4);
tryFString(Float, 10, 8, 11);
tryFString(Float, 100, 0, 3);
tryFString(Float, 100, 1, 5);
tryFString(Float, 100, 8, 12);
tryFString(Float, 1000, 0, 4);
tryFString(Float, 1000, 1, 6);
tryFString(Float, 1000, 8, 13);
tryFString(Float, 10000, 0, 5);
tryFString(Float, 10000, 1, 7);
tryFString(Float, 10000, 8, 14);
tryFString(Float, 100000, 0, 6);
tryFString(Float, 100000, 1, 8);
tryFString(Float, 100000, 8, 15);
tryFString(Float, 1000000, 0, 7);
tryFString(Float, 1000000, 1, 9);
tryFString(Float, 1000000, 8, 16);
tryFString(Float, 10000000, 0, 8);
tryFString(Float, 10000000, 1, 10);
tryFString(Float, 10000000, 8, 17);
testDiag("------------------------------------------------------");
testDiag("** Negative Float fixed-point **");
tryFString(Float, -FLT_MIN, 0, 2);
tryFString(Float, -FLT_MIN, 1, 4);
tryFString(Float, -FLT_MIN, 8, 11);
tryFString(Float, -1, 0, 2);
tryFString(Float, -1, 1, 4);
tryFString(Float, -1, 8, 11);
tryFString(Float, -1.0500001, 1, 4);
tryFString(Float, -1.1, 1, 4);
tryFString(Float, -1.1499999, 1, 4);
tryFString(Float, -9.5000001, 0, 3);
tryFString(Float, -10, 0, 3);
tryFString(Float, -10, 1, 5);
tryFString(Float, -10, 8, 12);
tryFString(Float, -100, 0, 4);
tryFString(Float, -100, 1, 6);
tryFString(Float, -100, 8, 13);
tryFString(Float, -1000, 0, 5);
tryFString(Float, -1000, 1, 7);
tryFString(Float, -1000, 8, 14);
tryFString(Float, -10000, 0, 6);
tryFString(Float, -10000, 1, 8);
tryFString(Float, -10000, 8, 15);
tryFString(Float, -100000, 0, 7);
tryFString(Float, -100000, 1, 9);
tryFString(Float, -100000, 8, 16);
tryFString(Float, -1000000, 0, 8);
tryFString(Float, -1000000, 1, 10);
tryFString(Float, -1000000, 8, 17);
tryFString(Float, -10000000, 0, 9);
tryFString(Float, -10000000, 1, 11);
tryFString(Float, -10000000, 8, 18);
/*
* Values > 1e7 trigger the %e format.
*/
testDiag("------------------------------------------------------");
testDiag("** Positive Float scientific **");
tryFString(Float, 1e+08, 0, 6);
tryFString(Float, 1e+08, 1, 8);
tryFString(Float, 1e+08, 2, 9);
tryFString(Float, 1e+08, 3, 10);
tryFString(Float, 1e+08, 4, 11);
tryFString(Float, 1e+08, 5, 12);
tryFString(Float, 1e+08, 6, 13);
testDiag("------------------------------------------------------");
testDiag("** Positive Double fixed-point **");
tryFString(Double, 0, 0, 1);
tryFString(Double, 0, 1, 3);
tryFString(Double, 0, 2, 4);
tryFString(Double, 0, 3, 5);
tryFString(Double, 0, 4, 6);
tryFString(Double, 0, 5, 7);
tryFString(Double, 0, 6, 8);
tryFString(Double, 0, 7, 9);
tryFString(Double, 0, 8, 10);
tryFString(Double, DBL_MIN, 0, 1);
tryFString(Double, DBL_MIN, 1, 3);
tryFString(Double, DBL_MIN, 2, 4);
tryFString(Double, DBL_MIN, 3, 5);
tryFString(Double, DBL_MIN, 4, 6);
tryFString(Double, DBL_MIN, 5, 7);
tryFString(Double, DBL_MIN, 6, 8);
tryFString(Double, DBL_MIN, 7, 9);
tryFString(Double, DBL_MIN, 8, 10);
tryFString(Double, 0.000000004999999, 8, 10);
tryFString(Double, 0.000000005000001, 8, 10);
tryFString(Double, 0.00000004999999, 7, 9);
tryFString(Double, 0.00000005000001, 7, 9);
tryFString(Double, 0.0000004999999, 6, 8);
tryFString(Double, 0.0000005000001, 6, 8);
tryFString(Double, 0.000004999999, 5, 7);
tryFString(Double, 0.000005000001, 5, 7);
tryFString(Double, 0.00004999999, 4, 6);
tryFString(Double, 0.00005000001, 4, 6);
tryFString(Double, 0.0004999999, 3, 5);
tryFString(Double, 0.0005000001, 3, 5);
tryFString(Double, 0.004999999, 2, 4);
tryFString(Double, 0.005000001, 2, 4);
tryFString(Double, 0.04999999, 1, 3);
tryFString(Double, 0.05000001, 1, 3);
tryFString(Double, 0.4999999, 0, 1);
tryFString(Double, 0.5000001, 0, 1);
tryFString(Double, 1, 0, 1);
tryFString(Double, 1, 1, 3);
tryFString(Double, 1, 2, 4);
tryFString(Double, 1, 3, 5);
tryFString(Double, 1, 4, 6);
tryFString(Double, 1, 5, 7);
tryFString(Double, 1, 6, 8);
tryFString(Double, 1, 7, 9);
tryFString(Double, 1, 8, 10);
tryFString(Double, 1.0500001, 1, 3);
tryFString(Double, 1.1, 1, 3);
tryFString(Double, 1.1499999, 1, 3);
tryFString(Double, 9.5000001, 0, 2);
tryFString(Double, 10, 0, 2);
tryFString(Double, 10, 1, 4);
tryFString(Double, 10, 8, 11);
tryFString(Double, 100, 0, 3);
tryFString(Double, 100, 1, 5);
tryFString(Double, 100, 8, 12);
tryFString(Double, 1000, 0, 4);
tryFString(Double, 1000, 1, 6);
tryFString(Double, 1000, 8, 13);
tryFString(Double, 10000, 0, 5);
tryFString(Double, 10000, 1, 7);
tryFString(Double, 10000, 8, 14);
tryFString(Double, 100000, 0, 6);
tryFString(Double, 100000, 1, 8);
tryFString(Double, 100000, 8, 15);
tryFString(Double, 1000000, 0, 7);
tryFString(Double, 1000000, 1, 9);
tryFString(Double, 1000000, 8, 16);
tryFString(Double, 10000000, 0, 8);
tryFString(Double, 10000000, 1, 10);
tryFString(Double, 10000000, 8, 17);
testDiag("------------------------------------------------------");
testDiag("** Negative Double fixed-point **");
tryFString(Double, -DBL_MIN, 0, 2);
tryFString(Double, -DBL_MIN, 1, 4);
tryFString(Double, -DBL_MIN, 8, 11);
tryFString(Double, -1, 0, 2);
tryFString(Double, -1, 1, 4);
tryFString(Double, -1, 8, 11);
tryFString(Double, -1.0500001, 1, 4);
tryFString(Double, -1.1, 1, 4);
tryFString(Double, -1.1499999, 1, 4);
tryFString(Double, -9.5000001, 0, 3);
tryFString(Double, -10, 0, 3);
tryFString(Double, -10, 1, 5);
tryFString(Double, -10, 8, 12);
tryFString(Double, -100, 0, 4);
tryFString(Double, -100, 1, 6);
tryFString(Double, -100, 8, 13);
tryFString(Double, -1000, 0, 5);
tryFString(Double, -1000, 1, 7);
tryFString(Double, -1000, 8, 14);
tryFString(Double, -10000, 0, 6);
tryFString(Double, -10000, 1, 8);
tryFString(Double, -10000, 8, 15);
tryFString(Double, -100000, 0, 7);
tryFString(Double, -100000, 1, 9);
tryFString(Double, -100000, 8, 16);
tryFString(Double, -1000000, 0, 8);
tryFString(Double, -1000000, 1, 10);
tryFString(Double, -1000000, 8, 17);
tryFString(Double, -10000000, 0, 9);
tryFString(Double, -10000000, 1, 11);
tryFString(Double, -10000000, 8, 18);
/*
* Values > 1e7 trigger the %e format.
* Windows may print 3 digit exponents...
*/
testDiag("------------------------------------------------------");
testDiag("** Positive Double scientific **");
tryFString(Double, 1e+17, 0, 7);
tryFString(Double, 1e+17, 1, 8);
tryFString(Double, 1e+17, 2, 9);
tryFString(Double, 1e+17, 3, 10);
tryFString(Double, 1e+17, 4, 11);
tryFString(Double, 1e+17, 5, 12);
return testDone();
}

View File

@@ -12,6 +12,8 @@ our %field_types = (
DBF_USHORT => $RXuintx,
DBF_LONG => $RXintx,
DBF_ULONG => $RXuintx,
DBF_INT64 => $RXintx,
DBF_UINT64 => $RXuintx,
DBF_FLOAT => $RXnum,
DBF_DOUBLE => $RXnum,
DBF_ENUM => qr/.*/,
@@ -317,6 +319,43 @@ sub toDeclaration {
}
################################################################################
package DBD::Recfield::DBF_INT64;
use DBD::Base;
@ISA = qw(DBD::Recfield);
sub legal_value {
my ($this, $value) = @_;
$value =~ s/^ ( $RXhex | $RXoct ) $/ oct($1) /xe;
return ($value =~ m/^ $RXint $/x);
}
sub toDeclaration {
return shift->SUPER::toDeclaration("epicsInt64");
}
################################################################################
package DBD::Recfield::DBF_UINT64;
use DBD::Base;
@ISA = qw(DBD::Recfield);
sub legal_value {
my ($this, $value) = @_;
$value =~ s/^ ( $RXhex | $RXoct ) $/ oct($1) /xe;
return ($value =~ m/^ $RXuint $/x and
$value >= 0);
}
sub toDeclaration {
return shift->SUPER::toDeclaration("epicsUInt64");
}
################################################################################
package DBD::Recfield::DBF_FLOAT;