-
Notifications
You must be signed in to change notification settings - Fork 3k
minimal-printf: Fix handling of the two character sequence %% #11729
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
minimal-printf: Fix handling of the two character sequence %% #11729
Conversation
@hugueskamba, thank you for your changes. |
7297f37
to
8e89d99
Compare
@@ -625,6 +625,9 @@ int mbed_minimal_formatted_string(char *buffer, size_t length, const char *forma | |||
index = next_index; | |||
|
|||
mbed_minimal_formatted_string_void_pointer(buffer, length, &result, value, stream); | |||
} else if (next == '%') { | |||
index = next_index; | |||
mbed_minimal_formatted_string_signed(buffer, length, &result, next, stream); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
signed
? Isn't this printing "25"? Surely that should read
mbed_minimal_formatted_string_character(buffer, length, &result, '%', stream);
Although, just to save space, I wonder if you could cheat and handle this in the overall else
:
} else {
/* Handle `%%` - skip the first `%`, so we print just `%` via the "unrecognized modifier" code */
if (next == `%`) {
index++;
}
/* Write all characters between format beginning and unrecognized modifier */
I believe that handles what the standard requires - the conversion specifier %
, with the entire conversion specification being %%
. Behaviour of "%.5%` is undefined.
Although on the other hand that else loop is clunky by the way. Maybe, instead, the much simpler:
} else {
// Unrecognised, or `%%`. Print the `%` that led us in.
mbed_minimal_formatted_string_character(buffer, length, &result, '%', stream);
if (next == '%') {
// Continue printing loop after `%%`
index = next_index;
}
// Otherwise we continue the printing loop after the leading `%`, so an
// unrecognised thing like "Blah = %a" will just come out as "Blah = %a".
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although, just to save space, I wonder if you could cheat and handle this in the overall
Your proposed change increases flash memory usage by 8 bytes.
This force-push uses mbed_minimal_formatted_string_character
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first suggestion, I guess? What about the second - that should be a big reduction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although on the other hand that else loop is clunky by the way. Maybe, instead, the much simpler:
This force-push applies this suggested change for a 44 bytes flash memory saving.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. I have one more suggestion that may make it even tighter. Adjust the entire loop to get rid of the else
on if (format[index] == '%')
. Make each normal recognised case continue
instead, then %
and unrecognised can fall into the standard character print by not continue
ing.
for (size_t index = 0; format[index] != '\0'; index++) {
if (format[index] == '%') {
//...
char next = format[next_index];
if ((next == 'd') || (next == 'i')) {
//...
index = next_index;
continue;
} else if ((next == 'u') || (next == 'x') || (next == 'X')) {
//... Note that putting `index = next_index` last in every case
// should promote code sharing between each block
index = next_index;
continue;
} else if (next == '%') {
index = next_index;
}
}
mbed_minimal_formatted_string_character(buffer, length, &result, format[index], stream);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's an optimisation worth trying but I'd rather that we do it in a different PR as we are getting behind on other tasks.
ad4eca6
to
1ebd043
Compare
1ebd043
to
a29776a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add test coverage in greentea minimal-printf test suite.
The two character sequence %% is used in standard implementations of printf to print a single %. This is because % is essentially printf's escape character for format specifiers and as \% cannot work printf uses %%. Therefore to be compatible with string buffers containing %%, minimal-printf also needs to only print a single %.
a29776a
to
ceffb6d
Compare
Test run: FAILEDSummary: 1 of 11 test jobs failed Failed test jobs:
|
Internal CI fault ,restarted exporters |
Description
The two character sequence
%%
is used in standard implementations ofprintf
to print a single %. This is because%
is essentiallyprintf
'sescape character for format specifiers and as
\%
cannot workprintf
uses
%%
.Therefore to be compatible with string buffers containing
%%
, minimal-printf also needs to only print a single%
.To reproduce the bug.
mbed-os-example-blinky
and program your target with the following commandWith the fix the output is similar to:
Pull request type
Reviewers
@evedon @kjbracey-arm
Release Notes