diff options
author | jilles <jilles@FreeBSD.org> | 2011-05-28 11:37:47 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2011-05-28 11:37:47 +0000 |
commit | 979af05e7725d814570e4633b10a5d49e67e987c (patch) | |
tree | 97044025b3bbee11165340fbea5bcf368dd81b10 /usr.bin/printf | |
parent | 36cd7cef5ee843f5238463d58cf2180183b674cd (diff) | |
download | FreeBSD-src-979af05e7725d814570e4633b10a5d49e67e987c.zip FreeBSD-src-979af05e7725d814570e4633b10a5d49e67e987c.tar.gz |
printf: Allow multibyte characters for '<char> form, avoid negative codes.
Examples:
LC_ALL=en_US.UTF-8 printf '%d\n' $(printf \'\\303\\244)
LC_ALL=en_US.ISO8859-1 printf '%d\n' $(printf \'\\344)
Both of these should print 228.
Like some other shells, incomplete or invalid multibyte characters yield the
value of the first byte without a warning.
Note that there is no general way to go back from the character code to the
character.
Diffstat (limited to 'usr.bin/printf')
-rw-r--r-- | usr.bin/printf/printf.1 | 5 | ||||
-rw-r--r-- | usr.bin/printf/printf.c | 22 |
2 files changed, 20 insertions, 7 deletions
diff --git a/usr.bin/printf/printf.1 b/usr.bin/printf/printf.1 index 56c6855..2afb9d3 100644 --- a/usr.bin/printf/printf.1 +++ b/usr.bin/printf/printf.1 @@ -31,7 +31,7 @@ .\" @(#)printf.1 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd April 25, 2011 +.Dd May 28, 2011 .Dt PRINTF 1 .Os .Sh NAME @@ -68,8 +68,7 @@ otherwise it is evaluated as a C constant, with the following extensions: A leading plus or minus sign is allowed. .It If the leading character is a single or double quote, the value is the -.Tn ASCII -code of the next character. +character code of the next character. .El .Pp The format string is reused as often as necessary to satisfy the diff --git a/usr.bin/printf/printf.c b/usr.bin/printf/printf.c index 56c1caf..eace370 100644 --- a/usr.bin/printf/printf.c +++ b/usr.bin/printf/printf.c @@ -58,6 +58,7 @@ static const char rcsid[] = #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <wchar.h> #ifdef SHELL #define main printfcmd @@ -537,10 +538,23 @@ static int asciicode(void) { int ch; - - ch = **gargv; - if (ch == '\'' || ch == '"') - ch = (*gargv)[1]; + wchar_t wch; + mbstate_t mbs; + + ch = (unsigned char)**gargv; + if (ch == '\'' || ch == '"') { + memset(&mbs, 0, sizeof(mbs)); + switch (mbrtowc(&wch, *gargv + 1, MB_LEN_MAX, &mbs)) { + case (size_t)-2: + case (size_t)-1: + wch = (unsigned char)gargv[0][1]; + break; + case 0: + wch = 0; + break; + } + ch = wch; + } ++gargv; return (ch); } |