From 3119b6b228d5c65e81dbcee2bc04db05be1951fe Mon Sep 17 00:00:00 2001 From: Florian Fleissner Date: Sat, 23 Dec 2017 13:30:27 +0100 Subject: [PATCH 1/5] Added src/macro_helpers.h that supports application of preprocessor-macros --- src/macro_helpers.h | 103 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 src/macro_helpers.h diff --git a/src/macro_helpers.h b/src/macro_helpers.h new file mode 100644 index 00000000..8d90abe2 --- /dev/null +++ b/src/macro_helpers.h @@ -0,0 +1,103 @@ +#pragma once + +// Code generated by muli-line pre-processor macros is hard to read after +// pre-processing. +// +// When you want to check pre-processed code, e.g. for debugging or +// to understand what's going on, do the following: +// +// 1) Add the compiler command line definition +// -DKALEIDOSCOPE_ENABLE_MACRO_NEWLINE_SUBSTITUTION +// This prevents the __NL__ macro being defined below. +// 2) Generate the preprocessed code (it will contain a lot of __NL__ definitions). +// 3) Open the pre-processed code in your favorite editor. +// 3.1) Replace all __NL__ with newline characters. +// In vim the command would be ':%s/__NL__/\r/g'. +// 3.2) Autocorrect code-indenting to improve readability. This is necessary +// as pre-processor macros remove all whitespaces at the beginning of lines. +// With vim, the command gg=G helps (just type the characters one after +// the other). +// 4) Don't forget to remove the +// -DKALEIDOSCOPE_ENABLE_MACRO_NEWLINE_SUBSTITUTION +// from your compiler command line. Else the code won't compile. + +#ifndef KALEIDOSCOPE_ENABLE_MACRO_NEWLINE_SUBSTITUTION +#define __NL__ +#endif + +#define __NN__ + +// Allow for the creation of verbose messages in static_asserts +// +#define VEROSE_STATIC_ASSERT_HEADER \ +__NL__ "\n***************************************************************" \ +__NL__ "\n******************** READ THIS CAREFULLY! *********************" \ +__NL__ "\n***************************************************************" \ +__NL__ "\n" + +#define VERBOSE_STATIC_ASSERT_FOOTER \ +__NL__ "\n" \ +__NL__ "\n***************************************************************" \ +__NL__ "\n***************************************************************" \ +__NL__ "\n***************************************************************" + +// The macro function RESTRICT_ARGS_COUNT can be used to generate more +// verbose error messages when users supply an insuitable number of arguments +// to a macro. +// +// For a macro it is used wherever one of the arguments A, B, C might +// be used, e.g. +// +#if 0 // This is just so that A_MACRO is not actually defined + #define A_MACRO(A, B, C, ...) \ + (void)RESTRICT_ARGS_COUNT(0, 3, A_MACRO, ##__VA_ARGS__); \ + int a = A; \ + int b = B; \ + int c = C; +#endif +// +// Note that RESTRICT_ARGS_COUNT can also be invoked wherever one of the macro +// arguments is used, e.g. +// +#if 0 // This is just so that B_MACRO is not actually defined + #define B_MACRO(A, B, C, ...) + int array[] = { A, B, RESTRICT_ARGS_COUNT(C, 3, B_MACRO, ##__VA_ARGS__) }; +#endif +// +#define RESTRICT_ARGS_COUNT(B, \ + NUM_EXPECTED_ARGS, \ + ORIGINAL_MACRO, \ + ...) \ +__NN__ ( \ +__NL__ []{ /* Here we are in the body of a dummy lambda function. \ +__NN__ []{} is, BTW, the shortest way to write a lambda. \ +__NN__ It is only used to hold the static_assert that cannot be \ +__NN__ defined directly in the keymap initializer list. By using the \ +__NN__ comma operator ((A, B) always evaluates to b), we ensure \ +__NN__ that not the lambda but B is what ASSERT_ARGS_COUNT \ +__NN__ finally evaluates to. \ +__NN__ Please not that passing B through this macro is a must \ +__NN__ as we need it for the comma operator to work. \ +__NN__ */ \ +__NN__ static_assert(sizeof(const char) == sizeof(/*(const char*[]){*/ #__VA_ARGS__ /*}*/), \ +__NN__ /* sizeof((int[]){ __VA_ARGS__ }) evaluates to \ +__NN__ non-zero if __VA_ARGS__ is non-empty and zero otherwise. \ +__NN__ */ \ +__NN__ VEROSE_STATIC_ASSERT_HEADER \ +__NN__ \ +__NL__ "\nStrange arguments encountered in call to " #ORIGINAL_MACRO "." \ +__NL__ "\n" \ +__NL__ "\nPlease make sure to pass exactly " #NUM_EXPECTED_ARGS \ +__NN__ " macro arguments to" \ +__NL__ "\n" #ORIGINAL_MACRO ". Also make sure that there are no dangling" \ +__NL__ "\ncommas at the end of the argument list. This is the superfluous" \ +__NL__ "\npart at the end of the macro arguments list." \ +__NL__ "\n" \ +__NL__ "\n\'" #__VA_ARGS__ "\'" \ +__NN__ \ +__NN__ VERBOSE_STATIC_ASSERT_FOOTER \ +__NL__ ); \ +__NL__ }, /* End of dummy lambda, the comma operator's A operand. */ \ +__NL__ B /* The overall ASSERT_ARGS_COUNT evaluates to B. */ \ +__NL__ ) + \ No newline at end of file From ae93c18728a9d90991463aeda59697d97ad0c9c7 Mon Sep 17 00:00:00 2001 From: Florian Fleissner Date: Sat, 23 Dec 2017 13:52:12 +0100 Subject: [PATCH 2/5] Fixed style related errors --- src/macro_helpers.h | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/macro_helpers.h b/src/macro_helpers.h index 8d90abe2..92c7c1fc 100644 --- a/src/macro_helpers.h +++ b/src/macro_helpers.h @@ -6,7 +6,7 @@ // When you want to check pre-processed code, e.g. for debugging or // to understand what's going on, do the following: // -// 1) Add the compiler command line definition +// 1) Add the compiler command line definition // -DKALEIDOSCOPE_ENABLE_MACRO_NEWLINE_SUBSTITUTION // This prevents the __NL__ macro being defined below. // 2) Generate the preprocessed code (it will contain a lot of __NL__ definitions). @@ -17,7 +17,7 @@ // as pre-processor macros remove all whitespaces at the beginning of lines. // With vim, the command gg=G helps (just type the characters one after // the other). -// 4) Don't forget to remove the +// 4) Don't forget to remove the // -DKALEIDOSCOPE_ENABLE_MACRO_NEWLINE_SUBSTITUTION // from your compiler command line. Else the code won't compile. @@ -33,7 +33,7 @@ __NL__ "\n***************************************************************" \ __NL__ "\n******************** READ THIS CAREFULLY! *********************" \ __NL__ "\n***************************************************************" \ -__NL__ "\n" +__NL__ "\n" #define VERBOSE_STATIC_ASSERT_FOOTER \ __NL__ "\n" \ @@ -41,15 +41,15 @@ __NL__ "\n***************************************************************" \ __NL__ "\n***************************************************************" \ __NL__ "\n***************************************************************" -// The macro function RESTRICT_ARGS_COUNT can be used to generate more -// verbose error messages when users supply an insuitable number of arguments +// The macro function RESTRICT_ARGS_COUNT can be used to generate more +// verbose error messages when users supply an insuitable number of arguments // to a macro. // -// For a macro it is used wherever one of the arguments A, B, C might +// For a macro it is used wherever one of the arguments A, B, C might // be used, e.g. // #if 0 // This is just so that A_MACRO is not actually defined - #define A_MACRO(A, B, C, ...) \ +#define A_MACRO(A, B, C, ...) \ (void)RESTRICT_ARGS_COUNT(0, 3, A_MACRO, ##__VA_ARGS__); \ int a = A; \ int b = B; \ @@ -60,8 +60,8 @@ __NL__ "\n***************************************************************" // arguments is used, e.g. // #if 0 // This is just so that B_MACRO is not actually defined - #define B_MACRO(A, B, C, ...) - int array[] = { A, B, RESTRICT_ARGS_COUNT(C, 3, B_MACRO, ##__VA_ARGS__) }; +#define B_MACRO(A, B, C, ...) +int array[] = { A, B, RESTRICT_ARGS_COUNT(C, 3, B_MACRO, ##__VA_ARGS__) }; #endif // #define RESTRICT_ARGS_COUNT(B, \ @@ -100,4 +100,3 @@ __NL__ ); \ __NL__ }, /* End of dummy lambda, the comma operator's A operand. */ \ __NL__ B /* The overall ASSERT_ARGS_COUNT evaluates to B. */ \ __NL__ ) - \ No newline at end of file From e9759ee64a34100b6977d41802f503b233ee6c20 Mon Sep 17 00:00:00 2001 From: Florian Fleissner Date: Mon, 25 Dec 2017 11:07:05 +0100 Subject: [PATCH 3/5] Added source file and line to static assert reports. --- src/macro_helpers.h | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/src/macro_helpers.h b/src/macro_helpers.h index 92c7c1fc..c63f47bb 100644 --- a/src/macro_helpers.h +++ b/src/macro_helpers.h @@ -27,9 +27,15 @@ #define __NN__ +// Some auxiliary macros +// +#define __STRINGIZE(S) #S +#define STRINGIZE(S) __STRINGIZE(S) + // Allow for the creation of verbose messages in static_asserts // #define VEROSE_STATIC_ASSERT_HEADER \ +__NL__ "\n" \ __NL__ "\n***************************************************************" \ __NL__ "\n******************** READ THIS CAREFULLY! *********************" \ __NL__ "\n***************************************************************" \ @@ -39,7 +45,14 @@ __NL__ "\n" __NL__ "\n" \ __NL__ "\n***************************************************************" \ __NL__ "\n***************************************************************" \ -__NL__ "\n***************************************************************" +__NL__ "\n***************************************************************" \ +__NL__ "\n" + +#define VERBOSE_FILE_INFO \ +__NL__ "\nFile: " __FILE__ + +#define VERBOSE_LINE_INFO \ +__NL__ "\nLine: " STRINGIZE(__LINE__) // The macro function RESTRICT_ARGS_COUNT can be used to generate more // verbose error messages when users supply an insuitable number of arguments @@ -79,24 +92,32 @@ __NN__ finally evaluates to. \ __NN__ Please not that passing B through this macro is a must \ __NN__ as we need it for the comma operator to work. \ __NN__ */ \ -__NN__ static_assert(sizeof(const char) == sizeof(/*(const char*[]){*/ #__VA_ARGS__ /*}*/), \ -__NN__ /* sizeof((int[]){ __VA_ARGS__ }) evaluates to \ -__NN__ non-zero if __VA_ARGS__ is non-empty and zero otherwise. \ +__NN__ static_assert(sizeof(const char) == sizeof(#__VA_ARGS__ ), \ +__NN__ /* sizeof(const char) == sizeof(#__VA_ARGS__ ) checks the quoted \ +__NN__ list of additional arguments. If there are none, then the \ +__NN__ length of #__VA_ARGS__ is a single char as it contains '\0'. \ +__NN__ This check is not able to find the corner case of a single \ +__NN__ superfluous comma at the end of the macro arguments as this \ +__NN__ causes #__VA_ARGS__ being empty (only '\0'). \ __NN__ */ \ __NN__ VEROSE_STATIC_ASSERT_HEADER \ __NN__ \ -__NL__ "\nStrange arguments encountered in call to " #ORIGINAL_MACRO "." \ +__NN__ VERBOSE_FILE_INFO \ +__NN__ VERBOSE_LINE_INFO \ +__NL__ "\n" \ +__NL__ "\nStrange arguments encountered in invocation of " #ORIGINAL_MACRO "." \ __NL__ "\n" \ __NL__ "\nPlease make sure to pass exactly " #NUM_EXPECTED_ARGS \ __NN__ " macro arguments to" \ -__NL__ "\n" #ORIGINAL_MACRO ". Also make sure that there are no dangling" \ -__NL__ "\ncommas at the end of the argument list. This is the superfluous" \ -__NL__ "\npart at the end of the macro arguments list." \ +__NL__ "\n" #ORIGINAL_MACRO ". Also make sure that there are no dangling" \ +__NL__ "\ncommas at the end of the argument list." \ __NL__ "\n" \ -__NL__ "\n\'" #__VA_ARGS__ "\'" \ +__NL__ "\nThis is the superfluous part at the end of the macro" \ +__NL__ "\narguments list: \'" #__VA_ARGS__ "\'" \ __NN__ \ __NN__ VERBOSE_STATIC_ASSERT_FOOTER \ __NL__ ); \ +__NL__ \ __NL__ }, /* End of dummy lambda, the comma operator's A operand. */ \ __NL__ B /* The overall ASSERT_ARGS_COUNT evaluates to B. */ \ __NL__ ) From c811d3be703f676958a80d5516b0b9b5f706bf6d Mon Sep 17 00:00:00 2001 From: Florian Fleissner Date: Mon, 25 Dec 2017 11:10:41 +0100 Subject: [PATCH 4/5] Fixed style errors --- src/macro_helpers.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/macro_helpers.h b/src/macro_helpers.h index c63f47bb..c24c9ac5 100644 --- a/src/macro_helpers.h +++ b/src/macro_helpers.h @@ -28,7 +28,7 @@ #define __NN__ // Some auxiliary macros -// +// #define __STRINGIZE(S) #S #define STRINGIZE(S) __STRINGIZE(S) @@ -49,10 +49,10 @@ __NL__ "\n***************************************************************" \ __NL__ "\n" #define VERBOSE_FILE_INFO \ -__NL__ "\nFile: " __FILE__ +__NL__ "\nFile: " __FILE__ #define VERBOSE_LINE_INFO \ -__NL__ "\nLine: " STRINGIZE(__LINE__) +__NL__ "\nLine: " STRINGIZE(__LINE__) // The macro function RESTRICT_ARGS_COUNT can be used to generate more // verbose error messages when users supply an insuitable number of arguments From 869ba74edf29c19ab7ce60a8ea10d6077ca0f1f8 Mon Sep 17 00:00:00 2001 From: noseglasses Date: Mon, 19 Feb 2018 16:59:17 +0100 Subject: [PATCH 5/5] Update macro_helpers.h Corrected spelling. --- src/macro_helpers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/macro_helpers.h b/src/macro_helpers.h index c24c9ac5..31b0976e 100644 --- a/src/macro_helpers.h +++ b/src/macro_helpers.h @@ -34,7 +34,7 @@ // Allow for the creation of verbose messages in static_asserts // -#define VEROSE_STATIC_ASSERT_HEADER \ +#define VERBOSE_STATIC_ASSERT_HEADER \ __NL__ "\n" \ __NL__ "\n***************************************************************" \ __NL__ "\n******************** READ THIS CAREFULLY! *********************" \ @@ -100,7 +100,7 @@ __NN__ This check is not able to find the corner case of a single \ __NN__ superfluous comma at the end of the macro arguments as this \ __NN__ causes #__VA_ARGS__ being empty (only '\0'). \ __NN__ */ \ -__NN__ VEROSE_STATIC_ASSERT_HEADER \ +__NN__ VERBOSE_STATIC_ASSERT_HEADER \ __NN__ \ __NN__ VERBOSE_FILE_INFO \ __NN__ VERBOSE_LINE_INFO \