Skip to content

Commit

Permalink
Make identification of nan and inf more robust
Browse files Browse the repository at this point in the history
Use isinf() and isnan() when converting double to string
to ensure that the value is given canonical form.

And implement our own isinf and isnan if necessary
  • Loading branch information
msteveb committed Dec 20, 2013
1 parent 5390d57 commit 5218859
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 59 deletions.
2 changes: 1 addition & 1 deletion auto.def
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ cc-check-functions ualarm lstat fork vfork system select execvpe
cc-check-functions backtrace geteuid mkstemp realpath strptime isatty
cc-check-functions regcomp waitpid sigaction sys_signame sys_siglist isascii
cc-check-functions syslog opendir readlink sleep usleep pipe getaddrinfo utimes
cc-check-functions shutdown socketpair
cc-check-functions shutdown socketpair isinf isnan

if {[cc-check-functions sysinfo]} {
cc-with {-includes sys/sysinfo.h} {
Expand Down
128 changes: 70 additions & 58 deletions jim.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,47 +581,6 @@ int Jim_StringToWide(const char *str, jim_wide * widePtr, int base)
return JimCheckConversion(str, endptr);
}

int Jim_DoubleToString(char *buf, double doubleValue)
{
int len;
int i;

len = sprintf(buf, "%.12g", doubleValue);

/* Add a final ".0" if necessary */
for (i = 0; i < len; i++) {
if (buf[i] == '.' || buf[i] == 'e') {
#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
/* If 'buf' ends in e-0nn or e+0nn, remove
* the 0 after the + or - and reduce the length by 1
*/
char *e = strchr(buf, 'e');
if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
/* Move it up */
e += 2;
memmove(e, e + 1, len - (e - buf));
return len - 1;
}
#endif
return len;
}
/* inf or Infinity -> Inf, nan -> NaN */
if (buf[i] == 'i' || buf[i] == 'I' || buf[i] == 'n' || buf[i] == 'N') {
buf[i] = toupper(UCHAR(buf[i]));
if (buf[i] == 'n' || buf[i] == 'N')
buf[i+2] = toupper(UCHAR(buf[i+2]));
buf[i + 3] = 0;
return i + 3;
}
}

buf[i++] = '.';
buf[i++] = '0';
buf[i] = '\0';

return i;
}

int Jim_StringToDouble(const char *str, double *doublePtr)
{
char *endptr;
Expand Down Expand Up @@ -2361,6 +2320,12 @@ const char *Jim_String(Jim_Obj *objPtr)
return objPtr->bytes;
}

static void JimSetStringBytes(Jim_Obj *objPtr, const char *str)
{
objPtr->bytes = Jim_StrDup(str);
objPtr->length = strlen(str);
}

static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);

Expand Down Expand Up @@ -5906,15 +5871,61 @@ static const Jim_ObjType doubleObjType = {
JIM_TYPE_NONE,
};

#ifndef HAVE_ISNAN
#undef isnan
#define isnan(X) ((X) != (X))
#endif
#ifndef HAVE_ISINF
#undef isinf
#define isinf(X) (1.0 / (X) == 0.0)
#endif

void UpdateStringOfDouble(struct Jim_Obj *objPtr)
{
int len;
char buf[JIM_DOUBLE_SPACE + 1];
double value = objPtr->internalRep.doubleValue;

len = Jim_DoubleToString(buf, objPtr->internalRep.doubleValue);
objPtr->bytes = Jim_Alloc(len + 1);
memcpy(objPtr->bytes, buf, len + 1);
objPtr->length = len;
if (isnan(value)) {
JimSetStringBytes(objPtr, "NaN");
return;
}
if (isinf(value)) {
if (value < 0) {
JimSetStringBytes(objPtr, "-Inf");
}
else {
JimSetStringBytes(objPtr, "Inf");
}
return;
}
{
char buf[JIM_DOUBLE_SPACE + 1];
int i;
int len = sprintf(buf, "%.12g", value);

/* Add a final ".0" if necessary */
for (i = 0; i < len; i++) {
if (buf[i] == '.' || buf[i] == 'e') {
#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX)
/* If 'buf' ends in e-0nn or e+0nn, remove
* the 0 after the + or - and reduce the length by 1
*/
char *e = strchr(buf, 'e');
if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') {
/* Move it up */
e += 2;
memmove(e, e + 1, len - (e - buf));
}
#endif
break;
}
}
if (buf[i] == '\0') {
buf[i++] = '.';
buf[i++] = '0';
buf[i] = '\0';
}
JimSetStringBytes(objPtr, buf);
}
}

int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
Expand Down Expand Up @@ -7255,19 +7266,20 @@ static const Jim_ObjType indexObjType = {

void UpdateStringOfIndex(struct Jim_Obj *objPtr)
{
int len;
char buf[JIM_INTEGER_SPACE + 1];

if (objPtr->internalRep.intValue >= 0)
len = sprintf(buf, "%d", objPtr->internalRep.intValue);
else if (objPtr->internalRep.intValue == -1)
len = sprintf(buf, "end");
if (objPtr->internalRep.intValue == -1) {
JimSetStringBytes(objPtr, "end");
}
else {
len = sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
char buf[JIM_INTEGER_SPACE + 1];
if (objPtr->internalRep.intValue >= 0) {
sprintf(buf, "%d", objPtr->internalRep.intValue);
}
else {
/* Must be <= -2 */
sprintf(buf, "end%d", objPtr->internalRep.intValue + 1);
}
JimSetStringBytes(objPtr, buf);
}
objPtr->bytes = Jim_Alloc(len + 1);
memcpy(objPtr->bytes, buf, len + 1);
objPtr->length = len;
}

int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
Expand Down

0 comments on commit 5218859

Please sign in to comment.