1 // Copyright 2019 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 #pragma once 16 17 // Preprocessor boolean operation macros that evaluate to 0 or 1. 18 // 19 // These macros perform boolean operations in the C preprocessor that evaluate 20 // to a literal 1 or 0. They can be used for a few purposes: 21 // 22 // - Generate other macros that evaluate to a 1 or 0, instead of a 23 // parenthesized boolean expression. 24 // - Ensure that the operands are defined and evaluate to 1 or 0 themselves. 25 // - Write macros that conditionally use other macros by token pasting the 26 // resulting 1 or 0 to form a new macro name. 27 // 28 // These macros should not be used outside of macro definitions. Use normal C 29 // operators (&&, ||, !, ==, !=) instead. For example, to check whether two 30 // flags are set, the C operators are the best choice: 31 // 32 // #if RELEASE && OPTIMIZED 33 // 34 // However, there are cases when a literal 0 or 1 is required. For example: 35 // 36 // #define SELECT_ALGORITHM() PW_CONCAT(ALGO_, PW_AND(RELEASE, OPTIMIZED)) 37 // 38 // SELECT_ALGORITHM evaluates to ALGO_0 or ALGO_1, depending on whether RELEASE 39 // and OPTIMIZED are set to 1. 40 41 // Boolean AND of two preprocessor expressions that evaluate to 0 or 1. 42 #define PW_AND(a, b) _PW_AND(a, b) // Expand the macro an extra time to 43 #define _PW_AND(a, b) _PW_AND_##a##b() // allow macro substitution to occur. 44 #define _PW_AND_00() 0 45 #define _PW_AND_01() 0 46 #define _PW_AND_10() 0 47 #define _PW_AND_11() 1 48 49 // Boolean OR of two preprocessor expressions that evaluate to 0 or 1. 50 #define PW_OR(a, b) _PW_OR(a, b) 51 #define _PW_OR(a, b) _PW_OR_##a##b() 52 #define _PW_OR_00() 0 53 #define _PW_OR_01() 1 54 #define _PW_OR_10() 1 55 #define _PW_OR_11() 1 56 57 // Boolean NOT of a preprocessor expression that evaluates to 0 or 1. 58 #define PW_NOT(value) _PW_NOT(value) 59 #define _PW_NOT(value) _PW_NOT_##value() 60 #define _PW_NOT_0() 1 61 #define _PW_NOT_1() 0 62 63 // Boolean XOR of two preprocessor expressions that evaluate to 0 or 1. 64 #define PW_XOR(a, b) _PW_XOR(a, b) 65 #define _PW_XOR(a, b) _PW_XOR_##a##b() 66 #define _PW_XOR_00() 0 67 #define _PW_XOR_01() 1 68 #define _PW_XOR_10() 1 69 #define _PW_XOR_11() 0 70 71 // Boolean NAND, NOR, and XNOR of expressions that evaluate to 0 or 1. 72 #define PW_NAND(a, b) PW_NOT(PW_AND(a, b)) 73 #define PW_NOR(a, b) PW_NOT(PW_OR(a, b)) 74 #define PW_XNOR(a, b) PW_NOT(PW_XOR(a, b)) 75