From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1QDOB4-0007yL-R0 for mharc-grub-devel@gnu.org; Fri, 22 Apr 2011 17:46:14 -0400 Received: from eggs.gnu.org ([140.186.70.92]:55169) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QDOB2-0007xf-Ka for grub-devel@gnu.org; Fri, 22 Apr 2011 17:46:13 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QDOB1-0002VO-Ko for grub-devel@gnu.org; Fri, 22 Apr 2011 17:46:12 -0400 Received: from relay3-d.mail.gandi.net ([217.70.183.195]:42989) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QDOB1-0002VI-6G for grub-devel@gnu.org; Fri, 22 Apr 2011 17:46:11 -0400 X-Originating-IP: 217.70.178.134 Received: from mfilter4-d.gandi.net (mfilter4-d.gandi.net [217.70.178.134]) by relay3-d.mail.gandi.net (Postfix) with ESMTP id DEEA3A807A; Fri, 22 Apr 2011 23:46:08 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at undef12-d.mgt.gandi.net Received: from relay3-d.mail.gandi.net ([217.70.183.195]) by mfilter4-d.gandi.net (mfilter4-d.gandi.net [10.0.15.180]) (amavisd-new, port 10024) with ESMTP id pIYfQWU9l9rr; Fri, 22 Apr 2011 23:46:07 +0200 (CEST) X-Originating-IP: 50.43.15.19 Received: from feather (static-50-43-15-19.bvtn.or.frontiernet.net [50.43.15.19]) (Authenticated sender: josh@joshtriplett.org) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 9CAFAA8077; Fri, 22 Apr 2011 23:46:04 +0200 (CEST) Date: Fri, 22 Apr 2011 14:46:02 -0700 From: Josh Triplett To: grub-devel@gnu.org Subject: [PATCH] Support * as field width or precision in printf Message-ID: <20110422214602.GA22144@feather> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="mP3DRpeJDSE+ciuQ" Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 3) X-Received-From: 217.70.183.195 Cc: burt@pbjtriplett.org X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 22 Apr 2011 21:46:13 -0000 --mP3DRpeJDSE+ciuQ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline The attached patch implements support for * as the field width or precision in printf, which obtains that field width or precision from the next va_arg. This proves particularly useful as a modifier on %s: %.*s allows printing a non-NUL-terminated string with a known length. Tested with the following test cases, all of which worked: grub_printf("|%*s|\n", -50, "left-aligned in 50"); grub_printf("|%*s|\n", 50, "right-aligned in 50"); grub_printf("|%.*s|\n", 5, "truncated"); grub_printf("|%.*s|\n", -5, "truncated"); grub_printf("|%*.*s|\n", 20, 5, "truncated"); grub_printf("|%*.*s|\n", -20, 5, "truncated"); grub_printf("|%50s|\n", "hardcoded 50"); grub_printf("|%-50s|\n", "hardcoded -50"); grub_printf("|%.5s|\n", "truncated"); ChangeLog entry: 2011-04-21 Josh Triplett 2011-04-21 Burt Triplett * grub-core/kern/misc.c (grub_vsnprintf_real): Add support for '*' as field width or precision. In bug 33144, phcoder requested justification for the inclusion of this feature in grub's printf. We added this feature to support our port of ACPICA that runs as a GRUB module. ACPICA depends on having that particular feature in printf; it uses %*s extensively. Now that we've added this feature, we can also use it to simplify many other pieces of code we've written. Also, I just checked, and this patch adds a grand total of 8 bytes to kernel.img. If it helps, I've also attached a second patch to current GRUB, which tweaks the printf implementation to save 72 bytes by factoring out common code paths. Given that, could we please have 8 of those bytes? :) - Josh Triplett --mP3DRpeJDSE+ciuQ Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="grub-printf-star.patch" === modified file 'grub-core/kern/misc.c' --- grub-core/kern/misc.c 2011-04-18 21:03:52 +0000 +++ grub-core/kern/misc.c 2011-04-22 07:13:52 +0000 @@ -726,45 +726,70 @@ int longlongfmt = 0; int unsig = 0; - if (*fmt && *fmt =='-') - { - rightfill = 1; - fmt++; - } - - p = (char *) fmt; - /* Read formatting parameters. */ - while (*p && grub_isdigit (*p)) - p++; - - if (p > fmt) - { - char s[p - fmt + 1]; - grub_strncpy (s, fmt, p - fmt); - s[p - fmt] = 0; - if (s[0] == '0') - zerofill = '0'; - format1 = grub_strtoul (s, 0, 10); - fmt = p; - } - - if (*p && *p == '.') - { - p++; - fmt++; + if (*fmt && *fmt == '*') + { + fmt++; + n = va_arg (args, int); + if (n < 0) + { + rightfill = 1; + n = -n; + } + format1 = n; + } + else + { + if (*fmt && *fmt =='-') + { + rightfill = 1; + fmt++; + } + + p = (char *) fmt; + /* Read formatting parameters. */ while (*p && grub_isdigit (*p)) p++; if (p > fmt) { - char fstr[p - fmt + 1]; - grub_strncpy (fstr, fmt, p - fmt); - fstr[p - fmt] = 0; - format2 = grub_strtoul (fstr, 0, 10); + char s[p - fmt + 1]; + grub_strncpy (s, fmt, p - fmt); + s[p - fmt] = 0; + if (s[0] == '0') + zerofill = '0'; + format1 = grub_strtoul (s, 0, 10); fmt = p; } } + if (*fmt && *fmt == '.') + { + fmt++; + if (*fmt && *fmt == '*') + { + fmt++; + n = va_arg (args, int); + if (n < 0) + n = 0; + format2 = n; + } + else + { + p = (char *) fmt; + while (*p && grub_isdigit (*p)) + p++; + + if (p > fmt) + { + char fstr[p - fmt + 1]; + grub_strncpy (fstr, fmt, p - fmt); + fstr[p - fmt] = 0; + format2 = grub_strtoul (fstr, 0, 10); + fmt = p; + } + } + } + c = *fmt++; if (c == 'l') { --mP3DRpeJDSE+ciuQ Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="grub-microoptimize-printf-to-save-72-bytes.patch" === modified file 'grub-core/kern/misc.c' --- grub-core/kern/misc.c 2011-04-18 21:03:52 +0000 +++ grub-core/kern/misc.c 2011-04-22 21:38:31 +0000 @@ -750,10 +750,10 @@ if (*p && *p == '.') { - p++; fmt++; - while (*p && grub_isdigit (*p)) + do p++; + while (*p && grub_isdigit (*p)); if (p > fmt) { @@ -789,39 +789,26 @@ unsig = 1; /* Fall through. */ case 'd': - if (longlongfmt) - { - long long ll; - + { + unsigned long long ll; + if (longlongfmt) ll = va_arg (args, long long); - grub_lltoa (tmp, c, ll); - } - else if (longfmt && unsig) - { - unsigned long l = va_arg (args, unsigned long); - grub_lltoa (tmp, c, l); - } - else if (longfmt) - { - long l = va_arg (args, long); - grub_lltoa (tmp, c, l); - } - else if (unsig) - { - unsigned u = va_arg (args, unsigned); - grub_lltoa (tmp, c, u); - } - else - { - n = va_arg (args, int); - grub_lltoa (tmp, c, n); - } - if (! rightfill && grub_strlen (tmp) < format1) - write_fill (zerofill, format1 - grub_strlen (tmp)); - write_str (tmp); - if (rightfill && grub_strlen (tmp) < format1) - write_fill (zerofill, format1 - grub_strlen (tmp)); - break; + else if (longfmt && unsig) + ll = va_arg (args, unsigned long); + else if (longfmt) + ll = va_arg (args, long); + else if (unsig) + ll = va_arg (args, unsigned); + else + ll = va_arg (args, int); + grub_lltoa (tmp, c, ll); + if (! rightfill && grub_strlen (tmp) < format1) + write_fill (zerofill, format1 - grub_strlen (tmp)); + write_str (tmp); + if (rightfill && grub_strlen (tmp) < format1) + write_fill (zerofill, format1 - grub_strlen (tmp)); + break; + } case 'c': n = va_arg (args, int); --mP3DRpeJDSE+ciuQ--