├── LICENSE ├── README.md ├── args.h ├── blank.h ├── consume.h ├── foldl.h ├── foldr.h ├── intersperse.h ├── list.h ├── map-lists.h ├── map.h ├── paren.h ├── separators.h ├── stop-lists.h ├── stop.h ├── tests ├── foldl.in.c ├── foldl.out.c ├── foldr.in.c ├── foldr.out.c ├── intersperse.in.c ├── intersperse.out.c ├── map-lists.in.c ├── map-lists.out.c ├── map.in.c ├── map.out.c ├── run.bash ├── zip-repeat.in.c ├── zip-repeat.out.c ├── zip.in.c └── zip.out.c ├── zip-repeat.h └── zip.h /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Malcolm Inglis 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | I've released [Libpp](https://github.com/mcinglis/libpp) which provides many similar macros, but is significantly faster, actively maintained, and certainly standards-conformant. Both are limited in the number of arguments the macros can handle, but Libpp's limit can be easily changed. 3 | 4 | Macrofun is still provided here as a demonstration of a cool hack. 5 | 6 | ----- 7 | 8 | **[Macrofun](https://github.com/mcinglis/macrofun)** provides functional-programming macros for the C preprocessor, like mapping, folding and zipping over arguments in various forms. 9 | 10 | **Macrofun is just a demonstration; please don't use it.** It depends on preprocessing behavior of GCC and Clang that may not conform to the ISO standards. Section 6.10.3.4 paragraph 2 of the [C11 standard](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) specifies: 11 | 12 | > If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced. Furthermore, **if any nested replacements encounter the name of the macro being replaced, it is not replaced.** These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced. 13 | 14 | However, the meaning of "nested replacements" is ambiguous: it may only refer to *immediately*-nested replacements. pfultz2 wrote in [an issue](https://github.com/mcinglis/macrofun/issues/1): 15 | 16 | > The description of the C99 preprocessor in the standard implies a DAG, so this library does not violate the rule of a "nested replacement", as such. Futhermore, David Prosser's description of the [algorithm](http://www.spinellis.gr/blog/20060626/), which demonstrates the "intent of the specification" shows that gcc is conforming. So it is unfair to say that gcc is non-conforming in this regard, since most implementations interpret it as a DAG, and the reference implementation interprets it this way as well. 17 | 18 | > Of course, it could be interpreted as a hierarchical expansion, however, this is extremely rare, and could be considered non-conforming in the future. Although n3882 is a C++ proposal, its approval and addition in C++ could be a very strong persuasion to include the same text in C. 19 | 20 | An example of using these macros: 21 | 22 | ``` c 23 | #include // FOLDL 24 | #include // INTERSPERSE 25 | #include // MAP 26 | #include // MAP_LISTS 27 | #include // SEP_* 28 | #include // ZIP 29 | #include // ZIP_REPEAT 30 | 31 | int main( void ) 32 | { 33 | #define PRINTD1( expr ) printf( "%s = %d\n", #expr, expr ) 34 | #define PRINTD( ... ) MAP( PRINTD1, SEP_SEMICOLON, __VA_ARGS__ ) 35 | PRINTD( 1 + 1, // ==> 1 + 1 = 2 36 | 8 / 2 * 3 ); // ==> 8 / 2 * 3 = 12 37 | MAP_LISTS( m, SEP_COMMA, (a,b), (c,d) ) // m(a, b), m(c, d) 38 | INTERSPERSE( SEP_AND, a, b, c, d ) // (a) && (b) && (c) && (d) 39 | FOLDL( m, acc, a, b, c ) // m( m( m( acc, a ), b ), c ) 40 | FOLDR( f, acc, a, b, c ) // f( a, f( b, f( c, acc ) ) ) 41 | // FOLDR breaks when folding with a macro expression, because the 42 | // preprocessor then detects and disables the recursion. 43 | ZIP( (a,b,c), (d,e,f,g), (h,i,j) ) // (a,d,h), (b,e,i), (c,f,j) 44 | ZIP_REPEAT( (a,b), (c,d), (e,f) ) // (a,b,c,d), (a,b,e,f) 45 | } 46 | ``` 47 | 48 | The source files include extensive comments and example usage of each of the macros. 49 | 50 | You can run the tests by executing `tests/run.bash`. These tests work by `diff`ing the output of `gcc -E` for each `.in.c` file against the corresponding `.out.c` file. These `out.c` files contain the specific whitespacing provided by GCC 4.8. Therefore, the tests may "fail" for other preprocessors, even though they output functionally equivalent code. 51 | 52 | Macrofun has been tested with GCC 4.8 and Clang 3.4. 53 | 54 | Macrofun's recursion method is derived from William Swanson's [map-macro](https://github.com/swansontec/map-macro). 55 | 56 | I've played around with the possibilities provided by this library for a few months now, and I've seen it do a lot of good. Recursive macros give C programmers so much more power to manipulate their code. Things like `MAP` and `MAP_LISTS` can remove a lot of repetition in your code and your clients' code. 57 | 58 | ``` c 59 | Test tests[] = { TEST( some_test_func ), 60 | TEST( another_test_func ), 61 | TEST( one_more_for_good_measure ) }; 62 | // could become, via MAP: 63 | Test tests[] = TESTS( some_test_func, 64 | another_test_func, 65 | one_more_for_good_measure ); 66 | 67 | return assertions( ASSERTION( 23 > 12 ), 68 | ASSERTION( "example"[ 2 ] == 'x' ), 69 | ASSERTION( 8 * 2 == 16 ) ); 70 | // could become: 71 | return assertions( 23 > 12, 72 | "example"[ 2 ] == 'x', 73 | 8 * 2 == 16 ); 74 | ``` 75 | 76 | Catamorphisms in the C preprocessor! 77 | 78 | ``` c 79 | #define MAX_TWO( x, y ) ( ( x ) > ( y ) ? ( x ) : ( y ) ) 80 | #define MAX( n, ... ) FOLDL( MAX_TWO, n, __VA_ARGS__ ) 81 | 82 | #define PLUS( x, y ) ( ( x ) + ( y ) ) 83 | #define SUM( ... ) FOLDL( PLUS, 0, __VA_ARGS__ ) 84 | ``` 85 | 86 | Treating code as data: 87 | 88 | ``` c 89 | #define ALL( ... ) INTERSPERSE( SEP_AND, __VA_ARGS__ ) 90 | #define ANY( ... ) INTERSPERSE( SEP_OR, __VA_ARGS__ ) 91 | #define ASSERT( ... ) MAP( assert, SEP_SEMICOLON, __VA_ARGS__ ) 92 | 93 | #define INVARIANTS_EMPTY( s ) \ 94 | s.bytes == NULL, \ 95 | s.length == 0, \ 96 | s.capacity == 0 97 | 98 | #define INVARIANTS_NONEMPTY( s ) \ 99 | s.capacity > s.length, \ 100 | s.bytes != NULL, \ 101 | all_bytes_up_to_length_are_nonzero( s ), \ 102 | s.bytes[ s.length ] == '\0', \ 103 | 104 | bool string_is_valid( String const s ) 105 | { 106 | return ALL( INVARIANTS_EMPTY( s ) ) 107 | || ALL( INVARIANTS_NONEMPTY( s ) ); 108 | } 109 | 110 | // We want fine-grained assertion errors, so we can't just do 111 | // `assert( string_is_valid( s ) )`. 112 | void string_assert_valid( String const s ) 113 | { 114 | if ( ANY( INVARIANTS_EMPTY( s ) ) ) { 115 | ASSERT( INVARIANTS_EMPTY( s ) ); 116 | } else { 117 | ASSERT( INVARIANTS_NONEMPTY( s ) ); 118 | } 119 | } 120 | ``` 121 | 122 | `MAP_LISTS` makes it much easier to define generic functions for a set of types. 123 | 124 | ``` c 125 | #define TYPE_SUFFIXES \ 126 | ( bool, bools ), \ 127 | ( char, chars ), \ 128 | ( signed char, schars ), \ 129 | ( unsigned char, uchars ), \ 130 | ( short, shorts ), \ 131 | /* 20 more lines snipped */ 132 | 133 | enum Ordering { 134 | Ordering_LT = -1, 135 | Ordering_EQ = 0, 136 | Ordering_GT = 1 137 | }; 138 | 139 | #define COMPARE_PROTOTYPE( type, suffix ) \ 140 | enum Ordering compare_##suffix( type, type ); 141 | MAP_LISTS( COMPARE_PROTOTYPE, SEP_NONE, COMPARABLE_TYPE_SUFFIXES ) 142 | // enum Ordering compare_bools( bool, bool ); 143 | // enum Ordering compare_chars( char, char ); 144 | // ... 145 | 146 | #define COMPARE_IMPL( type, suffix ) \ 147 | enum Ordering compare_##suffix( type const x, type const y ) \ 148 | { \ 149 | return ( x > y ) - ( x < y ); \ 150 | } 151 | MAP_LISTS( COMPARE_IMPL, SEP_NONE, COMPARABLE_TYPE_SUFFIXES ) 152 | 153 | #define COMPARE_TYPE_HANDLER( type, suffix ) \ 154 | type: compare_##suffix, \ 155 | type const: compare_##suffix 156 | 157 | #define compare( x, y ) \ 158 | _Generic( x, \ 159 | MAP_LISTS( COMPARE_TYPE_HANDLER, \ 160 | SEP_COMMA, \ 161 | COMPARABLE_TYPE_SUFFIXES ), \ 162 | default: compare_pointers )( x, y ) 163 | ``` 164 | 165 | -------------------------------------------------------------------------------- /args.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_ARGS_H 3 | #define MACROFUN_ARGS_H 4 | 5 | 6 | #define ARGS_1ST( x, ... ) x 7 | #define ARGS_2ND( x, y, ... ) y 8 | #define ARGS_REST( x, ... ) __VA_ARGS__ 9 | #define ARGS_REST_TO_LIST( ... ) ( ARGS_REST( __VA_ARGS__ ) ) 10 | 11 | 12 | #endif // ifndef MACROFUN_ARGS_H 13 | 14 | -------------------------------------------------------------------------------- /blank.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_BLANK_H 3 | #define MACROFUN_BLANK_H 4 | 5 | 6 | // Preprocessor recursion can occur between two different macros; a macro 7 | // can't recurse directly into itself, but it can call another macro that 8 | // calls the first again. This value should be used to separate the name of 9 | // the paired macro, and its argument list; see `map.h` as an example. 10 | #define BLANK 11 | 12 | 13 | #endif // ifndef MACROFUN_BLANK_H 14 | 15 | -------------------------------------------------------------------------------- /consume.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_CONSUME_H 3 | #define MACROFUN_CONSUME_H 4 | 5 | 6 | // Takes any number of expressions and evaluates to nothing. 7 | #define CONSUME( ... ) 8 | 9 | 10 | #endif // ifndef MACROFUN_CONSUME_H 11 | 12 | -------------------------------------------------------------------------------- /foldl.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_FOLDL_H 3 | #define MACROFUN_FOLDL_H 4 | 5 | 6 | #include "args.h" // ARGS_2ND 7 | #include "blank.h" // BLANK 8 | #include "consume.h" // CONSUME 9 | #include "paren.h" // UNPAREN 10 | #include "stop.h" // STOP2, IF_STOP2 11 | 12 | 13 | // Given an expression callable with two arguments, a starting value, and a 14 | // variable number of expressions, this returns a reduction of those 15 | // expressions using the given callable, from left to right. 16 | // 17 | // FOLDL( m, acc, a ) >>> m( acc, a ) 18 | // FOLDL( m, acc, a, b ) >>> m( m( acc, a ), b ) 19 | // FOLDL( m, acc, a, b, c ) >>> m( m( m( acc, a ), b ), c ) 20 | // 21 | #define FOLDL( m, acc, ... ) \ 22 | FOLDL_EVAL( FOLDL_0( m, acc, __VA_ARGS__, STOP2, 0 ) ) 23 | 24 | #define FOLDL_0( m, acc, head, next, ... ) \ 25 | IF_STOP2( next, ARGS_2ND, FOLDL_1 ) \ 26 | BLANK ( m, m( acc, head ), next, __VA_ARGS__ ) 27 | 28 | #define FOLDL_1( ... ) \ 29 | FOLDL_0 BLANK ( __VA_ARGS__ ) 30 | 31 | // Note that we use `STOP2` and `IF_STOP2`, so that we can accept `STOP` as a 32 | // valid argument to fold over; this feature is used to implement 33 | // `IF_STOP_IN`. 34 | 35 | 36 | // Causes 256 rounds of evaluation of its arguments. This enables a crude 37 | // form of recursion, with a maximum call-depth of 256. Each recursive macro 38 | // needs to provide its own recursive evaluator, because a recursive 39 | // evaluator can't be used recursively itself. This allows for recursive 40 | // macros to be defined in terms of other recursive macros. 41 | #define FOLDL_EVAL( ... ) FOLDL_EVAL255( __VA_ARGS__ ) 42 | 43 | #define FOLDL_EVAL255( ... ) FOLDL_EVAL127( FOLDL_EVAL127( __VA_ARGS__ ) ) 44 | #define FOLDL_EVAL127( ... ) FOLDL_EVAL63( FOLDL_EVAL63( __VA_ARGS__ ) ) 45 | #define FOLDL_EVAL63( ... ) FOLDL_EVAL31( FOLDL_EVAL31( __VA_ARGS__ ) ) 46 | #define FOLDL_EVAL31( ... ) FOLDL_EVAL15( FOLDL_EVAL15( __VA_ARGS__ ) ) 47 | #define FOLDL_EVAL15( ... ) FOLDL_EVAL7( FOLDL_EVAL7( __VA_ARGS__ ) ) 48 | #define FOLDL_EVAL7( ... ) FOLDL_EVAL3( FOLDL_EVAL3( __VA_ARGS__ ) ) 49 | #define FOLDL_EVAL3( ... ) FOLDL_EVAL1( FOLDL_EVAL1( __VA_ARGS__ ) ) 50 | #define FOLDL_EVAL1( ... ) __VA_ARGS__ 51 | 52 | 53 | #endif // ifndef MACROFUN_FOLDL_H 54 | 55 | -------------------------------------------------------------------------------- /foldr.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_FOLDR_H 3 | #define MACROFUN_FOLDR_H 4 | 5 | 6 | #include "args.h" // ARGS_2ND 7 | #include "blank.h" // BLANK 8 | #include "consume.h" // CONSUME 9 | #include "paren.h" // UNPAREN 10 | #include "stop.h" // STOP2, IF_STOP2 11 | 12 | 13 | // Given a non-macro expression callable with two arguments, a starting 14 | // value, and a variable number of expressions, this returns a reduction of 15 | // those expressions using the given callable, from left to right. 16 | // 17 | // FOLDR( f, acc, a ) >>> f( a, acc ) 18 | // FOLDR( f, acc, a, b ) >>> f( a, f( b, acc ) ) 19 | // FOLDR( f, acc, a, b, c ) >>> f( a, f( b, f( c, acc ) ) ) 20 | // 21 | // Note that this breaks when given a macro, because GCC and Clang then 22 | // detect and disable the recursion. 23 | #define FOLDR( f, acc, ... ) \ 24 | FOLDR_EVAL( FOLDR_0( f, acc, __VA_ARGS__, STOP2, 0 ) ) 25 | 26 | #define FOLDR_0( f, acc, head, next, ... ) \ 27 | f( head, \ 28 | IF_STOP2( next, acc CONSUME, FOLDR_1 ) \ 29 | BLANK ( f, acc, next, __VA_ARGS__ ) ) 30 | 31 | #define FOLDR_1( ... ) \ 32 | FOLDR_0 BLANK ( __VA_ARGS__ ) 33 | 34 | // Note that we use `STOP2` and `IF_STOP2`, so that we can accept `STOP` as a 35 | // valid argument to fold over; this feature is used to implement 36 | // `IF_STOP_IN`. 37 | 38 | 39 | // Causes 256 rounds of evaluation of its arguments. This enables a crude 40 | // form of recursion, with a maximum call-depth of 256. Each recursive macro 41 | // needs to provide its own recursive evaluator, because a recursive 42 | // evaluator can't be used recursively itself. This allows for recursive 43 | // macros to be defined in terms of other recursive macros. 44 | #define FOLDR_EVAL( ... ) FOLDR_EVAL255( __VA_ARGS__ ) 45 | 46 | #define FOLDR_EVAL255( ... ) FOLDR_EVAL127( FOLDR_EVAL127( __VA_ARGS__ ) ) 47 | #define FOLDR_EVAL127( ... ) FOLDR_EVAL63( FOLDR_EVAL63( __VA_ARGS__ ) ) 48 | #define FOLDR_EVAL63( ... ) FOLDR_EVAL31( FOLDR_EVAL31( __VA_ARGS__ ) ) 49 | #define FOLDR_EVAL31( ... ) FOLDR_EVAL15( FOLDR_EVAL15( __VA_ARGS__ ) ) 50 | #define FOLDR_EVAL15( ... ) FOLDR_EVAL7( FOLDR_EVAL7( __VA_ARGS__ ) ) 51 | #define FOLDR_EVAL7( ... ) FOLDR_EVAL3( FOLDR_EVAL3( __VA_ARGS__ ) ) 52 | #define FOLDR_EVAL3( ... ) FOLDR_EVAL1( FOLDR_EVAL1( __VA_ARGS__ ) ) 53 | #define FOLDR_EVAL1( ... ) __VA_ARGS__ 54 | 55 | 56 | #endif // ifndef MACROFUN_FOLDR_H 57 | 58 | -------------------------------------------------------------------------------- /intersperse.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_INTERSPERSE_H 3 | #define MACROFUN_INTERSPERSE_H 4 | 5 | 6 | #include "paren.h" // PAREN 7 | #include "map.h" // MAP 8 | 9 | 10 | // Takes a callable expression `sep`, and a variable number of following 11 | // arguments, and returns those arguments parenthesesized, and separated by 12 | // calls to `sep` with the previous argument. 13 | // 14 | // INTERSPERSE( s, a ) >>> ( a ) 15 | // INTERSPERSE( s, a, b ) >>> ( a ) s( a ) ( b ) 16 | // INTERSPERSE( s, a, b, c ) >>> ( a ) s( a ) ( b ) s( b ) ( c ) 17 | // 18 | // `separators.h` provides macros that evaluate to a constant expression. For 19 | // example, `INTERSPERSE( SEP_AND, ... )` will separate each variable 20 | // argument by `&&`. 21 | #define INTERSPERSE( sep, ... ) \ 22 | MAP( PAREN, sep, __VA_ARGS__ ) 23 | 24 | 25 | #endif // ifndef MACROFUN_INTERSPERSE_H 26 | 27 | -------------------------------------------------------------------------------- /list.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_LIST_H 3 | #define MACROFUN_LIST_H 4 | 5 | 6 | #include "blank.h" // BLANK 7 | #include "paren.h" // UNPAREN 8 | 9 | 10 | // Returns a new list containing all but the first element of the given list 11 | // `xs`. 12 | // 13 | // LIST_REST( () ) >>> () 14 | // LIST_REST( ( a ) ) >>> () 15 | // LIST_REST( ( a, b ) ) >>> ( b ) 16 | // LIST_REST( ( a, b, c ) ) >>> ( b, c ) 17 | // 18 | #define LIST_REST( xs ) \ 19 | LIST_REST_ BLANK ( UNPAREN( xs ) ) 20 | #define LIST_REST_( x, ... ) ( __VA_ARGS__ ) 21 | 22 | 23 | // Returns the first element of the given list `XS`. 24 | // 25 | // LIST_1ST( () ) >>> 26 | // LIST_1ST( ( a ) ) >>> a 27 | // LIST_1ST( ( a, b ) ) >>> a 28 | // LIST_1ST( ( ( a ), b ) ) >>> ( a ) 29 | // 30 | #define LIST_1ST( xs ) \ 31 | LIST_1ST_ BLANK ( UNPAREN( xs ) ) 32 | #define LIST_1ST_( x, ... ) x 33 | 34 | 35 | // Returns the second element of the given list. 36 | // 37 | // LIST_2ND( () ) >>> 38 | // LIST_2ND( ( a ) ) >>> 39 | // LIST_2ND( ( a, b ) ) >>> b 40 | // LIST_2ND( ( a, b, c ) ) >>> b 41 | // LIST_2ND( ( a, ( b ) ) >>> ( b ) 42 | // 43 | #define LIST_2ND( xs ) \ 44 | LIST_2ND_ BLANK ( UNPAREN( xs ) ) 45 | #define LIST_2ND_( x, y, ... ) y 46 | 47 | 48 | #endif // ifndef MACROFUN_LIST_H 49 | 50 | -------------------------------------------------------------------------------- /map-lists.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_MAP_LISTS_H 3 | #define MACROFUN_MAP_LISTS_H 4 | 5 | 6 | #include "blank.h" // BLANK 7 | #include "consume.h" // CONSUME 8 | #include "stop.h" // IF_STOP, STOP 9 | 10 | 11 | // Takes two callable expressions `m` and `sep` and a variable number of 12 | // lists, and consecutively calls `m` with the elements of each list. Each 13 | // `m( ... )` call will be separated by `sep( ... )`, where the arguments to 14 | // `sep` are the elements of the next list that `m` will be called with. 15 | // 16 | // MAP_LISTS( m, s, (a) ) 17 | // >>> m( a ) 18 | // MAP_LISTS( m, s, (a,b), (c) ) 19 | // >>> m( a, b ) s( c ) m( c ) 20 | // MAP_LISTS( m, s, (a,b,c), (d), (e,f) ) 21 | // >>> m( a, b, c ) s( d ) m( d ) s( e, f ) m( e, f ) 22 | // 23 | // `separators.h` provides macros that evaluate to a constant expression. For 24 | // example, `MAP_LISTS( m, SEP_AND, ... )` will separate each resulting `m` 25 | // call by `&&`. 26 | #define MAP_LISTS( m, sep, ... ) \ 27 | MAP_LISTS_EVAL( MAP_LISTS_0( m, sep, __VA_ARGS__, STOP, 0 ) ) 28 | 29 | #define MAP_LISTS_0( m, sep, head, next, ... ) \ 30 | m head \ 31 | IF_STOP( next, CONSUME, MAP_LISTS_1 ) \ 32 | BLANK ( m, sep, next, __VA_ARGS__ ) 33 | 34 | #define MAP_LISTS_1( m, sep, next, ... ) \ 35 | sep next MAP_LISTS_0 BLANK ( m, sep, next, __VA_ARGS__ ) 36 | 37 | 38 | // Causes 256 rounds of evaluation of its arguments. This enables a crude 39 | // form of recursion, with a maximum call-depth of 256. Each recursive macro 40 | // needs to provide its own recursive evaluator, because a recursive 41 | // evaluator can't be used recursively itself. This allows for recursive 42 | // macros to be implemented with other recursive macros. 43 | #define MAP_LISTS_EVAL( ... ) \ 44 | MAP_LISTS_EVAL255( __VA_ARGS__ ) 45 | 46 | #define MAP_LISTS_EVAL255( ... ) \ 47 | MAP_LISTS_EVAL127( MAP_LISTS_EVAL127( __VA_ARGS__ ) ) 48 | #define MAP_LISTS_EVAL127( ... ) \ 49 | MAP_LISTS_EVAL63( MAP_LISTS_EVAL63( __VA_ARGS__ ) ) 50 | #define MAP_LISTS_EVAL63( ... ) \ 51 | MAP_LISTS_EVAL31( MAP_LISTS_EVAL31( __VA_ARGS__ ) ) 52 | #define MAP_LISTS_EVAL31( ... ) \ 53 | MAP_LISTS_EVAL15( MAP_LISTS_EVAL15( __VA_ARGS__ ) ) 54 | #define MAP_LISTS_EVAL15( ... ) \ 55 | MAP_LISTS_EVAL7( MAP_LISTS_EVAL7( __VA_ARGS__ ) ) 56 | #define MAP_LISTS_EVAL7( ... ) \ 57 | MAP_LISTS_EVAL3( MAP_LISTS_EVAL3( __VA_ARGS__ ) ) 58 | #define MAP_LISTS_EVAL3( ... ) \ 59 | MAP_LISTS_EVAL1( MAP_LISTS_EVAL1( __VA_ARGS__ ) ) 60 | #define MAP_LISTS_EVAL1( ... ) \ 61 | __VA_ARGS__ 62 | 63 | 64 | #endif // ifndef MACROFUN_MAP_LISTS_H 65 | 66 | -------------------------------------------------------------------------------- /map.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_MAP_H 3 | #define MACROFUN_MAP_H 4 | 5 | 6 | #include "blank.h" // BLANK 7 | #include "consume.h" // CONSUME 8 | #include "stop.h" // IF_STOP, STOP 9 | 10 | 11 | // Takes two callable expressions `m` and `sep`, and calls `m` with each 12 | // consecutive variable argument, separating each `m( x )` call by 13 | // `sep( y )`, where `y` is the next variable argument after `x`. 14 | // 15 | // MAP( m, s, x ) >>> m( x ) 16 | // MAP( m, s, x, y ) >>> m( x ) s( y ) m( y ) 17 | // MAP( m, s, x, y, z ) >>> m( x ) s( y ) m( y ) s( z ) m( z ) 18 | // 19 | // `separators.h` provides macros that evaluate to a constant expression. For 20 | // example, `MAP( m, SEP_AND, ... )` will separate each resulting `m` call by 21 | // `&&`. 22 | #define MAP( m, sep, ... ) \ 23 | MAP_EVAL( MAP_0( m, sep, __VA_ARGS__, STOP, 0 ) ) 24 | 25 | #define MAP_0( m, sep, head, next, ... ) \ 26 | m( head ) \ 27 | IF_STOP( next, CONSUME, MAP_1 ) \ 28 | BLANK ( m, sep, next, __VA_ARGS__ ) 29 | 30 | #define MAP_1( m, sep, next, ... ) \ 31 | sep( next ) MAP_0 BLANK ( m, sep, next, __VA_ARGS__ ) 32 | 33 | 34 | // Causes 256 rounds of evaluation of its arguments. This enables a crude 35 | // form of recursion, with a maximum call-depth of 256. Each recursive macro 36 | // needs to provide its own recursive evaluator, because a recursive 37 | // evaluator can't be used recursively itself. This allows for recursive 38 | // macros to be implemented with other recursive macros. 39 | #define MAP_EVAL( ... ) MAP_EVAL255( __VA_ARGS__ ) 40 | 41 | #define MAP_EVAL255( ... ) MAP_EVAL127( MAP_EVAL127( __VA_ARGS__ ) ) 42 | #define MAP_EVAL127( ... ) MAP_EVAL63( MAP_EVAL63( __VA_ARGS__ ) ) 43 | #define MAP_EVAL63( ... ) MAP_EVAL31( MAP_EVAL31( __VA_ARGS__ ) ) 44 | #define MAP_EVAL31( ... ) MAP_EVAL15( MAP_EVAL15( __VA_ARGS__ ) ) 45 | #define MAP_EVAL15( ... ) MAP_EVAL7( MAP_EVAL7( __VA_ARGS__ ) ) 46 | #define MAP_EVAL7( ... ) MAP_EVAL3( MAP_EVAL3( __VA_ARGS__ ) ) 47 | #define MAP_EVAL3( ... ) MAP_EVAL1( MAP_EVAL1( __VA_ARGS__ ) ) 48 | #define MAP_EVAL1( ... ) __VA_ARGS__ 49 | 50 | 51 | #endif // ifndef MACROFUN_MAP_H 52 | 53 | -------------------------------------------------------------------------------- /paren.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_PAREN_H 3 | #define MACROFUN_PAREN_H 4 | 5 | 6 | // Surrounds the given arguments with parentheses. 7 | #define PAREN( ... ) \ 8 | ( __VA_ARGS__ ) 9 | 10 | 11 | // Strips the given argument of its outer-most parentheses. 12 | #define UNPAREN( x ) \ 13 | UNPAREN_ x 14 | #define UNPAREN_( ... ) __VA_ARGS__ 15 | 16 | 17 | #endif // ifndef MACROFUN_PAREN_H 18 | 19 | -------------------------------------------------------------------------------- /separators.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_SEPARATORS_H 3 | #define MACROFUN_SEPARATORS_H 4 | 5 | 6 | // You can pass one of these following separator macros as the separator 7 | // argument to `MAP`, `MAP_LISTS` or `INTERSPERSE` to separate each resulting 8 | // expression by a constant expression. Separators have to be provided in 9 | // this format because the simpler approach (i.e. `MAP( m, +, ... )`) won't 10 | // work for commas, and I was keen to provide a uniform interface. Also, that 11 | // approach wouldn't be as flexible or powerful. 12 | // 13 | // MAP( m, SEP_NONE, a, b, c ) >>> m( a ) m( b ) m( c ) 14 | // MAP( m, SEP_COMMA, a, b, c ) >>> m( a ), m( b ), m( c ) 15 | // MAP( m, SEP_AND, a, b, c ) >>> m( a ) && m( b ) && m( c ) 16 | // MAP_LISTS( m, SEP_NONE, (a,b), (c) ) >>> m( a, b ) m( c ) 17 | // MAP_LISTS( m, SEP_OR, (a,b), (c) ) >>> m( a, b ) || m( c ) 18 | // INTERSPERSE( SEP_AND, a, b, c ) >>> ( a ) && ( b ) && ( c ) 19 | // 20 | // Be careful about how you use some of these separators. For example, the 21 | // comparison operators don't work like mathematical notation when they're 22 | // chained: `2 < 3 < 2 == true`. 23 | 24 | #define SEP_NONE( ... ) 25 | #define SEP_COMMA( ... ) , 26 | #define SEP_SEMICOLON( ... ) ; 27 | #define SEP_PLUS( ... ) + 28 | #define SEP_MINUS( ... ) - 29 | #define SEP_TIMES( ... ) * 30 | #define SEP_DIVIDE( ... ) / 31 | #define SEP_MODULO( ... ) % 32 | #define SEP_AND( ... ) && 33 | #define SEP_OR( ... ) || 34 | #define SEP_LT( ... ) < 35 | #define SEP_LE( ... ) <= 36 | #define SEP_EQ( ... ) == 37 | #define SEP_NEQ( ... ) != 38 | #define SEP_GE( ... ) >= 39 | #define SEP_GT( ... ) > 40 | #define SEP_BIT_AND( ... ) & 41 | #define SEP_BIT_OR( ... ) | 42 | #define SEP_BIT_XOR( ... ) ^ 43 | #define SEP_BIT_LSHIFT( ... ) << 44 | #define SEP_BIT_RSHIFT( ... ) >> 45 | #define SEP_ASSIGN( ... ) = 46 | #define SEP_PLUS_ASSIGN( ... ) += 47 | #define SEP_MINUS_ASSIGN( ... ) -= 48 | #define SEP_TIMES_ASSIGN( ... ) *= 49 | #define SEP_DIVIDE_ASSIGN( ... ) /= 50 | #define SEP_MODULO_ASSIGN( ... ) %= 51 | #define SEP_BIT_AND_ASSIGN( ... ) &= 52 | #define SEP_BIT_OR_ASSIGN( ... ) |= 53 | #define SEP_BIT_XOR_ASSIGN( ... ) ^= 54 | #define SEP_BIT_LSHIFT_ASSIGN( ... ) <<= 55 | #define SEP_BIT_RSHIFT_ASSIGN( ... ) >>= 56 | #define SEP_FIELD( ... ) . 57 | #define SEP_DEREF_FIELD( ... ) -> 58 | 59 | 60 | #endif // ifndef MACROFUN_SEPARATORS_H 61 | 62 | -------------------------------------------------------------------------------- /stop-lists.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_STOP_LISTS_H 3 | #define MACROFUN_STOP_LISTS_H 4 | 5 | 6 | #include "foldl.h" // FOLDL 7 | #include "map-lists.h" // MAP_LISTS 8 | #include "paren.h" // UNPAREN 9 | #include "stop.h" // STOP, IF_STOP, IF_STOP_STOP 10 | 11 | 12 | #define LISTS_APPEND_STOPS( ... ) \ 13 | MAP_LISTS( ARGS_TO_STOPPED_LIST, SEP_COMMA, __VA_ARGS__ ) 14 | 15 | // Gives a list containing the given arguments and two `STOP`s. The two 16 | // `STOP`s allow macros working with the list to determine the stopping 17 | // point while avoiding missing argument warnings or errors. 18 | #define ARGS_TO_STOPPED_LIST( ... ) \ 19 | ( __VA_ARGS__, STOP, STOP ) 20 | 21 | 22 | // If the given list contains `STOP`, this evaluates to the given `then`. 23 | // Otherwise, this evaluates to the given `els`. 24 | #define IF_STOP_IN( list, then, els ) \ 25 | IF_STOP( FOLDL( IF_STOP_STOP, 0, UNPAREN( list ) ), then, els ) 26 | 27 | 28 | #endif // ifndef MACROFUN_STOP_LISTS_H 29 | 30 | -------------------------------------------------------------------------------- /stop.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_STOP_H 3 | #define MACROFUN_STOP_H 4 | 5 | 6 | #include "args.h" // ARGS_2ND 7 | #include "blank.h" // BLANK 8 | #include "list.h" // LIST_2ND 9 | 10 | 11 | // The end-sentinel of a series of comma-separated expressions. 12 | #define STOP ((((((())))))) 13 | 14 | 15 | // If `x` is `STOP` (or, really, just begins with as many parentheses as 16 | // `STOP` does), this evaluates to the given `then`. Otherwise, this 17 | // evaluates to the given `els` (else). 18 | #define IF_STOP( x, then, els ) \ 19 | ARGS_2ND BLANK ( COMMA_IF_STOP( x ) then, els, 0 ) 20 | 21 | 22 | // If `x` is `STOP` (or, really, just begins with as many parentheses as 23 | // `STOP` does), this evaluates to `STOP`. Otherwise, this evaluates to 24 | // the given `els`. This can be used with `FOLDL` to reduce a series of 25 | // expressions to `STOP` if any expression was `STOP`. 26 | #define IF_STOP_STOP( x, els ) \ 27 | IF_STOP( x, STOP, els ) 28 | 29 | 30 | // If `x` is `STOP` (or, really, just begins with as many parentheses as 31 | // `STOP` does), this evaluates to `x,`. Otherwise, this evaluates to some 32 | // expression without a comma. This can be used to shuffle the positions of 33 | // arguments. 34 | #define COMMA_IF_STOP( x ) \ 35 | COMMA_IF_STOP_7_0( x ) 36 | 37 | #define COMMA_IF_STOP_7_0( ... ) COMMA_IF_STOP_7_1( __VA_ARGS__, 0 ) 38 | #define COMMA_IF_STOP_7_1( x, ... ) COMMA_IF_STOP_6_0 x 39 | #define COMMA_IF_STOP_6_0( ... ) COMMA_IF_STOP_6_1( __VA_ARGS__, 0 ) 40 | #define COMMA_IF_STOP_6_1( x, ... ) COMMA_IF_STOP_5_0 x 41 | #define COMMA_IF_STOP_5_0( ... ) COMMA_IF_STOP_5_1( __VA_ARGS__, 0 ) 42 | #define COMMA_IF_STOP_5_1( x, ... ) COMMA_IF_STOP_4_0 x 43 | #define COMMA_IF_STOP_4_0( ... ) COMMA_IF_STOP_4_1( __VA_ARGS__, 0 ) 44 | #define COMMA_IF_STOP_4_1( x, ... ) COMMA_IF_STOP_3_0 x 45 | #define COMMA_IF_STOP_3_0( ... ) COMMA_IF_STOP_3_1( __VA_ARGS__, 0 ) 46 | #define COMMA_IF_STOP_3_1( x, ... ) COMMA_IF_STOP_2_0 x 47 | #define COMMA_IF_STOP_2_0( ... ) COMMA_IF_STOP_2_1( __VA_ARGS__, 0 ) 48 | #define COMMA_IF_STOP_2_1( x, ... ) COMMA_IF_STOP_1_0 x 49 | #define COMMA_IF_STOP_1_0( ... ) COMMA_IF_STOP_1_1( __VA_ARGS__, 0 ) 50 | #define COMMA_IF_STOP_1_1( x, ... ) COMMA_IF_STOP_0_0 x 51 | #define COMMA_IF_STOP_0_0( ... ) COMMA_IF_STOP_0_1( __VA_ARGS__, 0 ) 52 | #define COMMA_IF_STOP_0_1( x, ... ) x, 53 | 54 | // Each `_0` macro appends a `0` to the call to the associated `_1` macro, to 55 | // occupy the var-args argument when it would have otherwise been called with 56 | // a single token (this is required for strict ISO standards conformance). 57 | // The `_1` macros will call the following `_0` if their first argument 58 | // begins with parentheses, thereby stripping one layer of parentheses. 59 | 60 | 61 | 62 | // You can use this as the end-sentinel instead, if you want to accept 63 | // `STOP` as a valid argument. 64 | #define STOP2 (STOP) 65 | 66 | 67 | // If the given expression is `STOP2` (or, really, just begins with as many 68 | // parentheses as `STOP2` does), this evaluates to `,`. Otherwise, this 69 | // evaluates to some expression without a comma. This can be used to shuffle 70 | // the positions of arguments. 71 | #define COMMA_IF_STOP2( x ) COMMA_IF_STOP x 72 | 73 | 74 | // If `x` is `STOP2` (or, really, just begins with as many parentheses as 75 | // `STOP2` does), this evaluates to the given `then`. Otherwise, this 76 | // evaluates to the given `els`. 77 | #define IF_STOP2( x, then, els ) \ 78 | LIST_2ND( ( COMMA_IF_STOP2( x ) then, els, 0 ) ) 79 | 80 | 81 | #endif // ifndef MACROFUN_STOP_H 82 | 83 | -------------------------------------------------------------------------------- /tests/foldl.in.c: -------------------------------------------------------------------------------- 1 | #include "foldl.h" 2 | 3 | FOLDL( m, acc, a ) 4 | FOLDL( m, acc, a, b ) 5 | FOLDL( m, acc, a, b, c ) 6 | FOLDL( m, acc, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127 ) 7 | 8 | -------------------------------------------------------------------------------- /tests/foldl.out.c: -------------------------------------------------------------------------------- 1 | m( acc, a ) 2 | m( m( acc, a ), b ) 3 | m( m( m( acc, a ), b ), c ) 4 | m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( m( acc, 0 ), 1 ), 2 ), 3 ), 4 ), 5 ), 6 ), 7 ), 8 ), 9 ), 10 ), 11 ), 12 ), 13 ), 14 ), 15 ), 16 ), 17 ), 18 ), 19 ), 20 ), 21 ), 22 ), 23 ), 24 ), 25 ), 26 ), 27 ), 28 ), 29 ), 30 ), 31 ), 32 ), 33 ), 34 ), 35 ), 36 ), 37 ), 38 ), 39 ), 40 ), 41 ), 42 ), 43 ), 44 ), 45 ), 46 ), 47 ), 48 ), 49 ), 50 ), 51 ), 52 ), 53 ), 54 ), 55 ), 56 ), 57 ), 58 ), 59 ), 60 ), 61 ), 62 ), 63 ), 64 ), 65 ), 66 ), 67 ), 68 ), 69 ), 70 ), 71 ), 72 ), 73 ), 74 ), 75 ), 76 ), 77 ), 78 ), 79 ), 80 ), 81 ), 82 ), 83 ), 84 ), 85 ), 86 ), 87 ), 88 ), 89 ), 90 ), 91 ), 92 ), 93 ), 94 ), 95 ), 96 ), 97 ), 98 ), 99 ), 100 ), 101 ), 102 ), 103 ), 104 ), 105 ), 106 ), 107 ), 108 ), 109 ), 110 ), 111 ), 112 ), 113 ), 114 ), 115 ), 116 ), 117 ), 118 ), 119 ), 120 ), 121 ), 122 ), 123 ), 124 ), 125 ), 126 ), 127 ) 5 | -------------------------------------------------------------------------------- /tests/foldr.in.c: -------------------------------------------------------------------------------- 1 | #include "foldr.h" 2 | 3 | FOLDR( m, acc, a ) 4 | FOLDR( m, acc, a, b ) 5 | FOLDR( m, acc, a, b, c ) 6 | FOLDR( m, acc, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127 ) 7 | 8 | -------------------------------------------------------------------------------- /tests/foldr.out.c: -------------------------------------------------------------------------------- 1 | m( a, acc ) 2 | m( a, m( b, acc ) ) 3 | m( a, m( b, m( c, acc ) ) ) 4 | m( 0, m( 1, m( 2, m( 3, m( 4, m( 5, m( 6, m( 7, m( 8, m( 9, m( 10, m( 11, m( 12, m( 13, m( 14, m( 15, m( 16, m( 17, m( 18, m( 19, m( 20, m( 21, m( 22, m( 23, m( 24, m( 25, m( 26, m( 27, m( 28, m( 29, m( 30, m( 31, m( 32, m( 33, m( 34, m( 35, m( 36, m( 37, m( 38, m( 39, m( 40, m( 41, m( 42, m( 43, m( 44, m( 45, m( 46, m( 47, m( 48, m( 49, m( 50, m( 51, m( 52, m( 53, m( 54, m( 55, m( 56, m( 57, m( 58, m( 59, m( 60, m( 61, m( 62, m( 63, m( 64, m( 65, m( 66, m( 67, m( 68, m( 69, m( 70, m( 71, m( 72, m( 73, m( 74, m( 75, m( 76, m( 77, m( 78, m( 79, m( 80, m( 81, m( 82, m( 83, m( 84, m( 85, m( 86, m( 87, m( 88, m( 89, m( 90, m( 91, m( 92, m( 93, m( 94, m( 95, m( 96, m( 97, m( 98, m( 99, m( 100, m( 101, m( 102, m( 103, m( 104, m( 105, m( 106, m( 107, m( 108, m( 109, m( 110, m( 111, m( 112, m( 113, m( 114, m( 115, m( 116, m( 117, m( 118, m( 119, m( 120, m( 121, m( 122, m( 123, m( 124, m( 125, m( 126, m( 127, acc ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) 5 | -------------------------------------------------------------------------------- /tests/intersperse.in.c: -------------------------------------------------------------------------------- 1 | #include "intersperse.h" 2 | 3 | INTERSPERSE( s, a ) 4 | INTERSPERSE( s, a, b ) 5 | INTERSPERSE( s, a, b, c ) 6 | INTERSPERSE( s, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127 ) 7 | 8 | -------------------------------------------------------------------------------- /tests/intersperse.out.c: -------------------------------------------------------------------------------- 1 | ( a ) 2 | ( a ) s( b ) ( b ) 3 | ( a ) s( b ) ( b ) s( c ) ( c ) 4 | ( 0 ) s( 1 ) ( 1 ) s( 2 ) ( 2 ) s( 3 ) ( 3 ) s( 4 ) ( 4 ) s( 5 ) ( 5 ) s( 6 ) ( 6 ) s( 7 ) ( 7 ) s( 8 ) ( 8 ) s( 9 ) ( 9 ) s( 10 ) ( 10 ) s( 11 ) ( 11 ) s( 12 ) ( 12 ) s( 13 ) ( 13 ) s( 14 ) ( 14 ) s( 15 ) ( 15 ) s( 16 ) ( 16 ) s( 17 ) ( 17 ) s( 18 ) ( 18 ) s( 19 ) ( 19 ) s( 20 ) ( 20 ) s( 21 ) ( 21 ) s( 22 ) ( 22 ) s( 23 ) ( 23 ) s( 24 ) ( 24 ) s( 25 ) ( 25 ) s( 26 ) ( 26 ) s( 27 ) ( 27 ) s( 28 ) ( 28 ) s( 29 ) ( 29 ) s( 30 ) ( 30 ) s( 31 ) ( 31 ) s( 32 ) ( 32 ) s( 33 ) ( 33 ) s( 34 ) ( 34 ) s( 35 ) ( 35 ) s( 36 ) ( 36 ) s( 37 ) ( 37 ) s( 38 ) ( 38 ) s( 39 ) ( 39 ) s( 40 ) ( 40 ) s( 41 ) ( 41 ) s( 42 ) ( 42 ) s( 43 ) ( 43 ) s( 44 ) ( 44 ) s( 45 ) ( 45 ) s( 46 ) ( 46 ) s( 47 ) ( 47 ) s( 48 ) ( 48 ) s( 49 ) ( 49 ) s( 50 ) ( 50 ) s( 51 ) ( 51 ) s( 52 ) ( 52 ) s( 53 ) ( 53 ) s( 54 ) ( 54 ) s( 55 ) ( 55 ) s( 56 ) ( 56 ) s( 57 ) ( 57 ) s( 58 ) ( 58 ) s( 59 ) ( 59 ) s( 60 ) ( 60 ) s( 61 ) ( 61 ) s( 62 ) ( 62 ) s( 63 ) ( 63 ) s( 64 ) ( 64 ) s( 65 ) ( 65 ) s( 66 ) ( 66 ) s( 67 ) ( 67 ) s( 68 ) ( 68 ) s( 69 ) ( 69 ) s( 70 ) ( 70 ) s( 71 ) ( 71 ) s( 72 ) ( 72 ) s( 73 ) ( 73 ) s( 74 ) ( 74 ) s( 75 ) ( 75 ) s( 76 ) ( 76 ) s( 77 ) ( 77 ) s( 78 ) ( 78 ) s( 79 ) ( 79 ) s( 80 ) ( 80 ) s( 81 ) ( 81 ) s( 82 ) ( 82 ) s( 83 ) ( 83 ) s( 84 ) ( 84 ) s( 85 ) ( 85 ) s( 86 ) ( 86 ) s( 87 ) ( 87 ) s( 88 ) ( 88 ) s( 89 ) ( 89 ) s( 90 ) ( 90 ) s( 91 ) ( 91 ) s( 92 ) ( 92 ) s( 93 ) ( 93 ) s( 94 ) ( 94 ) s( 95 ) ( 95 ) s( 96 ) ( 96 ) s( 97 ) ( 97 ) s( 98 ) ( 98 ) s( 99 ) ( 99 ) s( 100 ) ( 100 ) s( 101 ) ( 101 ) s( 102 ) ( 102 ) s( 103 ) ( 103 ) s( 104 ) ( 104 ) s( 105 ) ( 105 ) s( 106 ) ( 106 ) s( 107 ) ( 107 ) s( 108 ) ( 108 ) s( 109 ) ( 109 ) s( 110 ) ( 110 ) s( 111 ) ( 111 ) s( 112 ) ( 112 ) s( 113 ) ( 113 ) s( 114 ) ( 114 ) s( 115 ) ( 115 ) s( 116 ) ( 116 ) s( 117 ) ( 117 ) s( 118 ) ( 118 ) s( 119 ) ( 119 ) s( 120 ) ( 120 ) s( 121 ) ( 121 ) s( 122 ) ( 122 ) s( 123 ) ( 123 ) s( 124 ) ( 124 ) s( 125 ) ( 125 ) s( 126 ) ( 126 ) s( 127 ) ( 127 ) 5 | -------------------------------------------------------------------------------- /tests/map-lists.in.c: -------------------------------------------------------------------------------- 1 | #include "map-lists.h" 2 | 3 | MAP_LISTS( m, s, (a) ) 4 | MAP_LISTS( m, s, (a), (b) ) 5 | MAP_LISTS( m, s, (a), (b), (c) ) 6 | MAP_LISTS( m, s, (a,b) ) 7 | MAP_LISTS( m, s, (a,b), (c,d) ) 8 | MAP_LISTS( m, s, (a,b), (c,d), (e,f) ) 9 | MAP_LISTS( m, s, (a,b,c) ) 10 | MAP_LISTS( m, s, (a,b,c), (d,e,f) ) 11 | MAP_LISTS( m, s, (a,b,c), (d,e,f), (g,h,i) ) 12 | MAP_LISTS( m, s, (a,b), (c,d), (e,f,g) ) 13 | MAP_LISTS( m, s, (a,b,c), (d), (e,f) ) 14 | MAP_LISTS( m, s, (0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14), (15, 16, 17), (18, 19, 20), (21, 22, 23), (24, 25, 26), (27, 28, 29), (30, 31, 32), (33, 34, 35), (36, 37, 38), (39, 40, 41), (42, 43, 44), (45, 46, 47), (48, 49, 50), (51, 52, 53), (54, 55, 56), (57, 58, 59), (60, 61, 62), (63, 64, 65), (66, 67, 68), (69, 70, 71), (72, 73, 74), (75, 76, 77), (78, 79, 80), (81, 82, 83), (84, 85, 86), (87, 88, 89), (90, 91, 92), (93, 94, 95), (96, 97, 98), (99, 100, 101), (102, 103, 104), (105, 106, 107), (108, 109, 110), (111, 112, 113), (114, 115, 116), (117, 118, 119), (120, 121, 122), (123, 124, 125), (126, 127, 128), (129, 130, 131), (132, 133, 134), (135, 136, 137), (138, 139, 140), (141, 142, 143), (144, 145, 146), (147, 148, 149), (150, 151, 152), (153, 154, 155), (156, 157, 158), (159, 160, 161), (162, 163, 164), (165, 166, 167), (168, 169, 170), (171, 172, 173), (174, 175, 176), (177, 178, 179), (180, 181, 182), (183, 184, 185), (186, 187, 188), (189, 190, 191), (192, 193, 194), (195, 196, 197), (198, 199, 200), (201, 202, 203), (204, 205, 206), (207, 208, 209), (210, 211, 212), (213, 214, 215), (216, 217, 218), (219, 220, 221), (222, 223, 224), (225, 226, 227), (228, 229, 230), (231, 232, 233), (234, 235, 236), (237, 238, 239), (240, 241, 242), (243, 244, 245), (246, 247, 248), (249, 250, 251), (252, 253, 254), (255, 256, 257), (258, 259, 260), (261, 262, 263), (264, 265, 266), (267, 268, 269), (270, 271, 272), (273, 274, 275), (276, 277, 278), (279, 280, 281), (282, 283, 284), (285, 286, 287), (288, 289, 290), (291, 292, 293), (294, 295, 296), (297, 298, 299), (300, 301, 302), (303, 304, 305), (306, 307, 308), (309, 310, 311), (312, 313, 314), (315, 316, 317), (318, 319, 320), (321, 322, 323), (324, 325, 326), (327, 328, 329), (330, 331, 332), (333, 334, 335), (336, 337, 338), (339, 340, 341), (342, 343, 344), (345, 346, 347), (348, 349, 350), (351, 352, 353), (354, 355, 356), (357, 358, 359), (360, 361, 362), (363, 364, 365), (366, 367, 368), (369, 370, 371), (372, 373, 374), (375, 376, 377), (378, 379, 380), (381, 382, 383) ) 15 | 16 | -------------------------------------------------------------------------------- /tests/map-lists.out.c: -------------------------------------------------------------------------------- 1 | m (a) 2 | m (a) s (b) m (b) 3 | m (a) s (b) m (b) s (c) m (c) 4 | m (a,b) 5 | m (a,b) s (c,d) m (c,d) 6 | m (a,b) s (c,d) m (c,d) s (e,f) m (e,f) 7 | m (a,b,c) 8 | m (a,b,c) s (d,e,f) m (d,e,f) 9 | m (a,b,c) s (d,e,f) m (d,e,f) s (g,h,i) m (g,h,i) 10 | m (a,b) s (c,d) m (c,d) s (e,f,g) m (e,f,g) 11 | m (a,b,c) s (d) m (d) s (e,f) m (e,f) 12 | m (0, 1, 2) s (3, 4, 5) m (3, 4, 5) s (6, 7, 8) m (6, 7, 8) s (9, 10, 11) m (9, 10, 11) s (12, 13, 14) m (12, 13, 14) s (15, 16, 17) m (15, 16, 17) s (18, 19, 20) m (18, 19, 20) s (21, 22, 23) m (21, 22, 23) s (24, 25, 26) m (24, 25, 26) s (27, 28, 29) m (27, 28, 29) s (30, 31, 32) m (30, 31, 32) s (33, 34, 35) m (33, 34, 35) s (36, 37, 38) m (36, 37, 38) s (39, 40, 41) m (39, 40, 41) s (42, 43, 44) m (42, 43, 44) s (45, 46, 47) m (45, 46, 47) s (48, 49, 50) m (48, 49, 50) s (51, 52, 53) m (51, 52, 53) s (54, 55, 56) m (54, 55, 56) s (57, 58, 59) m (57, 58, 59) s (60, 61, 62) m (60, 61, 62) s (63, 64, 65) m (63, 64, 65) s (66, 67, 68) m (66, 67, 68) s (69, 70, 71) m (69, 70, 71) s (72, 73, 74) m (72, 73, 74) s (75, 76, 77) m (75, 76, 77) s (78, 79, 80) m (78, 79, 80) s (81, 82, 83) m (81, 82, 83) s (84, 85, 86) m (84, 85, 86) s (87, 88, 89) m (87, 88, 89) s (90, 91, 92) m (90, 91, 92) s (93, 94, 95) m (93, 94, 95) s (96, 97, 98) m (96, 97, 98) s (99, 100, 101) m (99, 100, 101) s (102, 103, 104) m (102, 103, 104) s (105, 106, 107) m (105, 106, 107) s (108, 109, 110) m (108, 109, 110) s (111, 112, 113) m (111, 112, 113) s (114, 115, 116) m (114, 115, 116) s (117, 118, 119) m (117, 118, 119) s (120, 121, 122) m (120, 121, 122) s (123, 124, 125) m (123, 124, 125) s (126, 127, 128) m (126, 127, 128) s (129, 130, 131) m (129, 130, 131) s (132, 133, 134) m (132, 133, 134) s (135, 136, 137) m (135, 136, 137) s (138, 139, 140) m (138, 139, 140) s (141, 142, 143) m (141, 142, 143) s (144, 145, 146) m (144, 145, 146) s (147, 148, 149) m (147, 148, 149) s (150, 151, 152) m (150, 151, 152) s (153, 154, 155) m (153, 154, 155) s (156, 157, 158) m (156, 157, 158) s (159, 160, 161) m (159, 160, 161) s (162, 163, 164) m (162, 163, 164) s (165, 166, 167) m (165, 166, 167) s (168, 169, 170) m (168, 169, 170) s (171, 172, 173) m (171, 172, 173) s (174, 175, 176) m (174, 175, 176) s (177, 178, 179) m (177, 178, 179) s (180, 181, 182) m (180, 181, 182) s (183, 184, 185) m (183, 184, 185) s (186, 187, 188) m (186, 187, 188) s (189, 190, 191) m (189, 190, 191) s (192, 193, 194) m (192, 193, 194) s (195, 196, 197) m (195, 196, 197) s (198, 199, 200) m (198, 199, 200) s (201, 202, 203) m (201, 202, 203) s (204, 205, 206) m (204, 205, 206) s (207, 208, 209) m (207, 208, 209) s (210, 211, 212) m (210, 211, 212) s (213, 214, 215) m (213, 214, 215) s (216, 217, 218) m (216, 217, 218) s (219, 220, 221) m (219, 220, 221) s (222, 223, 224) m (222, 223, 224) s (225, 226, 227) m (225, 226, 227) s (228, 229, 230) m (228, 229, 230) s (231, 232, 233) m (231, 232, 233) s (234, 235, 236) m (234, 235, 236) s (237, 238, 239) m (237, 238, 239) s (240, 241, 242) m (240, 241, 242) s (243, 244, 245) m (243, 244, 245) s (246, 247, 248) m (246, 247, 248) s (249, 250, 251) m (249, 250, 251) s (252, 253, 254) m (252, 253, 254) s (255, 256, 257) m (255, 256, 257) s (258, 259, 260) m (258, 259, 260) s (261, 262, 263) m (261, 262, 263) s (264, 265, 266) m (264, 265, 266) s (267, 268, 269) m (267, 268, 269) s (270, 271, 272) m (270, 271, 272) s (273, 274, 275) m (273, 274, 275) s (276, 277, 278) m (276, 277, 278) s (279, 280, 281) m (279, 280, 281) s (282, 283, 284) m (282, 283, 284) s (285, 286, 287) m (285, 286, 287) s (288, 289, 290) m (288, 289, 290) s (291, 292, 293) m (291, 292, 293) s (294, 295, 296) m (294, 295, 296) s (297, 298, 299) m (297, 298, 299) s (300, 301, 302) m (300, 301, 302) s (303, 304, 305) m (303, 304, 305) s (306, 307, 308) m (306, 307, 308) s (309, 310, 311) m (309, 310, 311) s (312, 313, 314) m (312, 313, 314) s (315, 316, 317) m (315, 316, 317) s (318, 319, 320) m (318, 319, 320) s (321, 322, 323) m (321, 322, 323) s (324, 325, 326) m (324, 325, 326) s (327, 328, 329) m (327, 328, 329) s (330, 331, 332) m (330, 331, 332) s (333, 334, 335) m (333, 334, 335) s (336, 337, 338) m (336, 337, 338) s (339, 340, 341) m (339, 340, 341) s (342, 343, 344) m (342, 343, 344) s (345, 346, 347) m (345, 346, 347) s (348, 349, 350) m (348, 349, 350) s (351, 352, 353) m (351, 352, 353) s (354, 355, 356) m (354, 355, 356) s (357, 358, 359) m (357, 358, 359) s (360, 361, 362) m (360, 361, 362) s (363, 364, 365) m (363, 364, 365) s (366, 367, 368) m (366, 367, 368) s (369, 370, 371) m (369, 370, 371) s (372, 373, 374) m (372, 373, 374) s (375, 376, 377) m (375, 376, 377) s (378, 379, 380) m (378, 379, 380) s (381, 382, 383) m (381, 382, 383) 13 | -------------------------------------------------------------------------------- /tests/map.in.c: -------------------------------------------------------------------------------- 1 | 2 | #include "map.h" 3 | 4 | MAP( m, s, x ) 5 | MAP( m, s, x, y ) 6 | MAP( m, s, x, y, z ) 7 | MAP( m, s, w, ((((((x + (y))))))), z ) 8 | MAP( m, s, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127 ) 9 | 10 | -------------------------------------------------------------------------------- /tests/map.out.c: -------------------------------------------------------------------------------- 1 | m( x ) 2 | m( x ) s( y ) m( y ) 3 | m( x ) s( y ) m( y ) s( z ) m( z ) 4 | m( w ) s( ((((((x + (y))))))) ) m( ((((((x + (y))))))) ) s( z ) m( z ) 5 | m( 0 ) s( 1 ) m( 1 ) s( 2 ) m( 2 ) s( 3 ) m( 3 ) s( 4 ) m( 4 ) s( 5 ) m( 5 ) s( 6 ) m( 6 ) s( 7 ) m( 7 ) s( 8 ) m( 8 ) s( 9 ) m( 9 ) s( 10 ) m( 10 ) s( 11 ) m( 11 ) s( 12 ) m( 12 ) s( 13 ) m( 13 ) s( 14 ) m( 14 ) s( 15 ) m( 15 ) s( 16 ) m( 16 ) s( 17 ) m( 17 ) s( 18 ) m( 18 ) s( 19 ) m( 19 ) s( 20 ) m( 20 ) s( 21 ) m( 21 ) s( 22 ) m( 22 ) s( 23 ) m( 23 ) s( 24 ) m( 24 ) s( 25 ) m( 25 ) s( 26 ) m( 26 ) s( 27 ) m( 27 ) s( 28 ) m( 28 ) s( 29 ) m( 29 ) s( 30 ) m( 30 ) s( 31 ) m( 31 ) s( 32 ) m( 32 ) s( 33 ) m( 33 ) s( 34 ) m( 34 ) s( 35 ) m( 35 ) s( 36 ) m( 36 ) s( 37 ) m( 37 ) s( 38 ) m( 38 ) s( 39 ) m( 39 ) s( 40 ) m( 40 ) s( 41 ) m( 41 ) s( 42 ) m( 42 ) s( 43 ) m( 43 ) s( 44 ) m( 44 ) s( 45 ) m( 45 ) s( 46 ) m( 46 ) s( 47 ) m( 47 ) s( 48 ) m( 48 ) s( 49 ) m( 49 ) s( 50 ) m( 50 ) s( 51 ) m( 51 ) s( 52 ) m( 52 ) s( 53 ) m( 53 ) s( 54 ) m( 54 ) s( 55 ) m( 55 ) s( 56 ) m( 56 ) s( 57 ) m( 57 ) s( 58 ) m( 58 ) s( 59 ) m( 59 ) s( 60 ) m( 60 ) s( 61 ) m( 61 ) s( 62 ) m( 62 ) s( 63 ) m( 63 ) s( 64 ) m( 64 ) s( 65 ) m( 65 ) s( 66 ) m( 66 ) s( 67 ) m( 67 ) s( 68 ) m( 68 ) s( 69 ) m( 69 ) s( 70 ) m( 70 ) s( 71 ) m( 71 ) s( 72 ) m( 72 ) s( 73 ) m( 73 ) s( 74 ) m( 74 ) s( 75 ) m( 75 ) s( 76 ) m( 76 ) s( 77 ) m( 77 ) s( 78 ) m( 78 ) s( 79 ) m( 79 ) s( 80 ) m( 80 ) s( 81 ) m( 81 ) s( 82 ) m( 82 ) s( 83 ) m( 83 ) s( 84 ) m( 84 ) s( 85 ) m( 85 ) s( 86 ) m( 86 ) s( 87 ) m( 87 ) s( 88 ) m( 88 ) s( 89 ) m( 89 ) s( 90 ) m( 90 ) s( 91 ) m( 91 ) s( 92 ) m( 92 ) s( 93 ) m( 93 ) s( 94 ) m( 94 ) s( 95 ) m( 95 ) s( 96 ) m( 96 ) s( 97 ) m( 97 ) s( 98 ) m( 98 ) s( 99 ) m( 99 ) s( 100 ) m( 100 ) s( 101 ) m( 101 ) s( 102 ) m( 102 ) s( 103 ) m( 103 ) s( 104 ) m( 104 ) s( 105 ) m( 105 ) s( 106 ) m( 106 ) s( 107 ) m( 107 ) s( 108 ) m( 108 ) s( 109 ) m( 109 ) s( 110 ) m( 110 ) s( 111 ) m( 111 ) s( 112 ) m( 112 ) s( 113 ) m( 113 ) s( 114 ) m( 114 ) s( 115 ) m( 115 ) s( 116 ) m( 116 ) s( 117 ) m( 117 ) s( 118 ) m( 118 ) s( 119 ) m( 119 ) s( 120 ) m( 120 ) s( 121 ) m( 121 ) s( 122 ) m( 122 ) s( 123 ) m( 123 ) s( 124 ) m( 124 ) s( 125 ) m( 125 ) s( 126 ) m( 126 ) s( 127 ) m( 127 ) 6 | -------------------------------------------------------------------------------- /tests/run.bash: -------------------------------------------------------------------------------- 1 | #!/bin/env bash 2 | 3 | 4 | set -o errexit 5 | set -o pipefail 6 | set -o nounset 7 | 8 | 9 | main() { 10 | local testdir="$(dirname $(readlink --canonicalize "$0"))" 11 | local nfails=0 12 | for f in "$testdir"/*.in.c; do 13 | local f_basename="$(basename $f)" 14 | local testname="${f_basename%.in.c}" 15 | if ! diff --ignore-blank-lines \ 16 | <(gcc -E -std=c11 -I"$testdir/.." -Wall -P "$f") \ 17 | "${f%.in.c}".out.c; then 18 | echo "Fail: $testname" 19 | (( nfails += 1 )) 20 | else 21 | echo "Pass: $testname" 22 | fi 23 | done 24 | exit $nfails 25 | } 26 | 27 | 28 | main "$@" 29 | 30 | -------------------------------------------------------------------------------- /tests/zip-repeat.in.c: -------------------------------------------------------------------------------- 1 | #include "zip-repeat.h" 2 | 3 | ZIP_REPEAT( (), () ) 4 | ZIP_REPEAT( (), (), () ) 5 | ZIP_REPEAT( (), (a) ) 6 | ZIP_REPEAT( (), (a), (b) ) 7 | ZIP_REPEAT( (), (a,b) ) 8 | ZIP_REPEAT( (), (a,b), (c,d) ) 9 | ZIP_REPEAT( (), (a), (b,c) ) 10 | ZIP_REPEAT( (), (a,b), (c) ) 11 | 12 | ZIP_REPEAT( (a), () ) 13 | ZIP_REPEAT( (a), (), () ) 14 | ZIP_REPEAT( (a), (b) ) 15 | ZIP_REPEAT( (a), (b), (c) ) 16 | ZIP_REPEAT( (a), (b,c) ) 17 | ZIP_REPEAT( (a), (b,c), (d,e) ) 18 | ZIP_REPEAT( (a), (b), (c,d) ) 19 | ZIP_REPEAT( (a), (b,c), (d) ) 20 | 21 | ZIP_REPEAT( (a,b), () ) 22 | ZIP_REPEAT( (a,b), (), () ) 23 | ZIP_REPEAT( (a,b), (c) ) 24 | ZIP_REPEAT( (a,b), (c), (d) ) 25 | ZIP_REPEAT( (a,b), (c,d) ) 26 | ZIP_REPEAT( (a,b), (c,d), (e,f) ) 27 | ZIP_REPEAT( (a,b), (c), (d,e) ) 28 | ZIP_REPEAT( (a,b), (c,d), (e) ) 29 | 30 | ZIP_REPEAT( (a), (b), (c,d,e), (f,g) ) 31 | ZIP_REPEAT( (a,b), (c), (d,e,f), (g,h) ) 32 | ZIP_REPEAT( (a), (b,c), (d,e,f), (g,h) ) 33 | 34 | ZIP_REPEAT( (a,b), (c,d), (e,f,g), (h,i) ) 35 | 36 | ZIP_REPEAT( (0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14), (15, 16, 17), (18, 19, 20), (21, 22, 23), (24, 25, 26), (27, 28, 29), (30, 31, 32), (33, 34, 35), (36, 37, 38), (39, 40, 41), (42, 43, 44), (45, 46, 47), (48, 49, 50), (51, 52, 53), (54, 55, 56), (57, 58, 59), (60, 61, 62), (63, 64, 65), (66, 67, 68), (69, 70, 71), (72, 73, 74), (75, 76, 77), (78, 79, 80), (81, 82, 83), (84, 85, 86), (87, 88, 89), (90, 91, 92), (93, 94, 95), (96, 97, 98), (99, 100, 101), (102, 103, 104), (105, 106, 107), (108, 109, 110), (111, 112, 113), (114, 115, 116), (117, 118, 119), (120, 121, 122), (123, 124, 125), (126, 127, 128), (129, 130, 131), (132, 133, 134), (135, 136, 137), (138, 139, 140), (141, 142, 143), (144, 145, 146), (147, 148, 149), (150, 151, 152), (153, 154, 155), (156, 157, 158), (159, 160, 161), (162, 163, 164), (165, 166, 167), (168, 169, 170), (171, 172, 173), (174, 175, 176), (177, 178, 179), (180, 181, 182), (183, 184, 185), (186, 187, 188), (189, 190, 191), (192, 193, 194), (195, 196, 197), (198, 199, 200), (201, 202, 203), (204, 205, 206), (207, 208, 209), (210, 211, 212), (213, 214, 215), (216, 217, 218), (219, 220, 221), (222, 223, 224), (225, 226, 227), (228, 229, 230), (231, 232, 233), (234, 235, 236), (237, 238, 239), (240, 241, 242), (243, 244, 245), (246, 247, 248), (249, 250, 251), (252, 253, 254), (255, 256, 257), (258, 259, 260), (261, 262, 263), (264, 265, 266), (267, 268, 269), (270, 271, 272), (273, 274, 275), (276, 277, 278), (279, 280, 281), (282, 283, 284), (285, 286, 287), (288, 289, 290), (291, 292, 293), (294, 295, 296), (297, 298, 299), (300, 301, 302), (303, 304, 305), (306, 307, 308), (309, 310, 311), (312, 313, 314), (315, 316, 317), (318, 319, 320), (321, 322, 323), (324, 325, 326), (327, 328, 329), (330, 331, 332), (333, 334, 335), (336, 337, 338), (339, 340, 341), (342, 343, 344), (345, 346, 347), (348, 349, 350), (351, 352, 353), (354, 355, 356), (357, 358, 359), (360, 361, 362), (363, 364, 365), (366, 367, 368), (369, 370, 371), (372, 373, 374), (375, 376, 377), (378, 379, 380), (381, 382, 383), (384, 385, 386) ) 37 | 38 | -------------------------------------------------------------------------------- /tests/zip-repeat.out.c: -------------------------------------------------------------------------------- 1 | ( , ) 2 | ( , , ) 3 | ( , a ) 4 | ( , a , b ) 5 | ( , a ) , ( , b ) 6 | ( , a , c ) , ( , b , d ) 7 | ( , a , b ) 8 | ( , a , c ) 9 | ( a, ) 10 | ( a, , ) 11 | ( a, b ) 12 | ( a, b , c ) 13 | ( a, b ) , ( a, c ) 14 | ( a, b , d ) , ( a, c , e ) 15 | ( a, b , c ) 16 | ( a, b , d ) 17 | ( a,b, ) 18 | ( a,b, , ) 19 | ( a,b, c ) 20 | ( a,b, c , d ) 21 | ( a,b, c ) , ( a,b, d ) 22 | ( a,b, c , e ) , ( a,b, d , f ) 23 | ( a,b, c , d ) 24 | ( a,b, c , e ) 25 | ( a, b , c , f ) 26 | ( a,b, c , d , g ) 27 | ( a, b , d , g ) , ( a, c , e , h ) 28 | ( a,b, c , e , h ) , ( a,b, d , f , i ) 29 | ( 0, 1, 2, 3 , 6 , 9 , 12 , 15 , 18 , 21 , 24 , 27 , 30 , 33 , 36 , 39 , 42 , 45 , 48 , 51 , 54 , 57 , 60 , 63 , 66 , 69 , 72 , 75 , 78 , 81 , 84 , 87 , 90 , 93 , 96 , 99 , 102 , 105 , 108 , 111 , 114 , 117 , 120 , 123 , 126 , 129 , 132 , 135 , 138 , 141 , 144 , 147 , 150 , 153 , 156 , 159 , 162 , 165 , 168 , 171 , 174 , 177 , 180 , 183 , 186 , 189 , 192 , 195 , 198 , 201 , 204 , 207 , 210 , 213 , 216 , 219 , 222 , 225 , 228 , 231 , 234 , 237 , 240 , 243 , 246 , 249 , 252 , 255 , 258 , 261 , 264 , 267 , 270 , 273 , 276 , 279 , 282 , 285 , 288 , 291 , 294 , 297 , 300 , 303 , 306 , 309 , 312 , 315 , 318 , 321 , 324 , 327 , 330 , 333 , 336 , 339 , 342 , 345 , 348 , 351 , 354 , 357 , 360 , 363 , 366 , 369 , 372 , 375 , 378 , 381 , 384 ) , ( 0, 1, 2, 4 , 7 , 10 , 13 , 16 , 19 , 22 , 25 , 28 , 31 , 34 , 37 , 40 , 43 , 46 , 49 , 52 , 55 , 58 , 61 , 64 , 67 , 70 , 73 , 76 , 79 , 82 , 85 , 88 , 91 , 94 , 97 , 100 , 103 , 106 , 109 , 112 , 115 , 118 , 121 , 124 , 127 , 130 , 133 , 136 , 139 , 142 , 145 , 148 , 151 , 154 , 157 , 160 , 163 , 166 , 169 , 172 , 175 , 178 , 181 , 184 , 187 , 190 , 193 , 196 , 199 , 202 , 205 , 208 , 211 , 214 , 217 , 220 , 223 , 226 , 229 , 232 , 235 , 238 , 241 , 244 , 247 , 250 , 253 , 256 , 259 , 262 , 265 , 268 , 271 , 274 , 277 , 280 , 283 , 286 , 289 , 292 , 295 , 298 , 301 , 304 , 307 , 310 , 313 , 316 , 319 , 322 , 325 , 328 , 331 , 334 , 337 , 340 , 343 , 346 , 349 , 352 , 355 , 358 , 361 , 364 , 367 , 370 , 373 , 376 , 379 , 382 , 385 ) , ( 0, 1, 2, 5 , 8 , 11 , 14 , 17 , 20 , 23 , 26 , 29 , 32 , 35 , 38 , 41 , 44 , 47 , 50 , 53 , 56 , 59 , 62 , 65 , 68 , 71 , 74 , 77 , 80 , 83 , 86 , 89 , 92 , 95 , 98 , 101 , 104 , 107 , 110 , 113 , 116 , 119 , 122 , 125 , 128 , 131 , 134 , 137 , 140 , 143 , 146 , 149 , 152 , 155 , 158 , 161 , 164 , 167 , 170 , 173 , 176 , 179 , 182 , 185 , 188 , 191 , 194 , 197 , 200 , 203 , 206 , 209 , 212 , 215 , 218 , 221 , 224 , 227 , 230 , 233 , 236 , 239 , 242 , 245 , 248 , 251 , 254 , 257 , 260 , 263 , 266 , 269 , 272 , 275 , 278 , 281 , 284 , 287 , 290 , 293 , 296 , 299 , 302 , 305 , 308 , 311 , 314 , 317 , 320 , 323 , 326 , 329 , 332 , 335 , 338 , 341 , 344 , 347 , 350 , 353 , 356 , 359 , 362 , 365 , 368 , 371 , 374 , 377 , 380 , 383 , 386 ) 30 | -------------------------------------------------------------------------------- /tests/zip.in.c: -------------------------------------------------------------------------------- 1 | #include "zip.h" 2 | 3 | ZIP( () ) 4 | ZIP( (), () ) 5 | ZIP( (), (), () ) 6 | 7 | ZIP( (a) ) 8 | ZIP( (a), (b) ) 9 | ZIP( (a), (b), (c) ) 10 | 11 | ZIP( (a,b) ) 12 | ZIP( (a,b), (c,d) ) 13 | ZIP( (a,b), (c,d), (e,f) ) 14 | 15 | ZIP( (a,b,c) ) 16 | ZIP( (a,b,c), (d,e,f) ) 17 | ZIP( (a,b,c), (d,e,f), (g,h,i) ) 18 | 19 | ZIP( (a), () ) 20 | ZIP( (), (a) ) 21 | ZIP( (a,b), () ) 22 | ZIP( (), (a,b) ) 23 | 24 | ZIP( (a), (b,c) ) 25 | ZIP( (a,b), (c) ) 26 | ZIP( (a,b), (c), (d) ) 27 | ZIP( (a), (b,c), (d) ) 28 | ZIP( (a), (b), (c,d) ) 29 | ZIP( (a), (b,c), (d,e) ) 30 | ZIP( (a,b), (c), (d,e) ) 31 | ZIP( (a,b), (c,d), (e) ) 32 | 33 | ZIP( (a,b), (c,d,e), (f,g) ) 34 | ZIP( (a,b), (c,d,e,f), (g,h,i), (j,k) ) 35 | 36 | ZIP( (0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14), (15, 16, 17), (18, 19, 20), (21, 22, 23), (24, 25, 26), (27, 28, 29), (30, 31, 32), (33, 34, 35), (36, 37, 38), (39, 40, 41), (42, 43, 44), (45, 46, 47), (48, 49, 50), (51, 52, 53), (54, 55, 56), (57, 58, 59), (60, 61, 62), (63, 64, 65), (66, 67, 68), (69, 70, 71), (72, 73, 74), (75, 76, 77), (78, 79, 80), (81, 82, 83), (84, 85, 86), (87, 88, 89), (90, 91, 92), (93, 94, 95), (96, 97, 98), (99, 100, 101), (102, 103, 104), (105, 106, 107), (108, 109, 110), (111, 112, 113), (114, 115, 116), (117, 118, 119), (120, 121, 122), (123, 124, 125), (126, 127, 128), (129, 130, 131), (132, 133, 134), (135, 136, 137), (138, 139, 140), (141, 142, 143), (144, 145, 146), (147, 148, 149), (150, 151, 152), (153, 154, 155), (156, 157, 158), (159, 160, 161), (162, 163, 164), (165, 166, 167), (168, 169, 170), (171, 172, 173), (174, 175, 176), (177, 178, 179), (180, 181, 182), (183, 184, 185), (186, 187, 188), (189, 190, 191), (192, 193, 194), (195, 196, 197), (198, 199, 200), (201, 202, 203), (204, 205, 206), (207, 208, 209), (210, 211, 212), (213, 214, 215), (216, 217, 218), (219, 220, 221), (222, 223, 224), (225, 226, 227), (228, 229, 230), (231, 232, 233), (234, 235, 236), (237, 238, 239), (240, 241, 242), (243, 244, 245), (246, 247, 248), (249, 250, 251), (252, 253, 254), (255, 256, 257), (258, 259, 260), (261, 262, 263), (264, 265, 266), (267, 268, 269), (270, 271, 272), (273, 274, 275), (276, 277, 278), (279, 280, 281), (282, 283, 284), (285, 286, 287), (288, 289, 290), (291, 292, 293), (294, 295, 296), (297, 298, 299), (300, 301, 302), (303, 304, 305), (306, 307, 308), (309, 310, 311), (312, 313, 314), (315, 316, 317), (318, 319, 320), (321, 322, 323), (324, 325, 326), (327, 328, 329), (330, 331, 332), (333, 334, 335), (336, 337, 338), (339, 340, 341), (342, 343, 344), (345, 346, 347), (348, 349, 350), (351, 352, 353), (354, 355, 356), (357, 358, 359), (360, 361, 362), (363, 364, 365), (366, 367, 368), (369, 370, 371), (372, 373, 374), (375, 376, 377), (378, 379, 380), (381, 382, 383) ) 37 | 38 | -------------------------------------------------------------------------------- /tests/zip.out.c: -------------------------------------------------------------------------------- 1 | ( ) 2 | ( , ) 3 | ( , , ) 4 | ( a ) 5 | ( a , b ) 6 | ( a , b , c ) 7 | ( a ) , ( b ) 8 | ( a , c ) , ( b , d ) 9 | ( a , c , e ) , ( b , d , f ) 10 | ( a ) , ( b ) , ( c ) 11 | ( a , d ) , ( b , e ) , ( c , f ) 12 | ( a , d , g ) , ( b , e , h ) , ( c , f , i ) 13 | ( a , ) 14 | ( , a ) 15 | ( a , ) 16 | ( , a ) 17 | ( a , b ) 18 | ( a , c ) 19 | ( a , c , d ) 20 | ( a , b , d ) 21 | ( a , b , c ) 22 | ( a , b , d ) 23 | ( a , c , d ) 24 | ( a , c , e ) 25 | ( a , c , f ) , ( b , d , g ) 26 | ( a , c , g , j ) , ( b , d , h , k ) 27 | ( 0 , 3 , 6 , 9 , 12 , 15 , 18 , 21 , 24 , 27 , 30 , 33 , 36 , 39 , 42 , 45 , 48 , 51 , 54 , 57 , 60 , 63 , 66 , 69 , 72 , 75 , 78 , 81 , 84 , 87 , 90 , 93 , 96 , 99 , 102 , 105 , 108 , 111 , 114 , 117 , 120 , 123 , 126 , 129 , 132 , 135 , 138 , 141 , 144 , 147 , 150 , 153 , 156 , 159 , 162 , 165 , 168 , 171 , 174 , 177 , 180 , 183 , 186 , 189 , 192 , 195 , 198 , 201 , 204 , 207 , 210 , 213 , 216 , 219 , 222 , 225 , 228 , 231 , 234 , 237 , 240 , 243 , 246 , 249 , 252 , 255 , 258 , 261 , 264 , 267 , 270 , 273 , 276 , 279 , 282 , 285 , 288 , 291 , 294 , 297 , 300 , 303 , 306 , 309 , 312 , 315 , 318 , 321 , 324 , 327 , 330 , 333 , 336 , 339 , 342 , 345 , 348 , 351 , 354 , 357 , 360 , 363 , 366 , 369 , 372 , 375 , 378 , 381 ) , ( 1 , 4 , 7 , 10 , 13 , 16 , 19 , 22 , 25 , 28 , 31 , 34 , 37 , 40 , 43 , 46 , 49 , 52 , 55 , 58 , 61 , 64 , 67 , 70 , 73 , 76 , 79 , 82 , 85 , 88 , 91 , 94 , 97 , 100 , 103 , 106 , 109 , 112 , 115 , 118 , 121 , 124 , 127 , 130 , 133 , 136 , 139 , 142 , 145 , 148 , 151 , 154 , 157 , 160 , 163 , 166 , 169 , 172 , 175 , 178 , 181 , 184 , 187 , 190 , 193 , 196 , 199 , 202 , 205 , 208 , 211 , 214 , 217 , 220 , 223 , 226 , 229 , 232 , 235 , 238 , 241 , 244 , 247 , 250 , 253 , 256 , 259 , 262 , 265 , 268 , 271 , 274 , 277 , 280 , 283 , 286 , 289 , 292 , 295 , 298 , 301 , 304 , 307 , 310 , 313 , 316 , 319 , 322 , 325 , 328 , 331 , 334 , 337 , 340 , 343 , 346 , 349 , 352 , 355 , 358 , 361 , 364 , 367 , 370 , 373 , 376 , 379 , 382 ) , ( 2 , 5 , 8 , 11 , 14 , 17 , 20 , 23 , 26 , 29 , 32 , 35 , 38 , 41 , 44 , 47 , 50 , 53 , 56 , 59 , 62 , 65 , 68 , 71 , 74 , 77 , 80 , 83 , 86 , 89 , 92 , 95 , 98 , 101 , 104 , 107 , 110 , 113 , 116 , 119 , 122 , 125 , 128 , 131 , 134 , 137 , 140 , 143 , 146 , 149 , 152 , 155 , 158 , 161 , 164 , 167 , 170 , 173 , 176 , 179 , 182 , 185 , 188 , 191 , 194 , 197 , 200 , 203 , 206 , 209 , 212 , 215 , 218 , 221 , 224 , 227 , 230 , 233 , 236 , 239 , 242 , 245 , 248 , 251 , 254 , 257 , 260 , 263 , 266 , 269 , 272 , 275 , 278 , 281 , 284 , 287 , 290 , 293 , 296 , 299 , 302 , 305 , 308 , 311 , 314 , 317 , 320 , 323 , 326 , 329 , 332 , 335 , 338 , 341 , 344 , 347 , 350 , 353 , 356 , 359 , 362 , 365 , 368 , 371 , 374 , 377 , 380 , 383 ) 28 | -------------------------------------------------------------------------------- /zip-repeat.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_ZIP_REPEAT_H 3 | #define MACROFUN_ZIP_REPEAT_H 4 | 5 | 6 | #include "args.h" // ARGS_1ST, ARGS_2ND, ARGS_REST_TO_LIST 7 | #include "blank.h" // BLANK 8 | #include "consume.h" // CONSUME 9 | #include "map-lists.h" // MAP_LISTS 10 | #include "paren.h" // UNPAREN 11 | #include "separators.h" // SEP_COMMA 12 | #include "stop-lists.h" // LISTS_APPEND_STOPS, IF_STOP_IN 13 | 14 | 15 | // Takes a list containing `x` elements, and `n` following lists, and 16 | // returns `m` lists of `x + n` elements, where `m` is the shortest 17 | // length of all of the `n` lists. The `i`th list of those `m` returned 18 | // lists will consist of the `x` elements from the first given list, and 19 | // the `i`th elements in each of the `n` given lists. 20 | // 21 | // A list is a series of comma-separated expressions surrounded by 22 | // parentheses, like `(1, 2, 3)`. 23 | // 24 | // ZIP_REPEAT( (), (a), (b) ) >>> (,a,b) 25 | // ZIP_REPEAT( (a), (b,c), (d,e) ) >>> (a,b,d), (a,c,e) 26 | // ZIP_REPEAT( (a), (b), (c,d) ) >>> (a,b,c) 27 | // ZIP_REPEAT( (a,b), (), () ) >>> (a,b,,) 28 | // ZIP_REPEAT( (a,b), (c,d), (e,f) ) >>> (a,b,c,e), (a,b,d,f) 29 | // ZIP_REPEAT( (a,b), (c), (d,e) ) >>> (a,b,c,d) 30 | // ZIP_REPEAT( (a), (b), (c,d,e), (f,g) ) >>> (a,b,c,f) 31 | // ZIP_REPEAT( (a,b), (c), (d,e,f), (g,h) ) >>> (a,b,c,d,g) 32 | // ZIP_REPEAT( (a), (b,c), (d,e,f), (g,h) ) >>> (a,b,d,g), (a,c,e,h) 33 | // ZIP_REPEAT( (a,b), (c,d), (e,f,g), (h,i) ) 34 | // >>> (a,b,c,e,h), (a,b,d,f,i) 35 | // 36 | #define ZIP_REPEAT( xs, ... ) \ 37 | ZIP_REPEAT_EVAL( ZIP_REPEAT_0( xs, LISTS_APPEND_STOPS( __VA_ARGS__ ) ) ) 38 | 39 | #define ZIP_REPEAT_0( xs, ... ) \ 40 | ( UNPAREN( xs ), MAP_LISTS( ARGS_1ST, SEP_COMMA, __VA_ARGS__ ) ) \ 41 | IF_STOP_IN( ( MAP_LISTS( ARGS_2ND, SEP_COMMA, __VA_ARGS__ ) ), \ 42 | CONSUME, \ 43 | ZIP_REPEAT_1 ) \ 44 | BLANK ( xs, MAP_LISTS( ARGS_REST_TO_LIST, SEP_COMMA, __VA_ARGS__ ) ) 45 | 46 | #define ZIP_REPEAT_1( ... ) \ 47 | , ZIP_REPEAT_0 BLANK ( __VA_ARGS__ ) 48 | 49 | 50 | // Causes 256 rounds of evaluation of its arguments. This enables a crude 51 | // form of recursion, with a maximum call-depth of 256. Each recursive macro 52 | // needs to provide its own recursive evaluator, because a recursive 53 | // evaluator can't be used recursively itself. This allows for recursive 54 | // macros to be implemented with other recursive macros. 55 | #define ZIP_REPEAT_EVAL( ... ) \ 56 | ZIP_REPEAT_EVAL255( __VA_ARGS__ ) 57 | 58 | #define ZIP_REPEAT_EVAL255( ... ) \ 59 | ZIP_REPEAT_EVAL127( ZIP_REPEAT_EVAL127( __VA_ARGS__ ) ) 60 | #define ZIP_REPEAT_EVAL127( ... ) \ 61 | ZIP_REPEAT_EVAL63( ZIP_REPEAT_EVAL63( __VA_ARGS__ ) ) 62 | #define ZIP_REPEAT_EVAL63( ... ) \ 63 | ZIP_REPEAT_EVAL31( ZIP_REPEAT_EVAL31( __VA_ARGS__ ) ) 64 | #define ZIP_REPEAT_EVAL31( ... ) \ 65 | ZIP_REPEAT_EVAL15( ZIP_REPEAT_EVAL15( __VA_ARGS__ ) ) 66 | #define ZIP_REPEAT_EVAL15( ... ) \ 67 | ZIP_REPEAT_EVAL7( ZIP_REPEAT_EVAL7( __VA_ARGS__ ) ) 68 | #define ZIP_REPEAT_EVAL7( ... ) \ 69 | ZIP_REPEAT_EVAL3( ZIP_REPEAT_EVAL3( __VA_ARGS__ ) ) 70 | #define ZIP_REPEAT_EVAL3( ... ) \ 71 | ZIP_REPEAT_EVAL1( ZIP_REPEAT_EVAL1( __VA_ARGS__ ) ) 72 | #define ZIP_REPEAT_EVAL1( ... ) \ 73 | __VA_ARGS__ 74 | 75 | 76 | #endif // ifndef MACROFUN_ZIP_REPEAT_H 77 | 78 | -------------------------------------------------------------------------------- /zip.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MACROFUN_ZIP_H 3 | #define MACROFUN_ZIP_H 4 | 5 | 6 | #include "args.h" // ARGS_1ST, ARGS_2ND, ARGS_REST_TO_LIST 7 | #include "blank.h" // BLANK 8 | #include "consume.h" // CONSUME 9 | #include "map-lists.h" // MAP_LISTS 10 | #include "separators.h" // SEP_COMMA 11 | #include "stop-lists.h" // LISTS_APPEND_STOPS, IF_STOP_IN 12 | 13 | 14 | // Takes `n` lists, and returns `m` lists of `n` elements, where `m` is 15 | // the shortest length of all of the given lists. The `i`th list of 16 | // those `m` returned lists will consist of the `i`th elements in each 17 | // of the `n` given lists. 18 | // 19 | // A list is a series of comma-separated expressions surrounded by 20 | // parentheses, like `(1, 2, 3)`. 21 | // 22 | // ZIP( (a) ) >>> (a) 23 | // ZIP( (a), (b), (c) ) >>> (a,b,c) 24 | // ZIP( (a,b), (c,d) ) >>> (a,c), (b,d) 25 | // ZIP( (a,b,c), (d,e,f), (g,h,i) ) >>> (a,d,g), (b,e,h) (c,f,i) 26 | // ZIP( (a,b), () ) >>> (a,) 27 | // ZIP( (a,b), (c) ) >>> (a,c) 28 | // ZIP( (a), (b,c), (d) ) >>> (a,b,d) 29 | // ZIP( (a,b), (c,d,e), (f,g) ) >>> (a,c,f), (b,d,g) 30 | // ZIP( (a,b), (c,d,e,f), (g,h,i), (j,k) ) >>> (a,c,g,j), (b,d,h,k) 31 | // 32 | #define ZIP( ... ) \ 33 | ZIP_EVAL( ZIP_0( LISTS_APPEND_STOPS( __VA_ARGS__ ) ) ) 34 | 35 | 36 | #define ZIP_0( ... ) \ 37 | ( MAP_LISTS( ARGS_1ST, SEP_COMMA, __VA_ARGS__ ) ) \ 38 | IF_STOP_IN( ( MAP_LISTS( ARGS_2ND, SEP_COMMA, __VA_ARGS__ ) ), \ 39 | CONSUME, \ 40 | ZIP_1 ) \ 41 | BLANK ( MAP_LISTS( ARGS_REST_TO_LIST, SEP_COMMA, __VA_ARGS__ ) ) 42 | 43 | #define ZIP_1( ... ) \ 44 | , ZIP_0 BLANK ( __VA_ARGS__ ) 45 | 46 | 47 | // Causes 256 rounds of evaluation of its arguments. This enables a crude 48 | // form of recursion, with a maximum call-depth of 256. Each recursive macro 49 | // needs to provide its own recursive evaluator, because a recursive 50 | // evaluator can't be used recursively itself. This allows for recursive 51 | // macros to be implemented with other recursive macros. 52 | #define ZIP_EVAL( ... ) ZIP_EVAL255( __VA_ARGS__ ) 53 | 54 | #define ZIP_EVAL255( ... ) ZIP_EVAL127( ZIP_EVAL127( __VA_ARGS__ ) ) 55 | #define ZIP_EVAL127( ... ) ZIP_EVAL63( ZIP_EVAL63( __VA_ARGS__ ) ) 56 | #define ZIP_EVAL63( ... ) ZIP_EVAL31( ZIP_EVAL31( __VA_ARGS__ ) ) 57 | #define ZIP_EVAL31( ... ) ZIP_EVAL15( ZIP_EVAL15( __VA_ARGS__ ) ) 58 | #define ZIP_EVAL15( ... ) ZIP_EVAL7( ZIP_EVAL7( __VA_ARGS__ ) ) 59 | #define ZIP_EVAL7( ... ) ZIP_EVAL3( ZIP_EVAL3( __VA_ARGS__ ) ) 60 | #define ZIP_EVAL3( ... ) ZIP_EVAL1( ZIP_EVAL1( __VA_ARGS__ ) ) 61 | #define ZIP_EVAL1( ... ) __VA_ARGS__ 62 | 63 | 64 | #endif // ifndef MACROFUN_ZIP_H 65 | 66 | --------------------------------------------------------------------------------