From nobody Sun Feb 8 13:08:53 2026 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (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 B5EC832E72C for ; Tue, 3 Feb 2026 10:30:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770114616; cv=none; b=Fr4t/u88v08Nm6BJo7xt41l3SN8/lDE1/MiC2zJTvI7yvwp0plsaoyVdtaZ+5dT/P7AHTRW4cclowSZuygiig8dJEcsWwpBhZShZdlfjW9R684WvO1mH/hbf4P9eSnuhCoi7pyVj/Oy7SEKPCkShOhIV3DI0qIy3Ny0QFJW1uxU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770114616; c=relaxed/simple; bh=4jetbA/VxAZeSNU7MMJqqCXP0XvvvWVVTgPuEqk5rMk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PRcbiT6/ja6AIWlSne3Bo3ksaoUTrB7guABwtrcyvToWAWDUVrC3MwGwg7nDS0MF4CQ0j3HI4WYuGyP3T1N07R/tJ8YagWk5LHjC1/bCUQCH2prT1ESAAebbWh2GgWTXVFpb9C+cN0qOVBby0buPWaGKh45TVB4uwos/65HJ7sU= 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=k7N1cHjm; arc=none smtp.client-ip=209.85.128.50 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="k7N1cHjm" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-47ee2715254so29369215e9.3 for ; Tue, 03 Feb 2026 02:30:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1770114613; x=1770719413; 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=wFeIp1vF1JyAtC2s6vug6Vrx9pGp1vtozQFiewIAUGg=; b=k7N1cHjmXonB/ojY1eOeKwnIzHcjpUjBIaQXtBEjIw2ah9RgYZpRyCBquDYLJf7x3X qY7+k81P3nQYcXRTveBNBNDEfK+utj4KymrgU12+Ju1j3c08rOq/yDC4x26i3eU+sfOq 7lTkK4ee215J5CMgJ7NwudKa2Yu8278oT6Wx3f/Epc1QoqhL7UaJb/vPyYD9L5YxbvT+ QPlq7SgnHglBDu8H3QjmWYj+KOm+VdFDGCTfxdgrn5Z8/H5FJav1kWs5gBqLqDdiIjej xGS2n1eC31Qu4ym56g4DNfAO587m1qmWdMFcw+20CTYGx559Ohz5/ly2O3CnYj27GuZh lyPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1770114613; x=1770719413; 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=wFeIp1vF1JyAtC2s6vug6Vrx9pGp1vtozQFiewIAUGg=; b=IW+htC9iUnUiu476ZVj7G/GP5hrTvLcIdhNp+2Xg1uawuZLXou1ngw0jWz4mX0Tyw/ 31XpV0KwHk4Ou3adHXDjLWKVvdUUmJOyBxCYC3Tt7UTXsGe3BYMHh08YWna8vDT2aFmh LoP0Ky8/O2DVFgO8RggGvEo3qkDaMDuErNcFrn9VQ2ITbyBnWGuB1i8fim0Odq9pIArJ SDH36WFEfc77uI/m29nX+loM2afk8yhYYAJO5rUQTaXotgqJwkmMSYKWOqUn50g4LK56 YdZYvWLU1BSRQDDSB14DhuRJFAngzLmWb4xiIvHyi2zVPSRtTxGVRQwlf4wSeIIHjJRa 35Fw== X-Forwarded-Encrypted: i=1; AJvYcCVS7QdvJvwasNz27pOcVD705V++DmKw/Ww5D1yZzlkkqujGtFXiKXc0wfXNtuu8heYIxVOn0atooH0hSv4=@vger.kernel.org X-Gm-Message-State: AOJu0Yxw6LcWril9piQYZZk5uIoPC/ZAzJtNMwQL/OKYrtGDWW5k79Wv vHMlwDfboDsBxQM1sL4Pi37sRuFAC8KHbOicmZ0SM/7kb+aR+2yJX1Nl X-Gm-Gg: AZuq6aIdie61UPpOsS8qy96DUps6uQpBkZdxkBI/0yWBF+W6EiB0shos28oXehapYB6 DsQgC0SUc3PGDjU+Sqd5snYwjsmVcb+fO52AUtYSHzhJvCBim2gnuqG8zCLe7urV71pgQoUXx79 MclkSYYRvzXVGMeVejbsTkXCG94B9MGteFyQSQLRq3FMrGtQ/qdhAqC9fUrYUNeioU+xN+mxoEV 2K/+J6dLVlhUR3gwvAgYcGAOVI1mP+fKN7pCA4t0zHDY/frHH/LYTkLMPq7tGmd8y58VrwaabrY THO2vOi/zO2czMN0r/b3gMV56AxdbnXeTaQ7rnThw+b0wqQr0NL//8gZRMCkRT9pt9d/MniaihP Gufx5LgfstlBnQ+WrR49saRGFhkmGMA70e6aLz7lLuxAXvUs9zRsu6PCDBvKsCvWxTATYN4jOxb AErQsqaHddpZGqcSeVxMtrfqXxjZ1lMIoNXVdBgVaj6c+eSZOl/OY09wOIEKJ/AQWgA4eGrVtM X-Received: by 2002:a05:6000:1a8d:b0:435:db9b:5883 with SMTP id ffacd0b85a97d-435f3a820f0mr19870798f8f.2.1770114613062; Tue, 03 Feb 2026 02:30:13 -0800 (PST) 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 ffacd0b85a97d-435e10edf62sm55940729f8f.13.2026.02.03.02.30.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Feb 2026 02:30:12 -0800 (PST) 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 next 06/12] tools/nolibc/printf: Add support for left alignment and %[tzLq]d" Date: Tue, 3 Feb 2026 10:29:54 +0000 Message-Id: <20260203103000.20206-7-david.laight.linux@gmail.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20260203103000.20206-1-david.laight.linux@gmail.com> References: <20260203103000.20206-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: quoted-printable Content-Type: text/plain; charset="utf-8" From: David Laight Use a single 'flags' variable to hold both format flags and length modifier= s. Use (1u << (c & 31)) for the flag bits to reduce code complexity. Add support for left justifying fields. Add support for length modifiers 't' and 'z' (both long) and 'q' and 'L' (both long long). Unconditionall generate the signed values (for %d) to remove a second set of checks for the size. Use 'signed int' for the lengths to make the pad test simpler. Signed-off-by: David Laight --- tools/include/nolibc/stdio.h | 88 ++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/tools/include/nolibc/stdio.h b/tools/include/nolibc/stdio.h index 164d2384978e..1ce4d357a802 100644 --- a/tools/include/nolibc/stdio.h +++ b/tools/include/nolibc/stdio.h @@ -240,20 +240,20 @@ char *fgets(char *s, int size, FILE *stream) } =20 =20 -/* minimal printf(). It supports the following formats: - * - %[l*]{d,u,c,x,p} - * - %s - * - unknown modifiers are ignored. +/* simple printf(). It supports the following formats: + * - %[-][width][{l,t,z,ll,L,j,q}]{d,u,c,x,p,s,m} + * - %% + * - invalid formats are copied to the output buffer */ typedef int (*__nolibc_printf_cb)(void *state, const char *buf, size_t siz= e); =20 +#define __PF_FLAG(c) (1u << ((c) & 0x1f)) static __attribute__((unused, format(printf, 3, 0))) int __nolibc_printf(__nolibc_printf_cb cb, void *state, const char *fmt, v= a_list args) { - char lpref, c; - unsigned long long v; - unsigned int written, width; - size_t len; + char c; + int len, written, width; + unsigned int flags; char tmpbuf[21]; const char *outstr; =20 @@ -265,6 +265,7 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *state,= const char *fmt, va_list break; =20 width =3D 0; + flags =3D 0; if (c !=3D '%') { while (*fmt && *fmt !=3D '%') fmt++; @@ -274,6 +275,13 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *state= , const char *fmt, va_list =20 c =3D *fmt++; =20 + /* Flag characters */ + for (; c >=3D 0x20 && c <=3D 0x3f; c =3D *fmt++) { + if ((__PF_FLAG(c) & (__PF_FLAG('-'))) =3D=3D 0) + break; + flags |=3D __PF_FLAG(c); + } + /* width */ while (c >=3D '0' && c <=3D '9') { width *=3D 10; @@ -282,41 +290,34 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *stat= e, const char *fmt, va_list c =3D *fmt++; } =20 - /* Length modifiers */ - if (c =3D=3D 'l') { - lpref =3D 1; - c =3D *fmt++; - if (c =3D=3D 'l') { - lpref =3D 2; + /* Length modifiers are lower case except 'L' which is the same a 'q' */ + if ((c >=3D 'a' && c <=3D 'z') || (c =3D=3D 'L' && (c =3D 'q'))) { + if (__PF_FLAG(c) & (__PF_FLAG('l') | __PF_FLAG('t') | __PF_FLAG('z') | + __PF_FLAG('j') | __PF_FLAG('q'))) { + if (c =3D=3D 'l' && fmt[0] =3D=3D 'l') { + fmt++; + c =3D 'q'; + } + /* These all miss "# -0+" */ + flags |=3D __PF_FLAG(c); c =3D *fmt++; } - } else if (c =3D=3D 'j') { - /* intmax_t is long long */ - lpref =3D 2; - c =3D *fmt++; - } else { - lpref =3D 0; } =20 if (c =3D=3D 'c' || c =3D=3D 'd' || c =3D=3D 'u' || c =3D=3D 'x' || c = =3D=3D 'p') { + unsigned long long v; + long long signed_v; char *out =3D tmpbuf; =20 - if (c =3D=3D 'p') + if ((c =3D=3D 'p') || (flags & (__PF_FLAG('l') | __PF_FLAG('t') | __PF= _FLAG('z')))) { v =3D va_arg(args, unsigned long); - else if (lpref) { - if (lpref > 1) - v =3D va_arg(args, unsigned long long); - else - v =3D va_arg(args, unsigned long); - } else + signed_v =3D (long)v; + } else if (flags & (__PF_FLAG('j') | __PF_FLAG('q'))) { + v =3D va_arg(args, unsigned long long); + signed_v =3D v; + } else { v =3D va_arg(args, unsigned int); - - if (c =3D=3D 'd') { - /* sign-extend the value */ - if (lpref =3D=3D 0) - v =3D (long long)(int)v; - else if (lpref =3D=3D 1) - v =3D (long long)(long)v; + signed_v =3D (int)v; } =20 switch (c) { @@ -325,7 +326,7 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *state,= const char *fmt, va_list out[1] =3D 0; break; case 'd': - i64toa_r(v, out); + i64toa_r(signed_v, out); break; case 'u': u64toa_r(v, out); @@ -366,14 +367,24 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *stat= e, const char *fmt, va_list =20 written +=3D len; =20 - while (width > len) { - unsigned int pad_len =3D ((width - len - 1) & 15) + 1; + /* An OPTIMIZER_HIDE_VAR() seems to stop gcc back-merging = this + * code into one of the conditionals above. + */ + __asm__ volatile("" : "=3Dr"(len) : "0"(len)); + + /* Output 'left pad', 'value' then 'right pad'. */ + flags &=3D __PF_FLAG('-'); + width -=3D len; + if (flags && cb(state, outstr, len) !=3D 0) + return -1; + while (width > 0) { + int pad_len =3D ((width - 1) & 15) + 1; width -=3D pad_len; written +=3D pad_len; if (cb(state, " ", pad_len) !=3D 0) return -1; } - if (cb(state, outstr, len) !=3D 0) + if (!flags && cb(state, outstr, len) !=3D 0) return -1; } =20 @@ -382,6 +393,7 @@ int __nolibc_printf(__nolibc_printf_cb cb, void *state,= const char *fmt, va_list =20 return written; } +#undef _PF_FLAG =20 struct __nolibc_fprintf_cb_state { FILE *stream; --=20 2.39.5