From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) (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 85DCE36D4E1 for ; Sun, 8 Mar 2026 11:37:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.48 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772969877; cv=none; b=GRO5HSdfX7yXkS958npGQdIbOKFF7ezx8N0o9v8MbMvgw7aNBDPby+eySpygw9MkvzCuvpj+XUg3TwQesgkMX1xYzR5okTmFw4c/rPjdqL0eg95A00oP9uPXvgMR1vYUnE5z2aNWHUQKTFyWDJYxQi8lxif8r/4A7EBNVsuSjro= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772969877; c=relaxed/simple; bh=mQgFGwZjNvWzXWAPbcmUAKsDXOojzwYc3Guo0+OAJ/U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=S/3mRHlytlgueAHy7yqdI8GHbLa0BaWTrUiFaKv6Fo6xzt6GuuEkpkqY5yd+m6xeqUnRmpNTmS91gYV9rbYQkspb26GtC2gSxgFjC9jldDFuFviMVRyGP4CKV7RgzGX8TfBiR5/MUuFc4QaCHNGmxAjfEiqvsD4UXfx/YsTg9ak= 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=helkUsnD; arc=none smtp.client-ip=209.85.128.48 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="helkUsnD" Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-4853510b4f3so6184985e9.0 for ; Sun, 08 Mar 2026 04:37:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772969874; x=1773574674; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=IaIYyPCgZxopQGmoMQuP53IISO9sbx5leX51cpyI1nA=; b=helkUsnDSbpF7G+YIVFGKh571fXRb/KkT+hTXDRHQBHltpcmMvqY+nNEzlSaRo2rbt 6tvxBdvGgpfWUYyEdROF+nO5AeI0fl4gJNPwFWSEeEj2F4Z9282kDCNZlpOMUjx7zEyQ 2QuSY9mS4uRZRcR7lI9qwBZhTeFp47t14CeyynSQt16ZPlK09wYqlsldnhpmcuRbaE6Y 77mNftBYaz0lgWW2UY6eVfr5qy7bqTPI5PP3ZW5uhJ4PAgNcHwzezSArSUKBqi1LhuK6 8qXDComNOfcJxDlRDiffnIu8rKOIqfDzogeJKWMLtHayt8UZI2YZbm8qoF/nqrgGp4te tdZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772969874; x=1773574674; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=IaIYyPCgZxopQGmoMQuP53IISO9sbx5leX51cpyI1nA=; b=SVhYIJj+OdBMdgBqwiaEo3I/CE9iQhaHr/OCNMKJIJIbwaTQcnj6zsfvkpBLDlYcZx T9NaMDZA14FPibkdKQXIVy9/ltIgr1vPC8iJIZGHWfth+NFVlmeM/s30M1Y9v0FUeBcr drLo7HzCFQ3icWo8+At4LmrkCHYyNaENm7oPxM3wr7uVEUKp8oxlWZWXv42SDtM4pSxR 9/1dkiy/z9M57Cr4wkJPaZDkGDa3MLNHfYaKlYj3nqMc4Pc9btEsLuPh8v3hcd34esBZ v356vy+YTE/2c5E5eX0DnhTn4Wg/CTTIg5eAbqZIwUPtYukzCB+3qSc9zLZOZ8rGVoes Up+Q== X-Forwarded-Encrypted: i=1; AJvYcCUwEcXOl/m98IVuxyse0b7v/Yk9TrScxOuhSmakiPX7vrHrsxGDUv+0u80V6AFO+HpjQFRk9YmL+Hkuu6s=@vger.kernel.org X-Gm-Message-State: AOJu0YwF9IOPM3VxF4UYZt8yAdhBu/0Tg/ccinlcXPmJGzlHo1u+Vwtx n8c+My/excGLgjv+KtIMhhuKVIvZ1l+Fazs33r0aLLXIZTTaL8Z+91qN X-Gm-Gg: ATEYQzxRv0cIgpaqi5iTAfagrpAhR5L+IAxJ6+RPdI+2h7tyIGkh+SB+yhXpa1114b3 h/sSX37uCoXNBIsMaFpoWageLDijEXzPr+cNHqoqhBxZgAsMYJR5Q4vUQLp1Vik2m2p/3Lz/ygX o7CX06Xek3XLx840rLMdnrdnJ2yvdgqWPSch6KJ3d1zGiEdxAPFB3auOQRDEEP9Up1x3h+shUcr oBEL7V3yKHvTaXdhrKDYvtNRYaVVV03rHja+ro5cT1jjK93tWCKk/h75KrTqKPxd6C+ZqmvMSPp mbfHr2Gc7FOrni/ZL1gtumMX9V77gsj+LxZV1D/8z4CbgImo89DXuSyXm+ddngqSq1GBUtBViB1 6Zb8yO0OtOOe8C6NyyWlQ9NBqo/ZUcQqqKQFFNWbRawTBy6EI1dn2EW0KD7mMdmYmuOau0gm2T2 2yBZJQe9ivde0d1RRdE3byHDLXZAMd0QEKvsWnrEn1mBo6HGCMncwfvJ+JTOH5XNsbhsi2wcqU3 q9q/gm+PKvb X-Received: by 2002:a05:600c:1e88:b0:477:6d96:b3e5 with SMTP id 5b1f17b1804b1-48526916beamr154065155e9.7.1772969873810; Sun, 08 Mar 2026 04:37:53 -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.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 08 Mar 2026 04:37:53 -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 06/17] tools/nolibc/printf: Simplify __nolibc_printf() Date: Sun, 8 Mar 2026 11:37:31 +0000 Message-Id: <20260308113742.12649-7-david.laight.linux@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260308113742.12649-1-david.laight.linux@gmail.com> References: <20260308113742.12649-1-david.laight.linux@gmail.com> 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 Move the check for the length modifiers into the format processing between the field width and conversion specifier. This lets the loop be simplified and a 'fast scan' for a format start used. If an error is detected (eg an invalid conversion specifier) then copy the invalid format to the output buffer. Reduces code size by about 10% on x86-64. Some versions of gcc bloat this version by generating a jump table. All goes away in the later patches. Acked-By; Willy Tarreau Signed-off-by: David Laight --- No change for v3, v4 or v5. tools/include/nolibc/stdio.h | 104 ++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index c6d5d075f012..b3cfed162eb6 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -310,28 +310,52 @@ typedef int (*__nolibc_printf_cb)(void *state, const char *buf, size_t size); static __attribute__((unused, format(printf, 3, 0))) int __nolibc_printf(__nolibc_printf_cb cb, void *state, const char *fmt, va_list args) { - char escape, lpref, ch; + char lpref, ch; unsigned long long v; int written, width, len; - size_t ofs; char outbuf[21]; const char *outstr; - written = ofs = escape = lpref = 0; + written = 0; while (1) { - ch = fmt[ofs++]; + outstr = fmt; + ch = *fmt++; + if (!ch) + break; + width = 0; + if (ch != '%') { + while (*fmt && *fmt != '%') + fmt++; + /* Output characters from the format string. */ + len = fmt - outstr; + } else { + /* we're in a format sequence */ - if (escape) { - /* we're in an escape sequence, ofs == 1 */ - escape = 0; + ch = *fmt++; /* width */ while (ch >= '0' && ch <= '9') { width *= 10; width += ch - '0'; - ch = fmt[ofs++]; + ch = *fmt++; + } + + /* Length modifiers */ + if (ch == 'l') { + lpref = 1; + ch = *fmt++; + if (ch == 'l') { + lpref = 2; + ch = *fmt++; + } + } else if (ch == 'j') { + /* intmax_t is long long */ + lpref = 2; + ch = *fmt++; + } else { + lpref = 0; } if (ch == 'c' || ch == 'd' || ch == 'u' || ch == 'x' || ch == 'p') { @@ -387,56 +411,34 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *state, const char *fmt, va_list #else outstr = strerror(errno); #endif /* NOLIBC_IGNORE_ERRNO */ - } - else if (ch == '%') { - /* queue it verbatim */ - continue; - } - else { - /* modifiers or final 0 */ - if (ch == 'l') { - /* long format prefix, maintain the escape */ - lpref++; - } else if (ch == 'j') { - lpref = 2; + } else { + if (ch != '%') { + /* Invalid format: back up to output the format characters */ + fmt = outstr + 1; + /* and output a '%' now. */ } - escape = 1; - goto do_escape; + /* %% is documented as a 'conversion specifier'. + * Any flags, precision or length modifier are ignored. + */ + width = 0; + outstr = "%"; } len = strlen(outstr); - goto flush_str; } - /* not an escape sequence */ - if (ch == 0 || ch == '%') { - /* flush pending data on escape or end */ - escape = 1; - lpref = 0; - outstr = fmt; - len = ofs - 1; - flush_str: - width -= len; - while (width > 0) { - /* Output pad in 16 byte blocks with the small block first. */ - int pad_len = ((width - 1) & 15) + 1; - width -= pad_len; - written += pad_len; - if (cb(state, " ", pad_len) != 0) - return -1; - } - if (cb(state, outstr, len) != 0) - return -1; + written += len; - written += len; - do_escape: - if (ch == 0) - break; - fmt += ofs; - ofs = 0; - continue; + width -= len; + while (width > 0) { + /* Output pad in 16 byte blocks with the small block first. */ + int pad_len = ((width - 1) & 15) + 1; + width -= pad_len; + written += pad_len; + if (cb(state, " ", pad_len) != 0) + return -1; } - - /* literal char, just queue it */ + if (cb(state, outstr, len) != 0) + return -1; } /* Request a final '\0' be added to the snprintf() output. -- 2.39.5