1 // Copyright 2020 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 15 // Macros for working with arguments to function-like macros. 16 #pragma once 17 18 #include "pw_preprocessor/boolean.h" 19 #include "pw_preprocessor/compiler.h" 20 #include "pw_preprocessor/internal/arg_count_impl.h" 21 22 // Expands to a comma followed by __VA_ARGS__, if __VA_ARGS__ is non-empty. 23 // Otherwise, expands to nothing. If the final argument is empty, it is omitted. 24 // This is useful when passing __VA_ARGS__ to a variadic function or template 25 // parameter list, since it removes the extra comma when no arguments are 26 // provided. PW_COMMA_ARGS must NOT be used when invoking a macro from another 27 // macro. 28 // 29 // This is a more flexible, standard-compliant version of ##__VA_ARGS__. Unlike 30 // ##__VA_ARGS__, this can be used to eliminate an unwanted comma when 31 // __VA_ARGS__ expands to an empty argument because an outer macro was called 32 // with __VA_ARGS__ instead of ##__VA_ARGS__. Also, since PW_COMMA_ARGS drops 33 // the last argument if it is empty, both MY_MACRO(1, 2) and MY_MACRO(1, 2, ) 34 // can work correctly. 35 // 36 // PW_COMMA_ARGS must NOT be used to conditionally include a comma when invoking 37 // a macro from another macro. PW_COMMA_ARGS only functions correctly when the 38 // macro expands to C or C++ code! Using it with intermediate macros can result 39 // in out-of-order parameters. When invoking one macro from another, simply pass 40 // __VA_ARGS__. Only the final macro that expands to C/C++ code should use 41 // PW_COMMA_ARGS. 42 // 43 // For example, the following does NOT work: 44 /* 45 #define MY_MACRO(fmt, ...) \ 46 NESTED_MACRO(fmt PW_COMMA_ARGS(__VA_ARGS__)) // BAD! Do not do this! 47 */ 48 // Instead, only use PW_COMMA_ARGS when the macro expands to C/C++ code: 49 /* 50 #define MY_MACRO(fmt, ...) \ 51 NESTED_MACRO(fmt, __VA_ARGS__) // Pass __VA_ARGS__ to nested macros 52 53 #define NESTED_MACRO(fmt, ...) \ 54 printf(fmt PW_COMMA_ARGS(__VA_ARGS__)) // PW_COMMA_ARGS is OK here 55 */ 56 #define PW_COMMA_ARGS(...) \ 57 _PW_IF(PW_EMPTY_ARGS(__VA_ARGS__), _PW_EXPAND, _PW_COMMA_ARGS) \ 58 (PW_DROP_LAST_ARG_IF_EMPTY(__VA_ARGS__)) 59 60 #define _PW_COMMA_ARGS(...) , __VA_ARGS__ 61 62 // Allows calling a different function-like macros based on the number of 63 // arguments. For example: 64 // 65 // #define ARG_PRINT(...) PW_DELEGATE_BY_ARG_COUNT(_ARG_PRINT, __VA_ARGS__) 66 // #define _ARG_PRINT1(a) LOG_INFO("1 arg: %s", a) 67 // #define _ARG_PRINT2(a, b) LOG_INFO("2 args: %s, %s", a, b) 68 // #define _ARG_PRINT3(a, b, c) LOG_INFO("3 args: %s, %s, %s", a, b, c) 69 // 70 // This can the be called from C/C++ code: 71 // 72 // ARG_PRINT("a"); // Outputs: 1 arg: a 73 // ARG_PRINT("a", "b"); // Outputs: 2 args: a, b 74 // ARG_PRINT("a", "b", "c"); // Outputs: 3 args: a, b, c 75 // 76 #define PW_DELEGATE_BY_ARG_COUNT(function, ...) \ 77 _PW_DELEGATE_BY_ARG_COUNT( \ 78 _PW_PASTE2(function, PW_FUNCTION_ARG_COUNT(__VA_ARGS__)), \ 79 PW_DROP_LAST_ARG_IF_EMPTY(__VA_ARGS__)) 80 81 #define _PW_DELEGATE_BY_ARG_COUNT(function, ...) function(__VA_ARGS__) 82 83 // PW_MACRO_ARG_COUNT counts the number of arguments it was called with. It 84 // evalulates to an integer literal in the range 0 to 64. Counting more than 64 85 // arguments is not currently supported. 86 // 87 // PW_MACRO_ARG_COUNT is most commonly used to count __VA_ARGS__ in a variadic 88 // macro. For example, the following code counts the number of arguments passed 89 // to a logging macro: 90 // 91 /* #define LOG_INFO(format, ...) { \ 92 static const int kArgCount = PW_MACRO_ARG_COUNT(__VA_ARGS__); \ 93 SendLog(kArgCount, format, ##__VA_ARGS__); \ 94 } 95 */ 96 // The macro argument lists were generated with a Python script: 97 /* 98 COUNT = 256 99 100 for i in range(COUNT, 0, -1): 101 if i % 8 == 0: 102 print('\ \n', end='') 103 print(f"{i:3}, ", end='') 104 105 for i in range(COUNT, 0, -1): 106 if i % 8 == 0: 107 print('\ \n', end='') 108 print(f"a{i:03}, ", end='') 109 */ 110 // clang-format off 111 #define PW_MACRO_ARG_COUNT(...) \ 112 _PW_MACRO_ARG_COUNT_IMPL(__VA_ARGS__, \ 113 256, 255, 254, 253, 252, 251, 250, 249, \ 114 248, 247, 246, 245, 244, 243, 242, 241, \ 115 240, 239, 238, 237, 236, 235, 234, 233, \ 116 232, 231, 230, 229, 228, 227, 226, 225, \ 117 224, 223, 222, 221, 220, 219, 218, 217, \ 118 216, 215, 214, 213, 212, 211, 210, 209, \ 119 208, 207, 206, 205, 204, 203, 202, 201, \ 120 200, 199, 198, 197, 196, 195, 194, 193, \ 121 192, 191, 190, 189, 188, 187, 186, 185, \ 122 184, 183, 182, 181, 180, 179, 178, 177, \ 123 176, 175, 174, 173, 172, 171, 170, 169, \ 124 168, 167, 166, 165, 164, 163, 162, 161, \ 125 160, 159, 158, 157, 156, 155, 154, 153, \ 126 152, 151, 150, 149, 148, 147, 146, 145, \ 127 144, 143, 142, 141, 140, 139, 138, 137, \ 128 136, 135, 134, 133, 132, 131, 130, 129, \ 129 128, 127, 126, 125, 124, 123, 122, 121, \ 130 120, 119, 118, 117, 116, 115, 114, 113, \ 131 112, 111, 110, 109, 108, 107, 106, 105, \ 132 104, 103, 102, 101, 100, 99, 98, 97, \ 133 96, 95, 94, 93, 92, 91, 90, 89, \ 134 88, 87, 86, 85, 84, 83, 82, 81, \ 135 80, 79, 78, 77, 76, 75, 74, 73, \ 136 72, 71, 70, 69, 68, 67, 66, 65, \ 137 64, 63, 62, 61, 60, 59, 58, 57, \ 138 56, 55, 54, 53, 52, 51, 50, 49, \ 139 48, 47, 46, 45, 44, 43, 42, 41, \ 140 40, 39, 38, 37, 36, 35, 34, 33, \ 141 32, 31, 30, 29, 28, 27, 26, 25, \ 142 24, 23, 22, 21, 20, 19, 18, 17, \ 143 16, 15, 14, 13, 12, 11, 10, 9, \ 144 8, 7, 6, 5, 4, 3, 2, PW_HAS_ARGS(__VA_ARGS__)) 145 146 147 #define _PW_MACRO_ARG_COUNT_IMPL( \ 148 a256, a255, a254, a253, a252, a251, a250, a249, \ 149 a248, a247, a246, a245, a244, a243, a242, a241, \ 150 a240, a239, a238, a237, a236, a235, a234, a233, \ 151 a232, a231, a230, a229, a228, a227, a226, a225, \ 152 a224, a223, a222, a221, a220, a219, a218, a217, \ 153 a216, a215, a214, a213, a212, a211, a210, a209, \ 154 a208, a207, a206, a205, a204, a203, a202, a201, \ 155 a200, a199, a198, a197, a196, a195, a194, a193, \ 156 a192, a191, a190, a189, a188, a187, a186, a185, \ 157 a184, a183, a182, a181, a180, a179, a178, a177, \ 158 a176, a175, a174, a173, a172, a171, a170, a169, \ 159 a168, a167, a166, a165, a164, a163, a162, a161, \ 160 a160, a159, a158, a157, a156, a155, a154, a153, \ 161 a152, a151, a150, a149, a148, a147, a146, a145, \ 162 a144, a143, a142, a141, a140, a139, a138, a137, \ 163 a136, a135, a134, a133, a132, a131, a130, a129, \ 164 a128, a127, a126, a125, a124, a123, a122, a121, \ 165 a120, a119, a118, a117, a116, a115, a114, a113, \ 166 a112, a111, a110, a109, a108, a107, a106, a105, \ 167 a104, a103, a102, a101, a100, a099, a098, a097, \ 168 a096, a095, a094, a093, a092, a091, a090, a089, \ 169 a088, a087, a086, a085, a084, a083, a082, a081, \ 170 a080, a079, a078, a077, a076, a075, a074, a073, \ 171 a072, a071, a070, a069, a068, a067, a066, a065, \ 172 a064, a063, a062, a061, a060, a059, a058, a057, \ 173 a056, a055, a054, a053, a052, a051, a050, a049, \ 174 a048, a047, a046, a045, a044, a043, a042, a041, \ 175 a040, a039, a038, a037, a036, a035, a034, a033, \ 176 a032, a031, a030, a029, a028, a027, a026, a025, \ 177 a024, a023, a022, a021, a020, a019, a018, a017, \ 178 a016, a015, a014, a013, a012, a011, a010, a009, \ 179 a008, a007, a006, a005, a004, a003, a002, a001, \ 180 count, ...) \ 181 count 182 183 // clang-format on 184 185 // Argument count for using with a C/C++ function or template parameter list. 186 // The difference from PW_MACRO_ARG_COUNT is that the last argument is not 187 // counted if it is empty. This makes it easier to drop the final comma when 188 // expanding to C/C++ code. 189 #define PW_FUNCTION_ARG_COUNT(...) \ 190 _PW_FUNCTION_ARG_COUNT(PW_LAST_ARG(__VA_ARGS__), __VA_ARGS__) 191 192 #define _PW_FUNCTION_ARG_COUNT(last_arg, ...) \ 193 _PW_PASTE2(_PW_FUNCTION_ARG_COUNT_, PW_EMPTY_ARGS(last_arg))(__VA_ARGS__) 194 195 #define _PW_FUNCTION_ARG_COUNT_0 PW_MACRO_ARG_COUNT 196 #define _PW_FUNCTION_ARG_COUNT_1(...) \ 197 PW_MACRO_ARG_COUNT(PW_DROP_LAST_ARG(__VA_ARGS__)) 198 199 // Evaluates to the last argument in the provided arguments. 200 #define PW_LAST_ARG(...) \ 201 _PW_PASTE2(_PW_LAST_ARG_, PW_MACRO_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__) 202 203 // Evaluates to the provided arguments, excluding the final argument. 204 #define PW_DROP_LAST_ARG(...) \ 205 _PW_PASTE2(_PW_DROP_LAST_ARG_, PW_MACRO_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__) 206 207 // Evaluates to the arguments, excluding the final argument if it is empty. 208 #define PW_DROP_LAST_ARG_IF_EMPTY(...) \ 209 _PW_IF( \ 210 PW_EMPTY_ARGS(PW_LAST_ARG(__VA_ARGS__)), PW_DROP_LAST_ARG, _PW_EXPAND) \ 211 (__VA_ARGS__) 212 213 // Expands to 1 if one or more arguments are provided, 0 otherwise. 214 #define PW_HAS_ARGS(...) PW_NOT(PW_EMPTY_ARGS(__VA_ARGS__)) 215 216 #if PW_VA_OPT_SUPPORTED() 217 218 // Expands to 0 if one or more arguments are provided, 1 otherwise. 219 #define PW_EMPTY_ARGS(...) _PW_EMPTY_ARGS_##__VA_OPT__(0) 220 #define _PW_EMPTY_ARGS_ 1 221 #define _PW_EMPTY_ARGS_0 0 222 223 #else 224 225 // If __VA_OPT__ is not available, use a complicated fallback mechanism. This 226 // approach is from Jens Gustedt's blog: 227 // https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/ 228 // 229 // Normally, with a standard-compliant C preprocessor, it's impossible to tell 230 // whether a variadic macro was called with no arguments or with one argument. 231 // A macro invoked with no arguments is actually passed one empty argument. 232 // 233 // This macro works by checking for the presence of a comma in four situations. 234 // These situations give the following information about __VA_ARGS__: 235 // 236 // 1. It is two or more variadic arguments. 237 // 2. It expands to one argument surrounded by parentheses. 238 // 3. It is a function-like macro that produces a comma when invoked. 239 // 4. It does not interfere with calling a macro when placed between it and 240 // parentheses. 241 // 242 // If a comma is not present in 1, 2, 3, but is present in 4, then __VA_ARGS__ 243 // is empty. For this case (0001), and only this case, a corresponding macro 244 // that expands to a comma is defined. The presence of this comma determines 245 // whether any arguments were passed in. 246 #define PW_EMPTY_ARGS(...) \ 247 _PW_HAS_NO_ARGS(_PW_HAS_COMMA(__VA_ARGS__), \ 248 _PW_HAS_COMMA(_PW_MAKE_COMMA_IF_CALLED __VA_ARGS__), \ 249 _PW_HAS_COMMA(__VA_ARGS__()), \ 250 _PW_HAS_COMMA(_PW_MAKE_COMMA_IF_CALLED __VA_ARGS__())) 251 252 // clang-format off 253 #define _PW_HAS_COMMA(...) \ 254 _PW_MACRO_ARG_COUNT_IMPL(__VA_ARGS__, \ 255 /* 16 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 256 /* 32 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 257 /* 48 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 258 /* 64 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 259 /* */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 260 /* */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 261 /* */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 262 /* 128 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 263 /* */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 264 /* */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 265 /* */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 266 /* 196 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 267 /* */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 268 /* */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 269 /* */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ 270 /* 256 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0) 271 // clang-format on 272 273 #define _PW_HAS_NO_ARGS(a1, a2, a3, a4) \ 274 _PW_HAS_COMMA(_PW_PASTE_RESULTS(a1, a2, a3, a4)) 275 #define _PW_PASTE_RESULTS(a1, a2, a3, a4) _PW_HAS_COMMA_CASE_##a1##a2##a3##a4 276 #define _PW_HAS_COMMA_CASE_0001 , 277 #define _PW_MAKE_COMMA_IF_CALLED(...) , 278 279 #endif // PW_VA_OPT_SUPPORTED() 280