From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS3215 2.6.0.0/16 X-Spam-Status: No, score=-4.0 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_REPLYTO_END_DIGIT, MAILING_LIST_MULTI,SPF_HELO_PASS,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 88CE51F9E0 for ; Sat, 25 Apr 2020 13:33:14 +0000 (UTC) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A11D8386F442; Sat, 25 Apr 2020 13:33:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A11D8386F442 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1587821592; bh=L31p5U/jRhAFd9+m4H3+rLks57j5ddJeV9XO7uAzDzE=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=LQ3cc/8TzouqcqfygDUK8/ShDY99GjSGj0h+trdVfITKCPXN55+W+Kly5nE2dCqNb VHU/yf6ihesByrhdddfSAKut3P7GMdAgm6cu3M5zUm0aMI3suM21Vcds70hmfN7YXp Yc0CqHdCHbyb28LX8CTjXhY2vJkhyB5DY8o/3Qy8= 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 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-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: , From: Alejandro Colomar via Libc-alpha Reply-To: Alejandro Colomar Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" 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.