avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-libc-dev] printf behaviour change question


From: George Spelvin
Subject: [avr-libc-dev] printf behaviour change question
Date: 9 Dec 2016 22:34:33 -0500

While I'm poking about in the bowels of printf, one significant
problem I'm facing is figuring out where to store the argument
size.  FL_LONG isn't enough to distinguish %d, %ld and %lld, and
we're out of flag bits!

But ingenuity provides a solution, and I realized that the FL_WIDTH,
FL_PREC and FL_LONG bits are assigned in the order in which they
are parsed.  Once the width is seen, flags are not interpreted any more.
Once the precision is seen, digits aren't part of the width any more.
And once a long flag is seen, only format characters are valid.

But... once FL_LONG is set, FL_WIDTH isn't used any more.

So when we see the first l flag, we can set FL_LONG, clear FL_WIDTH,
and then use FL_WIDTH for FL_LONGLONG.

Yay!  Problem solved!  Except...

Eventually we need a length in bytes.  2, 4 or 8.  I have a
COPYBIT macro with which I can do this failrly efficiently:
#define COPYBIT(dst, dmask, src, smask) \
    asm(        "bst %2,%3"             \
        "\n     bld %0,%1"              \
        : "=r" (dst)                    \
        : "I" (ntz(dmask)),             \
          "r" (src),                    \
          "I" (ntz(smask)))

(I could replace that "I" constraint with "LPKC03C04C05C06C07" to express
the limit more accurately, but I'm not going to bother; the assembler
gives a better error message than the compiler anyway.)

        bytes = 0;
        COPYBIT(bytes,2,flags,FL_LONG)
        COPYBIT(bytes,4,flags,FL_LONGLONG);
        bytes += 2;


However, there's something else I could use FL_WIDTH for.
One useful property of ASCII is that 'x' == 'X' | 0x20.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]