Implement STRFMT and more printf-like format specifiers for string interpolation (#646)

Fixes #570
Fixes #178

Use errors for inapplicable format spec flags instead of -Wstring-format
This commit is contained in:
Rangi
2020-12-29 16:53:15 -05:00
committed by GitHub
parent aa27e714d4
commit c0ce1da4c3
16 changed files with 675 additions and 84 deletions

View File

@@ -268,18 +268,72 @@ PRINTT "The answer to {TOPIC} is {ANSWER}\[rs]n"
.Pp
Symbol interpolations can be nested, too!
.Pp
It's possible to change the way numeric symbols are converted by specifying a print type like so:
.Ql {d:symbol} .
It's possible to change the way symbols are converted by specifying a print format like so:
.Ql {fmt:symbol} .
The
.Ql fmt
specifier consists of parts
.Ql <sign><prefix><align><pad><width><frac><type> .
These parts are:
.Bl -column "<prefix>"
.It Sy Part Ta Sy Meaning
.It Ql <sign> Ta May be
.Ql +
or
.Ql \ .
If specified, prints this character in front of non-negative numbers.
.It Ql <prefix> Ta May be
.Ql # .
If specified, prints the appropriate prefix for numbers,
.Ql $ ,
.Ql & ,
or
.Ql % .
.It Ql <align> Ta May be
.Ql - .
If specified, aligns left instead of right.
.It Ql <pad> Ta May be
.Ql 0 .
If specified, pads right-aligned numbers with zeros instead of spaces.
.It Ql <width> Ta May be one or more
.Ql 0
\[en]
.Ql 9 .
If specified, pads the value to this width, right-aligned with spaces by default.
.It Ql <frac> Ta May be
.Ql \&.
followed by one or more
.Ql 0
\[en]
.Ql 9 .
If specified, prints this many digits of a fixed-point fraction.
.It Ql <type> Ta Specifies the type of value.
.El
.Pp
All the format specifier parts are optional except the
.Ql <type> .
Valid print types are:
.Bl -column -offset indent "Print type" "Lowercase hexadecimal" "Example"
.It Sy Print type Ta Sy Format Ta Sy Example
.It Ql d Ta Decimal Ta 42
.It Ql d Ta Signed decimal Ta -42
.It Ql u Ta Unsigned decimal Ta 42
.It Ql x Ta Lowercase hexadecimal Ta 2a
.It Ql X Ta Uppercase hexadecimal Ta 2A
.It Ql b Ta Binary Ta 101010
.It Ql o Ta Octal Ta 52
.It Ql f Ta Fixed-point Ta 1234.56789
.It Ql s Ta String Ta \&"example\&"
.El
.Pp
Note that print types should only be used with numeric values, not strings.
Examples:
.Bd -literal -offset indent
; Prints "%0010 + $3 == 5"
PRINTT STRFMT("%#05b + %#x == %d\n", 2, 3, 2+3)
; Prints "32% of 20 = 6.40"
PRINTT STRFMT("%d%% of %d = %.2f\n", 32, 20, MUL(20.0, 0.32))
; Prints "Hello world!"
PRINTT STRFMT("Hello %s!\n", STRLWR("WORLD"))
.Ed
.Pp
HINT: The
.Ic {symbol}
@@ -304,7 +358,7 @@ The following functions operate on string expressions.
Most of them return a string, however some of these functions actually return an integer and can be used as part of an integer expression!
.Bl -column "STRSUB(str, pos, len)"
.It Sy Name Ta Sy Operation
.It Fn STRLEN string Ta Returns the number of characters in Ar string .
.It Fn STRLEN str Ta Returns the number of characters in Ar str .
.It Fn STRCAT str1 str2 Ta Appends Ar str2 No to Ar str1 .
.It Fn STRCMP str1 str2 Ta Returns -1 if Ar str1 No is alphabetically lower than Ar str2 No , zero if they match, 1 if Ar str1 No is greater than Ar str2 .
.It Fn STRIN str1 str2 Ta Returns the first position of Ar str2 No in Ar str1 No or zero if it's not present Pq first character is position 1 .
@@ -312,6 +366,13 @@ Most of them return a string, however some of these functions actually return an
.It Fn STRSUB str pos len Ta Returns a substring from Ar str No starting at Ar pos Po first character is position 1 Pc and Ar len No characters long.
.It Fn STRUPR str Ta Converts all characters in Ar str No to capitals and returns the new string.
.It Fn STRLWR str Ta Converts all characters in Ar str No to lower case and returns the new string.
.It Fn STRFMT fmt args... Ta Returns the string Ar fmt No with each
.Ql %spec
pattern replaced by interpolating the format
.Ar spec
with its corresponding argument in
.Ar args
.Pq So %% Sc is replaced by the So % Sc character .
.El
.Ss Character maps
When writing text that is meant to be displayed in the Game Boy, the characters used in the source code may have a different encoding than the default of ASCII.