From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x341.google.com (mail-wm1-x341.google.com [IPv6:2a00:1450:4864:20::341]) by sourceware.org (Postfix) with ESMTPS id 35DBF385DC1C for ; Sat, 25 Apr 2020 13:33:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 35DBF385DC1C Received: by mail-wm1-x341.google.com with SMTP id g12so14849993wmh.3 for ; Sat, 25 Apr 2020 06:33:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-language:content-transfer-encoding; bh=L31p5U/jRhAFd9+m4H3+rLks57j5ddJeV9XO7uAzDzE=; b=hmkriVl7U5PZO8kh0mOfPGSsKXTf35L1gDwhNmsStDhAciNC+c6sfGYC+bAowjNel5 2O9eEzHbrQzgUjRYmStChmSlzuJXOAG3utEnYc4lJvp0If4Xr6YJ+QlsZZ+8rKct9jO1 xibqCPLfe+xPhlpwuSrl07LVpY951X/mXyzJjOBza6pApQ02ps9jCnFM5j2dOsuEWuxC VVs+dL8YyTFIk+VM/CLrhnCIdaJ+n95+A/ffWwXwySgJYjBVKItLKW4Upt7hKhXvdsad 4rhDbpZfnuGQdKM99rYRZMD1qROrJWgpQzbzWvsWTwGD45RaDaHOdZYgkU7Sg6Z6khLT zA1Q== X-Gm-Message-State: AGi0PuZNTxCQ+NujOSL/AMCzwnMbvvxs3v5CvgfC0eDck+vSVkrQgMBM RfPgEae+5rxph6/qvvsbwD3Ybb2f X-Google-Smtp-Source: APiQypLj34bNJUhaB+u6Nh2ceAhghI2M2RV/ASVVIV0QbOeU/bpBuV2azq+J6cq1x+psmwP5viYEnA== X-Received: by 2002:a05:600c:210:: with SMTP id 16mr15376460wmi.57.1587821587659; Sat, 25 Apr 2020 06:33:07 -0700 (PDT) Received: from [192.168.1.131] ([93.176.137.11]) by smtp.gmail.com with ESMTPSA id l4sm13000056wrv.60.2020.04.25.06.33.06 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 25 Apr 2020 06:33:07 -0700 (PDT) To: libc-alpha@sourceware.org From: Alejandro Colomar Subject: printf %b Message-ID: <1137ece3-27fb-0ca8-22df-dcc69077f354@gmail.com> Date: Sat, 25 Apr 2020 15:33:05 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-6.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, GIT_PATCH_2, KAM_LOTSOFHASH, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 25 Apr 2020 13:33:11 -0000 Hi all, In my personal library, about a year ago, I wrote a function to register the ``b`` and ``B`` conversion specifiers using ``register_printf_specifier()``. They work the closest possible to ``o``, ``u``, ``x`` & ``X``: - All "flag characters" behave as in ``x``, ``X`` (or as close as possible, while being meaningful). - "Field width" and "precision" behave as in ``x``, ``X`` (or as close as possible, while being meaningful). - All "length modifiers" that are valid on ``o``, ``u``, ``x``, ``X`` are valid. - There are some flags that override others in the case of ``o``, ``u``, ``x``, ``X``. Those behaviours have been kept the same. - I decided that the ``'`` flag character, which normally should group the output in thousands in decimal numbers, and is ignored in hexadecimal numbers, would be more meaningful here if it grouped nibbles (half bytes), and instead of using the locale for thousands separator, it should use ``_``. Basically, from reading the documentation for other conversion specifiers, one should have a good idea of how it works. Here's the source code: https://github.com/alejandro-colomar/libalx/blob/master/src/base/stdio/printf/b.c I did some testing, and it works as expected. It is interesting to show how it works: .. code-block:: c #include #include #include #include #include int main(void) { int len; char buff[BUFSIZ]; alx_printf_b_init(); snprintf(buff, 30, "Hey, %i == %#b :)\n", 5, 5); printf("%s", buff); printf("\n"); printf("....----....----....----....----\n"); len = printf("%llb;\n", 0x5Ellu); printf("%i\n", len - strlen(";\n")); len = printf("%lB;\n", 0x5Elu); printf("%i\n", len - strlen(";\n")); len = printf("%b;\n", 0x5Eu); printf("%i\n", len - strlen(";\n")); len = printf("%hB;\n", 0x5Eu); printf("%i\n", len - strlen(";\n")); len = printf("%hhb;\n", 0x5Eu); printf("%i\n", len - strlen(";\n")); len = printf("%jb;\n", (uintmax_t)0x5E); printf("%i\n", len - strlen(";\n")); len = printf("%zb;\n", (size_t)0x5E); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%#b;\n", 0x5Eu); printf("%i\n", len - strlen(";\n")); len = printf("%#B;\n", 0x5Eu); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%10b;\n", 0x5Eu); printf("%i\n", len - strlen(";\n")); len = printf("%010b;\n", 0x5Eu); printf("%i\n", len - strlen(";\n")); len = printf("%.10b;\n", 0x5Eu); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%-10B;\n", 0x5Eu); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%'B;\n", 0x5Eu); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); printf("....----....----....----....----\n"); len = printf("%#16.12b;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%-#'20.12b;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%#'020B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%#020B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%'020B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%020B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%#021B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%'021B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%021B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%#022B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%'022B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%022B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%#023B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%'023B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%023B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%-#'19.11b;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%#'019B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%#019B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%'019B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%019B;\n", 0xAB); printf("%i\n", len - strlen(";\n")); len = printf("%#016b;\n", 0xAB); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); printf("....----....----....----....----\n"); len = printf("%'010B;\n", 0xB); printf("%i\n", len - strlen(";\n")); len = printf("%#'010B;\n", 0xB); printf("%i\n", len - strlen(";\n")); len = printf("%'010B;\n", 0x1B); printf("%i\n", len - strlen(";\n")); len = printf("%#'010B;\n", 0x1B); printf("%i\n", len - strlen(";\n")); len = printf("%'010B;\n", 0x2B); printf("%i\n", len - strlen(";\n")); len = printf("%#'010B;\n", 0x2B); printf("%i\n", len - strlen(";\n")); len = printf("%'010B;\n", 0x4B); printf("%i\n", len - strlen(";\n")); len = printf("%#'010B;\n", 0x4B); printf("%i\n", len - strlen(";\n")); len = printf("%'010B;\n", 0x8B); printf("%i\n", len - strlen(";\n")); len = printf("%#'010B;\n", 0x8B); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%'010B;\n", 0xB); printf("%i\n", len - strlen(";\n")); len = printf("%#'010B;\n", 0xB); printf("%i\n", len - strlen(";\n")); len = printf("%'011B;\n", 0xB); printf("%i\n", len - strlen(";\n")); len = printf("%#'011B;\n", 0xB); printf("%i\n", len - strlen(";\n")); len = printf("%'012B;\n", 0xB); printf("%i\n", len - strlen(";\n")); len = printf("%#'012B;\n", 0xB); printf("%i\n", len - strlen(";\n")); len = printf("%'013B;\n", 0xB); printf("%i\n", len - strlen(";\n")); len = printf("%#'013B;\n", 0xB); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%'010B;\n", 0x1B); printf("%i\n", len - strlen(";\n")); len = printf("%#'010B;\n", 0x1B); printf("%i\n", len - strlen(";\n")); len = printf("%'011B;\n", 0x1B); printf("%i\n", len - strlen(";\n")); len = printf("%#'011B;\n", 0x1B); printf("%i\n", len - strlen(";\n")); len = printf("%'012B;\n", 0x1B); printf("%i\n", len - strlen(";\n")); len = printf("%#'012B;\n", 0x1B); printf("%i\n", len - strlen(";\n")); len = printf("%'013B;\n", 0x1B); printf("%i\n", len - strlen(";\n")); len = printf("%#'013B;\n", 0x1B); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%'010B;\n", 0x2B); printf("%i\n", len - strlen(";\n")); len = printf("%#'010B;\n", 0x2B); printf("%i\n", len - strlen(";\n")); len = printf("%'011B;\n", 0x2B); printf("%i\n", len - strlen(";\n")); len = printf("%#'011B;\n", 0x2B); printf("%i\n", len - strlen(";\n")); len = printf("%'012B;\n", 0x2B); printf("%i\n", len - strlen(";\n")); len = printf("%#'012B;\n", 0x2B); printf("%i\n", len - strlen(";\n")); len = printf("%'013B;\n", 0x2B); printf("%i\n", len - strlen(";\n")); len = printf("%#'013B;\n", 0x2B); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%'010B;\n", 0x4B); printf("%i\n", len - strlen(";\n")); len = printf("%#'010B;\n", 0x4B); printf("%i\n", len - strlen(";\n")); len = printf("%'011B;\n", 0x4B); printf("%i\n", len - strlen(";\n")); len = printf("%#'011B;\n", 0x4B); printf("%i\n", len - strlen(";\n")); len = printf("%'012B;\n", 0x4B); printf("%i\n", len - strlen(";\n")); len = printf("%#'012B;\n", 0x4B); printf("%i\n", len - strlen(";\n")); len = printf("%'013B;\n", 0x4B); printf("%i\n", len - strlen(";\n")); len = printf("%#'013B;\n", 0x4B); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); len = printf("%'010B;\n", 0x8B); printf("%i\n", len - strlen(";\n")); len = printf("%#'010B;\n", 0x8B); printf("%i\n", len - strlen(";\n")); len = printf("%'011B;\n", 0x8B); printf("%i\n", len - strlen(";\n")); len = printf("%#'011B;\n", 0x8B); printf("%i\n", len - strlen(";\n")); len = printf("%'012B;\n", 0x8B); printf("%i\n", len - strlen(";\n")); len = printf("%#'012B;\n", 0x8B); printf("%i\n", len - strlen(";\n")); len = printf("%'013B;\n", 0x8B); printf("%i\n", len - strlen(";\n")); len = printf("%#'013B;\n", 0x8B); printf("%i\n", len - strlen(";\n")); printf("....----....----....----....----\n"); return 0; } And the results: :: Hey, 5 == 0b101 :) ....----....----....----....---- 11111111111111000000000000000000000000001011110; 47 11111111111111000000000000000000000000001011110; 47 1011110; 7 1011110; 7 1011110; 7 11111111111111000000000000000000000000001011110; 47 11111111111111000000000000000000000000001011110; 47 ....----....----....----....---- 0b1011110; 9 0B1011110; 9 ....----....----....----....---- 1011110; 10 0001011110; 10 0001011110; 10 ....----....----....----....---- 1011110 ; 10 ....----....----....----....---- 101_1110; 8 ....----....----....----....---- ....----....----....----....---- 0b000010101011; 16 0b0000_1010_1011 ; 20 0B000_0000_1010_1011; 20 ....----....----....----....---- 0B000000000010101011; 20 0_0000_0000_1010_1011; 21 00000000000010101011; 20 ....----....----....----....---- 0B0000000000010101011; 21 0_0000_0000_1010_1011; 21 000000000000010101011; 21 ....----....----....----....---- 0B00000000000010101011; 22 00_0000_0000_1010_1011; 22 0000000000000010101011; 22 ....----....----....----....---- 0B000000000000010101011; 23 000_0000_0000_1010_1011; 23 00000000000000010101011; 23 ....----....----....----....---- 0b000_1010_1011 ; 19 0B00_0000_1010_1011; 19 0B00000000010101011; 19 ....----....----....----....---- 0000_0000_1010_1011; 19 0000000000010101011; 19 0b00000010101011; 16 ....----....----....----....---- ....----....----....----....---- 0_0000_1011; 11 0B000_1011; 10 0_0001_1011; 11 0B001_1011; 10 0_0010_1011; 11 0B010_1011; 10 0_0100_1011; 11 0B100_1011; 10 0_1000_1011; 11 0B1000_1011; 11 ....----....----....----....---- 0_0000_1011; 11 0B000_1011; 10 0_0000_1011; 11 0B0000_1011; 11 00_0000_1011; 12 0B0_0000_1011; 13 000_0000_1011; 13 0B0_0000_1011; 13 ....----....----....----....---- 0_0001_1011; 11 0B001_1011; 10 0_0001_1011; 11 0B0001_1011; 11 00_0001_1011; 12 0B0_0001_1011; 13 000_0001_1011; 13 0B0_0001_1011; 13 ....----....----....----....---- 0_0010_1011; 11 0B010_1011; 10 0_0010_1011; 11 0B0010_1011; 11 00_0010_1011; 12 0B0_0010_1011; 13 000_0010_1011; 13 0B0_0010_1011; 13 ....----....----....----....---- 0_0100_1011; 11 0B100_1011; 10 0_0100_1011; 11 0B0100_1011; 11 00_0100_1011; 12 0B0_0100_1011; 13 000_0100_1011; 13 0B0_0100_1011; 13 ....----....----....----....---- 0_1000_1011; 11 0B1000_1011; 11 0_1000_1011; 11 0B1000_1011; 11 00_1000_1011; 12 0B0_1000_1011; 13 000_1000_1011; 13 0B0_1000_1011; 13 ....----....----....----....---- I would like to add this feature to glibc, if you are interested in it. I have been reading through the glibc source code, and I guess the only file I should modify is ``stdio-common/vfprintf-internal.c`` (correct me if I'm missing something). How should I document the new feature? Which files should I modify for that? This is the first time I step into glibc code seriously, so I don't have any experience in how the library is organized at all. Please tell me which steps should I follow to write this patch. After this, I would like to write another patch for the ``scanf`` family of functions, but that's future. Alex. P.S.: Please CC me as I'm not subscribed to this mailing list.