printf behaviour change question

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

printf behaviour change question

George Spelvin
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;
        bytes += 2;

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

AVR-libc-dev mailing list
[hidden email]