Refine type detection in terminal write
The code no longer accepts valid mantissa-only doubles that are integer rejects, eg, 078 or ULL overflows. These are most likely input errors by the user: 8 is not an octal digit, they might have typed 17 hex digits, not 16. It's just too hard to explain that 0xffffFFFFffffFFFFf writes 0x4430000000000000, which is the correct double representation of the valid 17-digit hex mantissa that strtod() is perfectly happy to accept.
This commit is contained in:
parent
704d253636
commit
7c766ef9bd
55
src/term.c
55
src/term.c
|
@ -531,6 +531,30 @@ static void change_endian(void *p, int size) {
|
|||
}
|
||||
|
||||
|
||||
// Looks like a double mantissa in hex or dec notation
|
||||
static int is_mantissa_only(char *p) {
|
||||
char *digs;
|
||||
|
||||
if(*p == '+' || *p == '-')
|
||||
p++;
|
||||
|
||||
if(*p == '0' && (p[1] == 'x' || p[1] == 'X')) {
|
||||
p += 2;
|
||||
digs = "0123456789abcdefABCDEF";
|
||||
} else
|
||||
digs = "0123456789";
|
||||
|
||||
if(!*p)
|
||||
return 0;
|
||||
|
||||
while(*p)
|
||||
if(!strchr(digs, *p++))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
|
@ -741,18 +765,20 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
}
|
||||
|
||||
if(!data.size) { // Try double now that input was rejected as integer
|
||||
data.d = strtod(argi, &end_ptr);
|
||||
// Do not accept valid doubles that are integer rejects (eg, 078 or ULL overflows)
|
||||
if (end_ptr != argi && *end_ptr == 0)
|
||||
if (!is_mantissa_only(argi))
|
||||
data.size = 8;
|
||||
}
|
||||
|
||||
if(!data.size) { // Try float
|
||||
data.f = strtof(argi, &end_ptr);
|
||||
if (end_ptr != argi && toupper(*end_ptr) == 'F' && end_ptr[1] == 0)
|
||||
data.size = 4;
|
||||
}
|
||||
|
||||
if(!data.size) { // Try double
|
||||
data.d = strtod(argi, &end_ptr);
|
||||
if (end_ptr != argi && *end_ptr == 0)
|
||||
data.size = 8;
|
||||
}
|
||||
|
||||
if(!data.size) { // Try C-style string or single character
|
||||
if ((*argi == '\'' && argi[arglen-1] == '\'') || (*argi == '\"' && argi[arglen-1] == '\"')) {
|
||||
char *s = calloc(arglen-1, 1);
|
||||
|
@ -774,16 +800,17 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
|||
} else { // C-style string
|
||||
data.str_ptr = s;
|
||||
}
|
||||
} else {
|
||||
avrdude_message(MSG_INFO, "%s (write): can't parse data %s\n",
|
||||
progname, argi);
|
||||
free(buf);
|
||||
if(data.str_ptr != NULL)
|
||||
free(data.str_ptr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// ensure we have little endian representation in data.a
|
||||
|
||||
if(!data.size && !data.str_ptr) {
|
||||
avrdude_message(MSG_INFO, "%s (write): can't parse data %s\n",
|
||||
progname, argi);
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Assume endianness is the same for double and int, and ensure little endian representation
|
||||
if(is_big_endian && data.size > 1)
|
||||
change_endian(data.a, data.size);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue