Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Printing whitespace characters with {c} #4014

Closed
lukechampine opened this issue Dec 31, 2019 · 7 comments · Fixed by #4192
Closed

Printing whitespace characters with {c} #4014

lukechampine opened this issue Dec 31, 2019 · 7 comments · Fixed by #4192
Labels
standard library This issue involves writing Zig code for the standard library.
Milestone

Comments

@lukechampine
Copy link
Contributor

lukechampine commented Dec 31, 2019

21bc335 changed the behavior of the {c} formatting directive:

-    return output(context, @as(*const [1]u8, &c)[0..]);
+    if (std.ascii.isPrint(c))
+        return output(context, @as(*const [1]u8, &c)[0..]);
+    return format(context, Errors, output, "\\x{x:0<2}", .{c});

The effect of this is:

fn printChars(s: []const u8) void {
    for (s) |c| {
        std.debug.warn("{c}", .{c});
    }
}
// old behavior:
// printChars("foo\tbar") -> foo    bar

// new behavior:
// printChars("foo\tbar") -> foo\x09bar

This is because std.ascii.isPrint returns false on whitespace other than 0x20 ( ).

This behavior does not match the behavior of the %c directive in C, Go, and other languages. Is this departure intentional? If so, what's the proper way to print a string character-by-character?

@andrewrk andrewrk added bug Observed behavior contradicts documented or intended behavior standard library This issue involves writing Zig code for the standard library. labels Dec 31, 2019
@andrewrk andrewrk added this to the 0.6.0 milestone Dec 31, 2019
@andrewrk andrewrk removed the bug Observed behavior contradicts documented or intended behavior label Dec 31, 2019
@andrewrk
Copy link
Member

I labeled it as a bug, but then I checked the behavior of libc isprint and it agrees with std.ascii.isPrint, that \t is not printable. So I'm not yet sure how to resolve this.

@andrewrk
Copy link
Member

cc @Vexu, curious about your thoughts on this.

@Vexu
Copy link
Member

Vexu commented Dec 31, 2019

I think all whitespace with escape sequences (\t \n, \r) should be printed unescaped. I would've included them in the original change had I realized ascii doesn't consider them printable.

@andrewrk
Copy link
Member

Hmm, how about this proposal:

Change \t, \n, \r to return true for std.ascii.isPrint. This would disagree with what these functions return in libc's isprint. But doesn't that seem like a bug, that they return false? https://en.cppreference.com/w/c/string/byte/isprint

@thejoshwolfe
Copy link
Contributor

I can't find any specification on what the %c format is supposed to do in C or Go. All they say is "the character" or something similarly vague. To me, this means passing through the character without any escaping. There's no mention of "printable" in the %c specification, unless I'm not looking at the right document. Can someone point me to any specification for the behavior of %c more detailed than http://www.cplusplus.com/reference/cstdio/printf/ or https://golang.org/pkg/fmt/ ?

@hryx
Copy link
Contributor

hryx commented Jan 3, 2020

@thejoshwolfe From rummaging around the Go source and package documentation, %c means print everything unescaped, up to the maximum supported codepoint.

@TheZeus121
Copy link

%c in C outputs the "raw byte" with no checks on whether it's printable or not (which is why you can do terminal escapes with printf).

\t, \n, and \r are considered control characters instead of printable characters because instead of being one character, they do "magic" stuff with terminals usually--\t advances to the next tab stop, \n moves to the next line, \r moves to the beginning of the line.

I'd suggest adding some "raw string" and "raw character" formatting directives or remove the escaping behaviour altogether.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants