Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Jonathan Wilkes
purr-data
Commits
6ae5bdcf
Commit
6ae5bdcf
authored
Jul 02, 2020
by
Jonathan Wilkes
Browse files
flesh out handling of overflows, improve messages to explain these type issues
parent
263341a3
Changes
3
Hide whitespace changes
Inline
Side-by-side
pd/src/m_class.c
View file @
6ae5bdcf
...
...
@@ -45,31 +45,106 @@ static t_symbol *class_extern_dir = &s_;
int
symbol_can_float
(
t_symbol
*
s
,
t_float
*
f
);
char
*
type_hint
(
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
)
/* try to give the user some help with the uglier cases of unexpected
atom types in messages.
dostof flag controls whether we want to try to convert a symbol
to a float.
for [float]'s symbol conversion we even check if we received an
out of range error, but here for the general case we don't do that. */
char
*
type_hint
(
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
,
int
dostof
)
{
static
char
hint
[
MAXPDSTRING
];
t_float
f
;
t_float
f
=
0
;
/* Null selectors-- the user typically shouldn't encounter these,
especially one that triggers an unknown method error. But we
check for them anyway. */
if
(
!
s
)
sprintf
(
hint
,
" (null selector detected)"
);
else
if
(
s
==
&
s_
)
sprintf
(
hint
,
" (empty symbol selector)"
);
else
if
(
s
&&
s
==
&
s_symbol
&&
argc
&&
argv
->
a_type
==
A_SYMBOL
{
sprintf
(
hint
,
" (Note: null selector detected)"
);
return
hint
;
}
/* Empty symbol selector is also rare. But a user can easily generate
one with [symbol( or [symbol] then send to [list trim]. */
if
(
s
==
&
s_
)
{
sprintf
(
hint
,
" (Note: empty symbol selector)"
);
return
hint
;
}
/* More commonly, the user may have a "symbol" message where the
payload is an empty symbol. This can cause confusion for debugging
since the empty symbol doesn't print out anything. */
if
(
s
&&
s
==
&
s_symbol
&&
argc
&&
argv
->
a_type
==
A_SYMBOL
&&
argv
->
a_w
.
w_symbol
==
&
s_
)
sprintf
(
hint
,
" (empty symbol message detected)"
);
else
if
(
symbol_can_float
(
s
,
&
f
))
sprintf
(
hint
,
" (%s is actually a symbol atom here)"
,
s
->
s_name
);
else
if
(
symbol_can_float
(
atom_getsymbolarg
(
0
,
argc
,
argv
),
&
f
))
sprintf
(
hint
,
" (symbol message with floatlike payload detected."
" Did you mean 'float %s'?)"
,
argv
->
a_w
.
w_symbol
->
s_name
);
else
hint
[
0
]
=
'\0'
;
{
sprintf
(
hint
,
" (Note: empty symbol message payload detected)"
);
return
hint
;
}
/* Somewhat common edge case-- [makefilename] and other objects can
output a symbol message with a payload that looks numeric but is
indeed a symbol atom. In fact, Pd's text parser would interpret
such a string as a float if you sent it through the parser.
This can cause problems if the user tries to serialize the data
and read it back-- say, by saving the symbol message "symbol 123"
in a file. The next time they load it, "123" will be parsed as
a float atom, and any symbol methods will read from the wrong
union field and (probably) interpret it as an empty symbol. */
if
(
dostof
)
{
if
(
symbol_can_float
(
atom_getsymbolarg
(
0
,
argc
,
argv
),
&
f
))
{
sprintf
(
hint
,
" (Note: this symbol message has a floatlike payload "
"which cannot be saved properly. Did you mean 'float %s'?)"
,
argv
->
a_w
.
w_symbol
->
s_name
);
return
hint
;
}
else
if
(
f
==
-
1
||
f
==
1
)
{
/* For values which would overflow, give a hint but don't
suggest float type */
sprintf
(
hint
,
" (Note: this symbol message has an %s floatlike "
"payload which cannot be saved properly."
,
f
==
1
?
"overflowing"
:
"underflowing"
);
return
hint
;
}
}
/* Rather uncommon case where the selector itself is a symbol atom
that would normally have been parsed as a float. */
if
(
dostof
)
{
if
(
symbol_can_float
(
s
,
&
f
))
{
sprintf
(
hint
,
" (Note: %s looks like a float but is actually a "
"symbol which cannot be saved properly)"
,
s
->
s_name
);
return
hint
;
}
else
if
(
f
==
-
1
||
f
==
1
)
{
/* For values which would overflow, give a hint but don't
suggest float type */
sprintf
(
hint
,
" (Note: this symbol message has an %s floatlike "
"payload which cannot be saved properly."
,
f
==
1
?
"overflowing"
:
"underflowing"
);
return
hint
;
}
}
hint
[
0
]
=
'\0'
;
return
hint
;
}
static
void
pd_defaultanything
(
t_pd
*
x
,
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
)
{
pd_error
(
x
,
"%s: no method for '%s'%s"
,
(
*
x
)
->
c_name
->
s_name
,
s
->
s_name
,
type_hint
(
s
,
argc
,
argv
));
(
*
x
)
->
c_name
->
s_name
,
s
->
s_name
,
type_hint
(
s
,
argc
,
argv
,
*
(
*
x
)
->
c_floatmethod
!=
pd_defaultfloat
?
1
:
0
));
}
static
void
pd_defaultbang
(
t_pd
*
x
)
...
...
pd/src/m_obj.c
View file @
6ae5bdcf
...
...
@@ -72,12 +72,12 @@ t_inlet *signalinlet_new(t_object *owner, t_float f)
return
(
x
);
}
char
*
type_hint
(
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
);
char
*
type_hint
(
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
,
int
dostof
);
static
void
inlet_wrong
(
t_inlet
*
x
,
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
)
{
pd_error
(
x
->
i_owner
,
"inlet: expected '%s' but got '%s'%s"
,
x
->
i_symfrom
->
s_name
,
s
->
s_name
,
type_hint
(
s
,
argc
,
argv
));
x
->
i_symfrom
->
s_name
,
s
->
s_name
,
type_hint
(
s
,
argc
,
argv
,
1
));
}
static
void
inlet_list
(
t_inlet
*
x
,
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
);
...
...
pd/src/x_connective.c
View file @
6ae5bdcf
...
...
@@ -8,6 +8,8 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
extern
t_pd
*
newest
;
...
...
@@ -86,33 +88,56 @@ static void pdfloat_float(t_pdfloat *x, t_float f)
outlet_float
(
x
->
x_obj
.
ob_outlet
,
x
->
x_f
=
f
);
}
/* check if a symbol payload can be interpreted as a floating point number.
We get these cases sometimes from [makefilename], [keyname], and some
externals that shoot out data that would be parsed as a float if loaded
from a file.
return values are: 0 not a number
1 successfully parsed as float (stored in f)
if the number would underflow f is set to -1
if the number would overflow f is set to greater than zero
*/
int
symbol_can_float
(
t_symbol
*
s
,
t_float
*
f
)
{
char
c
;
if
(
!
s
||
s
==
&
s_
)
return
0
;
int
ret
;
char
c
,
*
str_end
;
c
=
s
->
s_name
[
0
];
if
(
c
!=
'-'
&&
c
!=
'+'
&&
c
<
48
&&
c
>
57
)
return
0
;
char
*
str_end
=
NULL
;
if
(
c
!=
'-'
&&
c
!=
'+'
&&
(
c
<
48
||
c
>
57
)
)
return
0
;
errno
=
0
;
*
f
=
strtod
(
s
->
s_name
,
&
str_end
);
/* Add error checking here like in cxc/hex2dec */
if
(
*
f
==
0
&&
s
->
s_name
==
str_end
)
return
0
;
return
1
;
if
(
errno
==
ERANGE
)
{
ret
=
0
;
if
(
*
f
==
0
)
*
f
=
-
1
;
/* underflow */
else
*
f
=
1
;
/* assume overflow otherwise */
}
else
if
(
*
f
==
0
&&
s
->
s_name
==
str_end
)
{
ret
=
0
;
}
else
ret
=
1
;
return
ret
;
}
char
*
type_hint
(
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
);
char
*
type_hint
(
t_symbol
*
s
,
int
argc
,
t_atom
*
argv
,
int
check_symforfloat
);
static
void
pdfloat_symbol
(
t_pdfloat
*
x
,
t_symbol
*
s
)
{
t_float
f
;
t_float
f
=
0
;
if
(
symbol_can_float
(
s
,
&
f
))
outlet_float
(
x
->
x_obj
.
ob_outlet
,
x
->
x_f
=
f
);
else
{
t_atom
at
;
SETSYMBOL
(
&
at
,
s
);
pd_error
(
x
,
"couldn't convert %s to float%s"
,
s
->
s_name
,
type_hint
(
&
s_symbol
,
1
,
&
at
));
pd_error
(
x
,
"couldn't convert 'symbol %s' to float%s"
,
s
->
s_name
,
f
==
-
1
?
" (number too small)"
:
f
==
1
?
" (number too large)"
:
type_hint
(
&
s_symbol
,
1
,
&
at
,
0
));
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment