diff --git a/src/misc/parseToPOD.cpp b/src/misc/parseToPOD.cpp index fa9bc85..d3c1598 100644 --- a/src/misc/parseToPOD.cpp +++ b/src/misc/parseToPOD.cpp @@ -308,6 +308,71 @@ noconvert: return 0; } +#if defined(__vxworks) +/* vxworks version of std::istringstream >>uint64_t is buggy, we use out own implementation */ +static +unsigned long long strtoull(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long long acc; + int c; + unsigned long long cutoff; + int neg = 0, any, cutlim; + + do + c = *s++; + while (isspace(c)); + if (c == '-') + { + neg = 1; + c = *s++; + } + else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) + { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + cutoff = (unsigned long long) UINT64_MAX / (unsigned long long) base; + cutlim = (unsigned long long) UINT64_MAX % (unsigned long long) base; + + for (acc = 0, any = 0;; c = *s++) + { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else + { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) + { + acc = UINT64_MAX; + errno = ERANGE; + } + else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = any ? (char *) s - 1 : (char *) nptr; + return (acc); +} +#else static unsigned long long strtoull(const char *ptr, char ** endp, int base) { @@ -350,7 +415,7 @@ noconvert: *endp = (char*)ptr; return 0; } - +#endif #endif /* do we need long long? */ @@ -486,6 +551,26 @@ void parseToPOD(const string& in, float *out) { void parseToPOD(const string& in, double *out) { int err = epicsParseDouble(in.c_str(), out, NULL); if(err) handleParseError(err); +#if defined(__vxworks) + /* vxWorks strtod returns [-]epicsINF when it should return ERANGE error + * if [-]epicsINF is returned and first char is a digit then translate this into ERANGE error + */ + else if (*out == epicsINF || *out == -epicsINF) { + const char* s = in.c_str(); + int c; + + /* skip spaces and the sign */ + do { + c = *s++; + } while (isspace(c)); + + if (c == '-' || c == '+') + c = *s++; + + if (isdigit(c)) + handleParseError(S_stdlib_overflow); + } +#endif } }}} diff --git a/src/pv/pvType.h b/src/pv/pvType.h index 506b835..89ec667 100644 --- a/src/pv/pvType.h +++ b/src/pv/pvType.h @@ -29,7 +29,7 @@ typedef int intptr_t; typedef unsigned int uintptr_t; #ifndef INT64_MAX #define INT64_MAX (0x7fffffffffffffffLL) -#define UINT64_MAX (0xffffffffffffffffLL) +#define UINT64_MAX (0xffffffffffffffffULL) #endif #else #include diff --git a/testApp/misc/testTypeCast.cpp b/testApp/misc/testTypeCast.cpp index efd46d8..cab5fb7 100644 --- a/testApp/misc/testTypeCast.cpp +++ b/testApp/misc/testTypeCast.cpp @@ -37,11 +37,11 @@ namespace { }; template<> struct testequal { - static bool op(double A, double B) {return fabs(A-B)<1e-300; } + static bool op(double A, double B) {return fabs(A-B)<1e-15; } }; template<> struct testequal { - static bool op(float A, float B) {return fabs(A-B)<1e-30; } + static bool op(float A, float B) {return fabs(A-B)<1e-7; } }; template @@ -117,7 +117,7 @@ namespace { MAIN(testTypeCast) { - testPlan(122); + testPlan(123); try { @@ -387,7 +387,8 @@ try { FAIL(int8_t, string, "1000"); FAIL(int8_t, string, "-1000"); - FAIL(double, string, "1e+10000000"); + FAIL(double, string, "1e+1000"); + FAIL(double, string, "-1e+1000"); FAIL(epics::pvData::boolean, string, "hello"); FAIL(epics::pvData::boolean, string, "1");