From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A607D2BAF7 for ; Sun, 8 Mar 2026 11:37:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.41 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772969874; cv=none; b=lbx5/2HlA+nAuSzJpMkyYnhxbp4knLZHx/xBrYDT/kRA1JpZ289qAPIMwbgHvlzQqlS6oi7O8utSvMQDXdyODZPGELIlAY2Ro24ObfyvicswqxBvXZH03mtNufWYDHkDToGDkUx8kVZf0E8GJ1Bf9BNLK/FFF4bMKZ4tqQSaasc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772969874; c=relaxed/simple; bh=9vK5jPgthwUgOl1C2nL10dPirLKHjPGHuTazJ1MLP8U=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=GROHeYI/5UQVsqM5KD/azzOEsfLGWLh7aaL7o7slSa8Kyv/oe1Q29sO3hnEx10ml78hFnLeZyrdpFOCE+DutcNT1AAQEaEq8YQu7LtFakDplCap+CBmKfCXE5gic33euAOgFvHUpAY8QmY7I3O8dKSS6SeSodGfQEdHEWqgemfc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=KIzAKK6D; arc=none smtp.client-ip=209.85.128.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="KIzAKK6D" Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-4838c15e3cbso98465645e9.3 for ; Sun, 08 Mar 2026 04:37:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772969871; x=1773574671; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=A3S7zre2zEdGd304RRWOGOw45Xo6QmxiFJrVmtWZWJU=; b=KIzAKK6DBloFnx800yfhdjKm++2oE2yYQiJ67GI6l4tusNJFDEjN3uCcKsxKncgvlA FfY/9agMatIAucO+9TAFEbxSUYu4BC8rDJqj3wwSM3TtN8Jg9hIRLJAphcd5LkKU/d0z szdRVZWS3XYk9vJZOQcFNYTfV/1/6kfZbq+hrUP9UQJjYVTVEJn+/ak13Qlrubrizi3J JlgOLhIWw3uxekFwUpyYz8X/pq3qxXQfKPdXxFkghqgUwqDHXXNT+ihIgLQA1t9wGT0I kipV/1gcbYnMwR1Vv6IpHYdbaKbCUBT041KBSZbxoJFagYqCCs0xAe7NQfiE3irwkKGp fW+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772969871; x=1773574671; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=A3S7zre2zEdGd304RRWOGOw45Xo6QmxiFJrVmtWZWJU=; b=e6i0jXz2+6X24iGPewt0W/n8oEzgqUYvsSMWG8kVDsWLj5n6KJVtJrlIefYBPUHle3 qV0LzrZ5qtFolkRBw2BNYbVJh4RQOIKWH+QW8qYofEpDutXa/XE26T3HOCsBiD5iH3AD LRFlbrwfUatfTU8MkTbbtukNCaRyRm1W/7KjZEHFRsJSEb99qGUOkevlYSvWnRZ+hQh4 KcVAZKC0VijS4p8SE/l1XmI4oxxtKqb2F6wKKOXX6zEhsctkRUyzoaqiPjUQCv9aw5EL 2UDr+yiUR5BVN3zlbHOipcpZHCF1d61gdV9iS5X6J45Cl4qkDGA3quUnPQN7J1pwYzot j6kg== X-Forwarded-Encrypted: i=1; AJvYcCVUXGnjOIuOiyUWvAkhGpNrHJDXA2W/3lsXjo8SJqdprXCRTN3DJNOaOpvY/NPkposH+f+kBTswBHtytiI=@vger.kernel.org X-Gm-Message-State: AOJu0Yx+G79jJT1vsA5MuEnM/deGKmoEOkq6/RGWBvIUXerPxE4/DxwS T3HH8kvrWf+hGUpD/NnuU5umrOyLOF3ces1LhS+Hlk9mu6EH78WbwXLA X-Gm-Gg: ATEYQzyfWXssHQYcHk5+RR1Dl9qHaBHqrFtbiO/TsnKNa9ckcVuWP7rCP3Tsumzb+cW MCaCdioZfOPuQZ+eAof1NG/WG6leJkL/+FIbbDDOiqUvUzW122InyIC4Qd1AyFKtleMiRKQLVJf 8Oj4i6rfqWdKYLRQQEtcvwUd2+GQTnCQL2sNIJ7t3QdLXyJA0R0NWh4WLEtRHO6s5ScBf1m89/w FdrreQGZyr7PyGHeCCQuo+rrfxiy1shIGT0uW+lzgWjkfqMmcIWFTKfOMlN5qK1X22zkgv3C9IA EZf/+WxYE/LQgTr33SNQSlEUupDbmK/fbZMifwlZ0B8j573bOn1xJgvaalIWLCnp3swKn+DtPtm 47YoffD6VPadtsez/ouQOtes70h/Prs3heHzDHrwWs395V1G06HVJr4GbFbYIwPreX4NLm1IR3J ETlFvOS0ayhJtibyzN8TL3W2pLBFX890uMQ/fWMwceqUqpSi8nvo9GTXIHnKFodALdRuUdRIYB3 7womOJPU7QL X-Received: by 2002:a05:600c:4fcc:b0:480:2521:4d92 with SMTP id 5b1f17b1804b1-48526964a1fmr125011225e9.24.1772969870823; Sun, 08 Mar 2026 04:37:50 -0700 (PDT) Received: from snowdrop.snailnet.com (82-69-66-36.dsl.in-addr.zen.co.uk. [82.69.66.36]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-485237dd017sm63621855e9.2.2026.03.08.04.37.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 08 Mar 2026 04:37:50 -0700 (PDT) From: david.laight.linux@gmail.com To: Willy Tarreau , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , linux-kernel@vger.kernel.org, Cheng Li Cc: David Laight Subject: [PATCH v5 next 00/17] Enhance printf() Date: Sun, 8 Mar 2026 11:37:25 +0000 Message-Id: <20260308113742.12649-1-david.laight.linux@gmail.com> X-Mailer: git-send-email 2.39.5 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: David Laight Update printf() so that it handles almost all the non-fp formats. In particular: - Left alignment. - Zero padding. - Alternate form "%#x" and "%#o". - Field precision. - Variable field width and precision. - Width modifiers q, L, t and z. - Conversion specifiers i, o and X (X generates lower case). About the only things that are missing are wide chanacters and floating point. The tests are updated to match. Bloat/savings (in nolibc-test, but excluding the program) to patch 11: (Measured for v3) Function old new delta _nolibc_u64toa_base.isra - 143 +143 strerror - 78 +78 __nolibc_sprintf_cb 58 91 +33 itoa_r.isra 60 75 +15 utoa_r.isra 144 - -144 __nolibc_printf 1081 729 -352 (All these functions include ~40 bytes for the stack protector code.) utoa_r.isra and _nolibc_u64toa_base.isra pretty much cancel each other out. itoa_r.isra grows slightly since it calls _nolibc_u64toa_base(). strerror() used to be inlined, but over half of it is the stack check. While some of the code added to __nolibc_sprintf_cb() has come out of __nolibc_printf() 16-20 bytes is removed from the caller. So there is a net saving of about 280 bytes (including losing a copy of the number to ascii code). The later patches add code back in: patch 13 - conversion flags " +#" +80 bytes patch 14 - left aligning fields +38 bytes patch 15 - zero padding and field precision +260 bytes patch 16 - octal output +34 bytes So probably about +130 bytes, but it will depend on what the application actually calls and inlining decisions made by the compiler. (All x86-64, other architectures will vary.) The biggest size change is probably removing the .data from strerror(). This reduced the program binary file by 4k if it is the only initialised data in a small program. Changes for v5: - Old patches 2 to 7 have been applied to nolibc-next and removed. - Patch 3 changed to return the correct (success/fail not length) value from strerror_r() and to return ERANGE if the buffer is short. - Patch 11 (prepend sign) has an updated comment. Changes for v4: - Old patches 2, 3 and 6 have been applied to nolibc-next and removed. - Patch 7 (fix padding) has been moved before the selftest changes so that the tests don't fail. - NOLIBC_IGNORE_ERRNO is left only applying to %m and not strerror(). - Avoid calling memcpy(tgt, NULL, 0) in the vsnprintf callback function. - Some of the patches have been split. The final version of stdio.h only differs from v3 in the strerror() and vsnprintf callback code. Significant changes for v3: The patches have been re-ordered, split and joined but the final code is pretty much the same as v2. - Include the patch to stdlib.h that optimises the 'number to ascii' functions. This is needed for the final patch that adds octal support. This includes a fix to the previous version that could generate negative digits. - Add octal support in the final patch. - Update the selftests as new features are added. - The patch to buffer fprintf() output has been removed. Changes for v2: Mostly changes to improve the readability of the code. - New patch #1 inserted to rename the variable 'c' to 'ch'. - Use #define 'magic' for the bit-masks that check multiple characters. The check for the conversion flag characters is then based on: ch_flag = _NOLIBC_PF_CHAR_IS_ONE_OF(ch, ' ', '#', '+', '-', '0'); - Re-order the changes so that the old patch 10 (Use bit-pattern for integral formats) is done at the same time as bit-masks are used for the flags characters and length modifiers. This means the restructuring changes are done before new features are added. - Put all the changes to the selftest together at the end. There is one extra test for ("%#01x", 0x1234) (should be "0x1234") which is problematic because once you've removed the length of the "0x" from the field width there are -1 character postions for the digits. David Laight (17): tools/nolibc: Add _NOLIBC_OPTIMIZER_HIDE_VAR() to compiler.h selftests/nolibc: Rename w to written in expect_vfprintf() tools/nolibc: Implement strerror() in terms of strerror_r() tools/nolibc: Rename the 'errnum' parameter to strerror() tools/nolibc/printf: Output pad characters in 16 byte chunks tools/nolibc/printf: Simplify __nolibc_printf() tools/nolibc/printf: Use goto and reduce indentation tools/nolibc/printf: Use bit-masks to hold requested flag, length and conversion chars tools/nolibc/printf: Add support for length modifiers tzqL and formats iX tools/nolibc/printf: Handle "%s" with the numeric formats tools/nolibc/printf: Prepend sign to converted number tools/nolibc/printf: Add support for conversion flags space and plus tools/nolibc/printf: Special case 0 and add support for %#x tools/nolibc/printf: Add support for left aligning fields tools/nolibc/printf: Add support for zero padding and field precision tools/nolibc/printf: Add support for octal output selftests/nolibc: Use printf variable field widths and precisions tools/include/nolibc/compiler.h | 3 + tools/include/nolibc/stdio.h | 427 ++++++++++++++----- tools/testing/selftests/nolibc/nolibc-test.c | 99 +++-- 3 files changed, 371 insertions(+), 158 deletions(-) -- 2.39.5