summaryrefslogtreecommitdiff
path: root/coreutils/ls.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2025-08-01 01:02:43 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2025-08-01 01:02:43 +0200
commit4f3a56dc12a2126bdacff73f1cfe586d06e800c0 (patch)
tree863d23f2fc3d2bf6b77213ef729a6ebda7101244 /coreutils/ls.c
parentbb18473216253b8602ce081dd944f854aad9e572 (diff)
ls: fix -Q to match GNU
function old new delta print_name 137 229 +92 display_files 375 402 +27 c_escape_conv_str00 - 24 +24 display 1476 1485 +9 conv_str 33 - -33 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 3/0 up/down: 152/-33) Total: 119 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils/ls.c')
-rw-r--r--coreutils/ls.c50
1 files changed, 38 insertions, 12 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c
index c725be92d..9e4b83032 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -457,19 +457,29 @@ static unsigned calc_name_len(const char *name)
if (!(option_mask32 & (OPT_q|OPT_Q)))
return strlen(name);
- name = printable_string2(&uni_stat, name);
-
if (!(option_mask32 & OPT_Q)) {
+ printable_string2(&uni_stat, name);
return uni_stat.unicode_width;
}
- // TODO: quote chars 7..13 as \a,b,t,n,v,f,r
- // other chars <32 or >127 as \ooo octal
- len = 2 + uni_stat.unicode_width;
+ len = 2 + strlen(name);
while (*name) {
+ unsigned char ch = (unsigned char)*name;
+ if (ch < ' ' || ch > 0x7e) {
+ ch -= 7;
+ if ((signed char)ch >= 0 && ch <= 6) {
+ // quote chars 7..13 as \a,b,t,n,v,f,r
+ len++;
+ goto next;
+ }
+ // other chars <32 or >126 as \ooo octal
+ len += 3;
+ goto next;
+ }
if (*name == '"' || *name == '\\') {
len++;
}
+ next:
name++;
}
return len;
@@ -492,23 +502,39 @@ static unsigned print_name(const char *name)
return strlen(name);
}
- name = printable_string2(&uni_stat, name);
-
if (!(option_mask32 & OPT_Q)) {
+ name = printable_string2(&uni_stat, name);
fputs_stdout(name);
return uni_stat.unicode_width;
}
- // TODO: quote chars 7..13 as \a,b,t,n,v,f,r
- // other chars <32 or >127 as \ooo octal
- len = 2 + uni_stat.unicode_width;
+ len = 2 + strlen(name);
putchar('"');
while (*name) {
- if (*name == '"' || *name == '\\') {
+ unsigned char ch = (unsigned char)*name;
+ if (ch < ' ' || ch > 0x7e) {
+ putchar('\\');
+ ch -= 7;
+ if ((signed char)ch >= 0 && ch <= 6) {
+ // quote chars 7..13 as \a,b,t,n,v,f,r
+ ch = c_escape_conv_str07[1 + 3 * ch];
+ len++;
+ goto put_ch;
+ }
+ // other chars <32 or >126 as \ooo octal
+ ch = (unsigned char)*name;
+ putchar('0' + ((ch>>6) & 7));
+ putchar('0' + ((ch>>3) & 7));
+ ch = '0' + (ch & 7);
+ len += 3;
+ goto put_ch;
+ }
+ if (ch == '"' || ch == '\\') {
putchar('\\');
len++;
}
- putchar(*name);
+ put_ch:
+ putchar(ch);
name++;
}
putchar('"');