I was getting odd behavior with printf(1) when using ' or "
with a value of 128 or more, but only on some systems.

On amd64 where CHAR_MAX 127
$ printf %x\\n "'$(printf \\200)"
ffffffffffffffb0
$ printf %o\\n "'$(printf \\200)"
1777777777777777777600
$ printf %u\\n "'$(printf \\200)"
18446744073709551488
$ printf %d\\n "'$(printf \\200)"
-128

On macppc where CHAR_MAX 255
$ printf %x\\n "'$(printf \\200)"
80
$ printf %o\\n "'$(printf \\200)"
200
$ printf %u\\n "'$(printf \\200)"
128
$ printf %d\\n "'$(printf \\200)"
128

This patch adds casts to unsigned char to avoid problems when char
is signed.  With this patch applied the correct values of 80, 200, 128
and 128 are printed for the above examples.

Index: printf.c
===================================================================
RCS file: /cvs/src/usr.bin/printf/printf.c,v
retrieving revision 1.24
diff -u -p -r1.24 printf.c
--- printf.c    9 Oct 2015 01:37:08 -0000       1.24
+++ printf.c    22 Jun 2016 21:9:11 -0000
@@ -439,7 +439,7 @@ getlong(void)
                return(0L);

        if (**gargv == '\"' || **gargv == '\'')
-               return (long) *((*gargv++)+1);
+               return (unsigned char)*((*gargv++)+1);

        errno = 0;
        val = strtol (*gargv, &ep, 0);
@@ -457,7 +457,7 @@ getulong(void)
                return(0UL);

        if (**gargv == '\"' || **gargv == '\'')
-               return (unsigned long) *((*gargv++)+1);
+               return (unsigned char)*((*gargv++)+1);

        errno = 0;
        val = strtoul (*gargv, &ep, 0);
@@ -475,7 +475,7 @@ getdouble(void)
                return(0.0);

        if (**gargv == '\"' || **gargv == '\'')
-               return (double) *((*gargv++)+1);
+               return (unsigned char)*((*gargv++)+1);

        errno = 0;
        val = strtod (*gargv, &ep);

Reply via email to