[commit: base] master: fix negative numbers for * modifiers (#7457) (63202b9)

Ian Lynagh ian at well-typed.com
Tue Jan 29 23:36:22 CET 2013


On Mon, Jan 28, 2013 at 02:06:48AM -0800, Simon Marlow wrote:
> 
> commit 63202b9df64041e1c17603ad5f06fec3c51f357d
> Author: Simon Marlow <marlowsd at gmail.com>
> Date:   Mon Jan 28 09:38:06 2013 +0000
> 
>     fix negative numbers for * modifiers (#7457)
> 
> >---------------------------------------------------------------
> 
>  Text/Printf.hs |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/Text/Printf.hs b/Text/Printf.hs
> index 0546e84..6028e16 100644
> --- a/Text/Printf.hs
> +++ b/Text/Printf.hs
> @@ -281,7 +281,7 @@ getSpecs l z s ('*':cs) us =
>  		    	      	 in  ((p', r), us''')
>  		    '.':r     -> (stoi 0 r, us')
>  		    _         -> ((-1, cs), us')
> -	in  (n, p, l, z, s, cs'', us'')
> +	in  (abs n, p, if n < 0 then not l else l, z, s, cs'', us'')
>  getSpecs l z s ('.':cs) us =
>  	let ((p, cs'), us') = 
>  	        case cs of

Hmm, this works for minBound for Int8:

    > printf "%*sx\n" (-4 :: Int8) "hi"
    hi  x
    > printf "%*sx\n" (minBound :: Int8) "hi"
    hi                                                                                                                              x

but not Int:

    > printf "%*sx\n" (-4 :: Int) "hi"
    hi  x
    > printf "%*sx\n" (minBound :: Int) "hi"
    hix

(the last line should have a huge number of spaces between "hi" and "x".

Actually, this matches what the printf commandline program does:

    $ printf "%*sx\n" -4 hi
    hi  x
    $ printf "%*sx\n" -2147483648 hi
    hix

and C just doesn't print anything:

    $ cat q.c

    #include <stdio.h>

    int main(void) {
        int i;
        i = -2147483648;
        printf("%*sx\n", -4, "hi");
        printf("%*sx\n", i, "hi");
        printf("Test\n");
        return 0;
    }

    $ gcc q.c -o q
    $ ./q
    hi  x
    Test
    $ 


This probably isn't important for printf, but it's a problem that seems
to keep coming up. I wonder if there's something we should do. We could
add methods like
    maybeAbs :: a -> Maybe a
    maybeAbs = Just . abs -- default method
to Num, but div and friends are a little trickier, as they can return
either divZeroError or overflowError, or even partially succeed in the
case of
    (-1) `divMod` minBound == (overflowError, 0)


Thanks
Ian




More information about the Libraries mailing list