Regression with printf 8-bit format macros

Ambroz Bizjak ambrop7@gmail.com
Mon Jan 4 16:05:00 GMT 2016


Hi Andre,

I understand that defining PRI*8 to "*" rather than "hh*" is not
elegant, but it is correct.

This is the relevant text from the C99 draft (7.8.1):

Each of the following object-like macros expands to a character string
literal containing a conversion specifier, possibly modified by a
length modifier, suitable for use within the format argument of a
formatted input/output function when converting the corresponding
integer type. These macro names have the general form of PRI
(character string literals for the fprintf and fwprintf family) or SCN
(character string literals for the fscanf and fwscanf family),
followed by the conversion specifier, followed by a name corresponding
to a similar type name in 7.18.1. In these names, N represents the
width of the type as described in 7.18.1. For example, PRIdFAST32 can
be used in a format string to print the value of an integer of type
int_fast32_t.

So all that is required is that the definition is suitable for use in
combination with that type. There is nothing that specifically implies
that PRI*8 needs to be "hh*".

For example, if PRId8 is defined to "d", the following code will
behave as expected. This is because x is implicitly promoted to int,
and int is the valid type to use with %d.
uint8_t x = 255; printf("%"PRId8, x);

I think that one of these three things should be done:
- Revert the changes so that PRI*8 is again defined to "*".
- Provide the new definitions ("hh*") when C99 printf is supported,
but the old ones ("*") if it's not.
- Do not define the PRI*8 macros when C99 printf is not supported.

>> I do agree that it is weird that for the SCN*8 macros to be guarded with _WANT_IO_C99_FORMATS, whilst the PRI*8 are not.
This is likely because the old PRI*8 definitions were known to be
correct regardless of C99 printf support. And the reason that the
SCN*8 macros must be guarded is because the scanf implementation needs
to specifically aware of the exact type that the passed pointers point
to, so that the outputs can be correctly stored. There is no implicit
promotion to "save us" in the case of scanf.

You might be surprised how Linux defines these macros - at least on
the machine I tested on, PRI*8 was "*".

Best

On Mon, Jan 4, 2016 at 12:21 PM, Andre Vieira
<Andre.SimoesDiasVieira@foss.arm.com> wrote:
> Hi Ambroz,
>
> Just to clarify as to why this change was made. The PRI*8 and SCN*8 macro's
> were printing '*' before, the pattern for 32-bit types, when the actual size
> of __INT8_TYPE__ was '8 bits', i.e. _WANT_IO_C99_FORMATS was defined. Which
> we agreed at the time was the wrong behavior.
>
> Now you are not the first to stumble onto this issue, though as FCh points
> out these are C99 types and the configurations you mentioned do not support
> these.
>
> On 01/01/16 23:03, Ambroz Bizjak wrote:
>>
>> Hi Freddie,
>>
>> I hope we agree that C99 support should not be an all-or-nothing
>> decision, you should be able to have some parts (like the stdint types
>> which cost nothing), but not other parts like the full C99 support in
>> printf. The worst part really is that the PRI*8 macros are defined in
>> the mentioned configurations but they do not work. I see that on the
>> other hand the SCN*8 macros are not defined when they would not work
>> (see the top comment in inttypes.h).
>>
> I do agree that it is weird that for the SCN*8 macros to be guarded with
> _WANT_IO_C99_FORMATS, whilst the PRI*8 are not. Though guarding PRI*8 would
> not solve your problem, as you seem to want these to be defined as '*', i.e.
> defaulting to their earlier behavior of returning the 32-bit format pattern.
> I would oppose doing this in all cases, since if _WANT_IO_C99_FORMATS is
> defined, then this would yield the erroneous behavior this patch was meant
> to fix.
>
> There might be a case to be made for doing so if _WANT_IO_C99_FORMATS is not
> defined. On the other hand, doing this for SCN*8 would be a bad idea in my
> opinion and this would keep the discrepancy between PRI*8 and SCN*8.
>
> I do not think we should encourage the use of PRI*8 and SCN*8 types if these
> are not supported by the library being used. As this seems to be the case,
> since _WANT_IO_C99_FORMATS is not defined, which I think would be the
> appropriate macro to indicate support for such.
>
>> But then we can have the PRI*8 macros for free anyway, so why should
>> they be available only when printf has "hh" support?
>>
>> Best regards,
>> Ambroz
>>
>>
>> On Fri, Jan 1, 2016 at 11:44 PM, Freddie Chopin <freddie_chopin@op.pl>
>> wrote:
>>>
>>> On piątek, 1 stycznia 2016 12:08:30 CET Ambroz Bizjak wrote:
>>>>
>>>> Hello,
>>>>
>>>> It appears to me that commit "Fix for pri and scn formats" [1] broke
>>>> the 8-bit printf format macros (PRI*8), for scenarios when newlib is
>>>> configured either with --enable-newlib-nano-formatted-io or without
>>>> --enable-newlib-io-c99-format is not used. Because the new code
>>>> defines these macros to the "hh" formats, which are not supported
>>>> then.
>>>
>>>
>>> Is it actually a problem that PRI* macros don't work without support for
>>> C99?
>>> After all, these are used for C99 types, so not really needed without
>>> C99...
>>>
>>> Regards,
>>> FCh
>>>
>>
>
> Further discussion is most welcome!
>
> Cheers,
> Andre



More information about the Newlib mailing list