Is String>>sprintfWith: broken?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Is String>>sprintfWith: broken?

John Small
Observe:

        (3/35) asFloat   ->   8.57142857142857e-002

But

        '%5.3e' sprintfWith: (3/35) asFloat    ->   '4.765e-315'

        '%5.3f' sprintfWith: (3/35) asFloat     ->    '0.000'

        '%5.3g' sprintfWith: (3/35) asFloat    ->    '4.77e-315'

What am I doing wrong?

Thanks!

John


Reply | Threaded
Open this post in threaded view
|

Re: Is String>>sprintfWith: broken?

Ian Bartholomew-17
John,

> What am I doing wrong?

I don't think you are doing anything wrong, it's just the Float values are
not supported in calls to sprintf.  There have been a few mentions of this
in the newsgroup over the years so you might want to have a scan of the
archive.  The most explanatory one was made by Blair in January 2000 and, as
far as I know, still applies.

~-~-~-~ (Blair 12/1/2000) ~-~-~-~
#sprintfWith: and friends do not support all of the possible types, only
those which are correctly passed by the lpvoid argument type.

If you are wondering why then the answer is:

sprintf() is a variable argument list C function and does not mesh well onto
Smalltalk which doesn't really have a clean syntax for expressing such.
Therefore we have to wrap this function by writing multiple external methods
in CRTLibrary ("C" runtime library) with varying numbers of arguments, and
then having multiple wrappers for those low level functions (sprintfWith:,
sprintfWith:with:). This works up to a point, but it is not only the number
of arguments that can vary, but also the type. In C the caller pushes a
variable number of arguments of any type, and the compiler arranges to push
as many bytes on the stack as each argument in the list requires (this makes
the function rather unsafe since the arguments frequently don't match the
format string specification). Dolphin's external call support requires a
fixed number of arguments of fixed types, so our best compromise is to use
the lpvoid type, but it passes the address of a float/double, rather than
the content, so those argument types will be passed incorrectly. There is no
notion in Dolphin of pushing arguments onto the stack based on the type of
the actual parameter rather than a formal parameter definition (hmmm,
maybe...). This is the best arrangement for most cases as it is often
necessary to coerce the supplied Smalltalk object to a suitable native
representation.

If you wanted to use sprintf for formatting individual floats, then you
could do so by adding a further external wrapper method to CRTLibrary with a
'double' argument. This could perhaps be invoked by a hypothetical
#printStringFormat: method defined in Float.
~-~-~-~

The situation is confused slightly by the removal of a method comment that
existed in version up to and including D3 which documented the fact that
only certain argument types could be used. In D4, because of a
rearrangement, the method disappeared and the comment went with it.

Ian