-
Notifications
You must be signed in to change notification settings - Fork 49
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
Misra compliance #79
Misra compliance #79
Conversation
…reprocessor directives or comments
This reverts commit e0aff68.
…ther a preceding &, or with a parenthesized parameter list, which may be empty.
… be used in place of the basic types
@@ -86,7 +102,7 @@ void putchar_(char character); | |||
* @param format A string that specifies the format of the output | |||
* @return The number of characters that are written into the array, not counting the terminating null character | |||
*/ | |||
int printf_(const char* format, ...) ATTR_PRINTF(1, 2); | |||
printf_int_t printf_(const char* format, ...) ATTR_PRINTF(1, 2); |
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.
This is not possible. The printf() functions must be compatible with the standard library. If the MISRA standard is incompatible with using the standard library, then we have a problem.
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.
This is not necessarily incompatible with the std lib. If you're not defining PRINTF_CUSTOM_INT_xx then printf_int_t
is a plain int. For MISRA compatibility you'd define PRINTF_CUSTOM_INT_32 to make printf_int_t
an int32_t
.
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.
Ah, ok. I guess we can do something like that. But - I still have to see the literal int in the signature. So I would rather have something like:
#ifndef PRINTF_CUSTOM_INT_xx
int printf_(const char* format, ...) ATTR_PRINTF(1, 2);
#else
printf_int_t printf_(const char* format, ...) ATTR_PRINTF(1, 2);
#endif
or maybe even:
#ifndef PRINTF_CUSTOM_INT_xx
int def1
int def2
int def3
#else
printf_int_t def1
printf_int_t def2
printf_int_t def3
#endif
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.
I've update the header file. Is this better?
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.
You'll need a new PR with whatever changes remain after my next push.
Also... what does MISRA have to say about the standard library version of these functions? I mean, they return a plain int, after all.
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.
Actually, I've just read the MISRA rule regarding typedefs. It says:
6.3 (adv) typedefs that indicate size and signedness should be used in place of the basic numerical types.
So, first of all, it's a "should", not a "shall" or "will". But even more importantly - the changes you propose don't bring you much closer to satisfying this rule, since the typedef you proposed indicates neither size nor signedness. I believe this advisory is about preferring int32_t
, uint8_t
and such over int
, unsigned
, char
and such.
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.
Ah ok. I'll see about that new pull request.
Basically MISRA indicates (among others) to avoid the standard library methods regarding time/date, character handling, stream operators and allocation/deallocation. It more or less recognizes one cannot do without, but discourages dependence.
More to the point, it says "For example, the essential type rules apply to the types of the arguments passed to functions specified in the standard library and to their results."
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.
Actually, I've just read the MISRA rule regarding typedefs. It says:
6.3 (adv) typedefs that indicate size and signedness should be used in place of the basic numerical types.
So, first of all, it's a "should", not a "shall" or "will". But even more importantly - the changes you propose don't bring you much closer to satisfying this rule, since the typedef you proposed indicates neither size nor signedness. I believe this advisory is about preferring
int32_t
,uint8_t
and such overint
,unsigned
,char
and such.
I completely agree that is what the rule is about.
That's what I'm doing by defining printf_int_t
as int16_t
, int32_t
or int64_t
. This way the return value uses a type with defined signedness and size.
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.
Basically MISRA indicates (among others) to avoid the standard library methods regarding time/date, character handling, stream operators and allocation/deallocation. It more or less recognizes one cannot do without, but discourages dependence.
Well, this library is about providing these same problematic functions. But - we'll see how it looks in the new PR. Closing this one for now.
src/printf/printf.c
Outdated
@@ -261,11 +260,11 @@ static inline void out_wrapped_function(char character, void* wrapped_function, | |||
|
|||
// internal secure strlen | |||
// @return The length of the string (excluding the terminating 0) limited by 'maxsize' | |||
static inline unsigned int strnlen_s_(const char* str, size_t maxsize) | |||
static inline printf_uint_t strnlen_s_(const char* str, size_t maxsize) |
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.
Maybe I could just make it size_t?
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.
Good suggestion, done in an additional commit.
} | ||
return i; | ||
} | ||
|
||
|
||
// output the specified string in reverse, taking care of any zero-padding | ||
static size_t out_rev_(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags) | ||
static size_t out_rev_(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, printf_uint_t width, printf_uint_t flags) |
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.
I suppose I could have a distinct type for the flag holder integer.
src/printf/printf.c
Outdated
@@ -1055,8 +1056,9 @@ static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const | |||
} | |||
} | |||
// string output | |||
while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) { | |||
while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision)) { |
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.
Is this exactly equivalent?
What if there are no precision flags? In that case, with the new code, precision gets decremented while before it wasn't.
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 is true, but precision
is only used to exit the while loop, so this does not impact any functionality.
MISRA C:2004, 6.3 - typedefs that indicate size and signedness should be used in place of the basic types Mostly ok, but not when it comes to standard library compliance of the user-visible functions. See individual comments. Also, I might want to have more than one unsigned-int replacement, depending on the context. MISRA C:2004, 19.10 Ok. MISRA C++:2008, 18-0-1 - The C library shall not be used. Can you explain the impact of this change? I think I'm ok with it, but I'm not sure I understand exactly what would happen. MISRA C:2004, 16.9 - A function identifier shall only be used with either a preceding &, or with a parenthesized parameter list, which may be empty. Ok. Unmodified pointers should be const (MISRA C:2004, 16.7 )
MISRA C:2012, 20.1 - #include directives should only be preceded by preprocessor directives or comments Ok. Removed redundant cast Ok. Merge collapsible if statements (not strictly MISRA) Don't have a strong opinion here; I probably separated for readability and consistency with other pieces of code earlier or below. Can you explain why you believe this is useful/important? Rule 13.3 increment/decrement with other side effects Generally ok, but see specific comment |
Oh, one last thing - your PR should be against the develop branch :-P |
Thanks for you comments, please find my responses below.
Sure, can you indicate which contexts you would like?
For this change, only when using C++, we're including the c++ version of the stdlib headers (so for example cstdarg instead of stdarg.h). The impact is compiler dependent, but most C++ compilers simply wrap the C versions so this should be negligible.
Correct, I came to same conclusion and reverted the commit.
Mostly readability. Subsequent if statements imply more complexity than is actually present.
I've changed the target to develop (still getting used to the github UI :) ). |
So, I'm going to go ahead and cherry-pick some of this PR. The rest will need a bit of updating for other changes. |
I'm little confused here. Couldn't MISRA compliance be met by using stdint.h types instead of a hack like printf_int_t? |
@JakeSays : Not unless I decided to force people to use non-native integer types (e.g. by choosing int32_t always,. or int64_t always). |
@eyalroz I'm not sure I follow. isn't stdint.h a standard? Personally I'd rather be forced to use int32_t instead of printf_int_t. |
|
My concern is this: One of the major attractions of libprintf is it's simplicity. The code is simple and easy to understand, and the header is a dream to read. It seems like many of these PR's are taking it in a different direction and it'll end up in #ifdef/#define hell. |
In this PR it is, but I don't think I would let it into the header. The fctprintf variants will return an I still haven't seen an alternative PR. What I have done and committed to the code is drastically reduce the use of non-typedef'ed types in |
* Fixes eyalroz#79. * Fixed a few more (GCC) warnings. * Separated the warning-triggering cases into test cases of their own. * Not using `signed size_t` - that's apparently not in the standard and not widely supported. * Added a CMake option for whether or not to test the warning-triggering cases.
Please find my MISRA modifications in this pull request.
I've tried to stick to the MISRA issues and not change other things ;)
I'm open for discussion and/or feedback!