lkml.org 
[lkml]   [2024]   [Apr]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    SubjectRe: [RFC] Printing numbers in SI units
    Hi Rasmus,

    On Wed, Jan 24, 2024 at 11:43 PM Rasmus Villemoes
    <linux@rasmusvillemoes.dk> wrote:
    > On 24/01/2024 19.58, Matthew Wilcox wrote:
    > > I was looking at hugetlbfs and it has several snippets of code like
    > > this:
    > >
    > > string_get_size(huge_page_size(h), 1, STRING_UNITS_2, buf, 32);
    > > pr_warn("HugeTLB: allocating %u of page size %s failed node%d. Only allocated %lu hugepages.\n",
    > > h->max_huge_pages_node[nid], buf, nid, i);
    > >
    > > That's not terribly ergonomic, so I wondered if I could do better.
    > > Unfortunately, I decided to do it using the SPECIAL flag which GCC
    > > warns about. But I've written the code now, so I'm sending it out in
    > > case anybody has a better idea for how to incorporate it.
    >
    > Well, something that gcc will warn about with Wformat isn't gonna fly,
    > obviously. But my man page also mentions ' as a possible flag for d
    > conversions:
    >
    > ' For decimal conversion (i, d, u, f, F, g, G) the output is
    > to be grouped with thousands'
    > grouping characters if the locale information indicates any.

    > Obviously, our printf wouldn't implement that, [...]

    Why not? ;-)

    Old Gmail-white-space-damaged patch below, which I wrote when I got
    fed up with meticulously counting zeros in GHz-range clock
    frequencies...

    Author: Geert Uytterhoeven <geert+renesas@glider.be>
    Date: Thu Aug 11 13:52:46 2016 +0200

    lib/vsprintf.c: Add support for thousands' grouping

    Use an underscore as the grouping character.

    TODO:
    - Documentation
    - Self test
    - Do we want to use this in /sys/kernel/debug/clk/clk_summary ?
    RFC patch, compatibility was already broken by commit
    e55a839a7a1c561b ("clk: add clock protection mechanism to clk
    core")

    Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
    ---
    Originally I wanted to use grouping by 4 for octal and hexadecimal
    numbers. Unfortunately gcc prints a warning when using the grouping
    character with octal and hexadecimal numbers:

    warning: ''' flag used with '%x' gnu_printf format [-Wformat=]
    warning: ''' flag used with '%o' gnu_printf format [-Wformat=]

    diff --git a/lib/vsprintf.c b/lib/vsprintf.c
    index f4a8bfacb70befbc..51e516cf4cc68156 100644
    --- a/lib/vsprintf.c
    +++ b/lib/vsprintf.c
    @@ -414,6 +414,9 @@ int num_to_str(char *buf, int size, unsigned long
    long num, unsigned int width)
    #define ZEROPAD 16 /* pad with zero, must be 16
    == '0' - ' ' */
    #define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */
    #define SPECIAL 64 /* prefix hex with "0x", octal
    with "0" */
    +#define GROUP 128 /* thousands' grouping */
    +// warning: ''' flag used with '%x' gnu_printf format [-Wformat=]
    +// warning: ''' flag used with '%o' gnu_printf format [-Wformat=]

    static_assert(SIGN == 1);
    static_assert(ZEROPAD == ('0' - ' '));
    @@ -462,7 +465,7 @@ char *number(char *buf, char *end, unsigned long long num,
    char sign;
    char locase;
    int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);
    - int i;
    + int i, j;
    bool is_zero = num == 0LL;
    int field_width = spec.field_width;
    int precision = spec.precision;
    @@ -511,6 +514,11 @@ char *number(char *buf, char *end, unsigned long long num,
    i = put_dec(tmp, num) - tmp;
    }

    + /* take into account grouping characters */
    + j = i;
    + if (spec.flags & GROUP)
    + i += (j - 1) / 3;
    +
    /* printing 100 using %2d gives "100", not "00" */
    if (i > precision)
    precision = i;
    @@ -559,10 +567,16 @@ char *number(char *buf, char *end, unsigned long long num,
    ++buf;
    }
    /* actual digits of result */
    - while (--i >= 0) {
    + while (--j >= 0) {
    if (buf < end)
    - *buf = tmp[i];
    + *buf = tmp[j];
    ++buf;
    + if ((spec.flags & GROUP) && j && !(j % 3)) {
    + if (buf < end)
    + // FIXME '\''
    + *buf = '_';
    + ++buf;
    + }
    }
    /* trailing space padding */
    while (--field_width >= 0) {
    @@ -2567,6 +2581,7 @@ int format_decode(const char *fmt, struct
    printf_spec *spec)
    case ' ': spec->flags |= SPACE; break;
    case '#': spec->flags |= SPECIAL; break;
    case '0': spec->flags |= ZEROPAD; break;
    + case '\'': spec->flags |= GROUP; break;
    default: found = false;
    }

    Gr{oetje,eeting}s,
    Geert

    --
    Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68korg

    In personal conversations with technical people, I call myself a hacker. But
    when I'm talking to journalists I just say "programmer" or something like that.
    -- Linus Torvalds

    \
     
     \ /
      Last update: 2024-05-27 18:05    [W:3.108 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site