• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <iostream>
2 #include <iomanip>
3 #include <string>
4 #include <boost/preprocessor/config/config.hpp>
5 
6 static unsigned int indent = 4;
7 static unsigned int width = 90;
8 
9 using std::cout;
10 using std::istream;
11 
print_separator()12 void print_separator()
13 {
14    std::cout <<
15 "\n\n*********************************************************************\n\n";
16 }
17 
remove_spaces(const std::string ss)18 std::string remove_spaces(const std::string ss)
19     {
20 
21     bool inquotes(false);
22     bool escape(false);
23     char qchar;
24     int len(static_cast<int>(ss.length()));
25 
26     std::string ret;
27 
28     for (int i = 0; i < len; ++i)
29         {
30 
31         char ch(ss[i]);
32 
33         if (inquotes)
34             {
35             if (escape)
36                 {
37                 escape = false;
38                 }
39             else if (ch == '\\')
40                 {
41                 escape = true;
42                 }
43             else if (ch == qchar)
44                 {
45                 inquotes = false;
46                 }
47             ret.push_back(ch);
48             }
49         else
50             {
51             if (ch == '\'' || ch == '"')
52                 {
53                 inquotes = true;
54                 qchar = ch;
55                 ret.push_back(ch);
56                 }
57             else if (ch != ' ')
58                 {
59                 ret.push_back(ch);
60                 }
61             }
62         }
63 
64     return ret;
65     }
66 
print_macro(const std::string name,const std::string expected,const std::string expansion)67 int print_macro(const std::string name,const std::string expected, const std::string expansion)
68 {
69    int bret(0);
70    const std::string sg("Success: ");
71    const std::string sb("Failure: ");
72    for(unsigned i = 0; i < indent; ++i) std::cout.put(' ');
73    if (name == expansion)
74     {
75     if (expected == expansion)
76         {
77         std::cout << sg;
78         std::cout << std::setw(width);
79         cout.setf(istream::left, istream::adjustfield);
80         std::cout << name;
81         std::cout << " [no value]\n";
82         }
83     else
84         {
85         std::cout << sb;
86         std::cout << std::setw(width);
87         cout.setf(istream::left, istream::adjustfield);
88         std::cout << name;
89         std::cout << " [no value]: ";
90         std::cout << " [expected]: ";
91         std::cout << expected << "\n";
92         bret = 1;
93         }
94     }
95    else
96     {
97 
98     std::string sexpected(remove_spaces(expected));
99     std::string sexpansion(remove_spaces(expansion));
100 
101     if (sexpected == sexpansion)
102         {
103         std::cout << sg;
104         std::cout << std::setw(width);
105         cout.setf(istream::left, istream::adjustfield);
106         std::cout << name;
107         std::cout << expansion << "\n";
108         }
109     else
110         {
111         std::cout << sb;
112         std::cout << std::setw(width);
113         cout.setf(istream::left, istream::adjustfield);
114         std::cout << name;
115         std::cout << expansion;
116         std::cout << " [expected]: ";
117         std::cout << expected << "\n";
118         bret = 1;
119         }
120     }
121  return bret;
122 }
123 
124 #if !BOOST_PP_VARIADICS
125 
126 #define STRINGIZE(arg) # arg
127 
128 #define PRINT_MACRO_RESULTS(X,exp) print_macro(std::string(# X), std::string(# exp), std::string(STRINGIZE(X)))
129 #define PRINT_MACRO(x) std::string(# x)
130 #define PRINT_EXPECTED(x) std::string(# x)
131 #define PRINT_EXPANSION(x) std::string(STRINGIZE(x))
132 
133 #else
134 
135 #define STRINGIZE(...) # __VA_ARGS__
136 
137 #define PRINT_MACRO_RESULTS(X,...) print_macro(std::string(# X), std::string(# __VA_ARGS__), std::string(STRINGIZE(X)))
138 #define PRINT_MACRO(...) std::string(# __VA_ARGS__)
139 #define PRINT_EXPECTED(...) std::string(# __VA_ARGS__)
140 #define PRINT_EXPANSION(...) std::string(STRINGIZE(__VA_ARGS__))
141 
142 #endif
143 
144 #if __cplusplus > 201703L
145 
print_macros_common_c20()146 int print_macros_common_c20()
147 {
148 
149   int bret = 0;
150 
151 #define LPAREN() (
152 #define G(Q) 42
153 #define F(R, X, ...) __VA_OPT__(G R X) )
154 
155 // int x = F(LPAREN(), 0, <:-);
156 
157 // replaced by
158 
159 // int x = 42;
160 
161 bret += PRINT_MACRO_RESULTS(int x = F(LPAREN(), 0, <:-);,int x = 42;);
162 
163 #undef LPAREN
164 #undef G
165 #undef F
166 
167 #define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)
168 #define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__)
169 #define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })
170 #define EMP
171 
172 // F(a, b, c)
173 // F()
174 // F(EMP)
175 
176 // replaced by
177 
178 // f(0, a, b, c)
179 // f(0)
180 // f(0)
181 
182 // G(a, b, c)
183 // G(a, )
184 // G(a)
185 
186 // replaced by
187 
188 // f(0, a, b, c)
189 // f(0, a)
190 // f(0, a)
191 
192 // SDEF(foo);
193 // SDEF(bar, 1, 2);
194 
195 // replaced by
196 
197 // S foo;
198 // S bar = { 1, 2 };
199 
200 bret += PRINT_MACRO_RESULTS(F(a, b, c),f(0, a, b, c));
201 bret += PRINT_MACRO_RESULTS(F(),f(0));
202 bret += PRINT_MACRO_RESULTS(F(EMP),f(0));
203 bret += PRINT_MACRO_RESULTS(G(a, b, c),f(0, a, b, c));
204 bret += PRINT_MACRO_RESULTS(G(a, ),f(0, a));
205 bret += PRINT_MACRO_RESULTS(G(a),f(0, a));
206 bret += PRINT_MACRO_RESULTS(SDEF(foo);,S foo;);
207 bret += PRINT_MACRO_RESULTS(SDEF(bar, 1, 2);,S bar = { 1, 2 };);
208 
209 #undef F
210 #undef G
211 #undef SDEF
212 #undef EMP
213 
214 #define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__
215 #define H3(X, ...) #__VA_OPT__(X##X X##X)
216 #define H4(X, ...) __VA_OPT__(a X ## X) ## b
217 #define H5A(...) __VA_OPT__()/**/__VA_OPT__()
218 #define H5B(X) a ## X ## b
219 #define H5C(X) H5B(X)
220 
221 // H2(a, b, c, d)
222 
223 // replaced by
224 
225 // ab, c, d
226 
227 // H3(, 0)
228 
229 // replaced by
230 
231 // ""
232 
233 // H4(, 1)
234 
235 // replaced by
236 
237 // a b
238 
239 // H5C(H5A())
240 
241 // replaced by
242 
243 // ab
244 
245 bret += PRINT_MACRO_RESULTS(H2(a, b, c, d),ab, c, d);
246 bret += PRINT_MACRO_RESULTS(H3(, 0),"");
247 bret += PRINT_MACRO_RESULTS(H4(, 1),a b);
248 bret += PRINT_MACRO_RESULTS(H5C(H5A()),ab);
249 
250 #undef H2
251 #undef H3
252 #undef H4
253 #undef H5A
254 #undef H5B
255 #undef H5C
256 
257   return bret;
258 
259 }
260 
261 #endif
262 
263 int print_macros_common_1()
264 {
265 
266   int bret = 0;
267 
268 #define x 3
269 #define f(a) f(x * (a))
270 #undef x
271 
272 #define x 2
273 #define g f
274 #define z z[0]
275 #define h g(~
276 #define m(a) a(w)
277 #define w 0,1
278 #define t(a) a
279 
280 // f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
281 // g(x+(3,4)-w) | h 5) & m(f)^m(m);
282 
283 // results in
284 
285 // f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
286 // f(2 * (2+(3,4)-0,1)) | f(2 * ( ~ 5)) & f(2 * (0,1))^m(0,1);
287 
288 bret += PRINT_MACRO_RESULTS(f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);,f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1););
289 
290 #define PRINT_INPUT g(x+(3,4)-w) | h 5) & m(f)^m(m);
291 
292 bret += print_macro
293     (
294     std::string("g(x+(3,4)-w) | h 5) & m(f)^m(m);"),
295     PRINT_EXPECTED(f(2 * (2+(3,4)-0,1)) | f(2 * ( ~ 5)) & f(2 * (0,1))^m(0,1);),
296     PRINT_EXPANSION(PRINT_INPUT)
297     );
298 
299 #undef PRINT_INPUT
300 
301 #undef f
302 #undef x
303 #undef g
304 #undef z
305 #undef h
306 #undef m
307 #undef w
308 #undef t
309 
310   return bret;
311 
312 }
313 
314 int print_macros_common_4()
315 {
316 
317   int bret = 0;
318 
319 #define str(s) # s
320 #define xstr(s) str(s)
321 #define debug(s, t) printf("x" # s "= %d, x" # t "= %s", x ## s, x ## t)
322 #define INCFILE(n) vers ## n
323 #define glue(a, b) a ## b
324 #define xglue(a, b) glue(a, b)
325 #define HIGHLOW "hello"
326 #define LOW LOW ", world"
327 
328 // debug(1, 2);
329 // fputs(str(strncmp("abc\0d", "abc", �\4�) // this goes away
330 // == 0) str(: @\n), s);
331 // #include xstr(INCFILE(2).h)
332 // glue(HIGH, LOW);
333 // xglue(HIGH, LOW)
334 
335 // results in
336 
337 // printf("x" "1" "= %d, x" "2" "= %s", x1, x2);
338 // fputs("strncmp(\"abc\\0d\", \"abc\", �\\4�) == 0" ": @\n", s);
339 // #include "vers2.h" (after macro replacement, before file access)
340 // "hello";
341 // "hello" ", world"
342 
343 bret += PRINT_MACRO_RESULTS(debug(1, 2);,printf("x" "1" "= %d, x" "2" "= %s", x1, x2););
344 bret += print_macro
345     (
346     std::string("fputs(str(strncmp(\"abc\\0d\", \"abc\", '\\4') /* this goes away */== 0) str(: @\\n), s);"),
347     PRINT_EXPECTED(fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s);),
348     PRINT_EXPANSION(fputs(str(strncmp("abc\0d", "abc", '\4') /* this goes away */== 0) str(: @\n), s);)
349     );
350 bret += PRINT_MACRO_RESULTS(xstr(INCFILE(2).h),"vers2.h");
351 bret += PRINT_MACRO_RESULTS(glue(HIGH, LOW);,"hello";);
352 
353 #if __cplusplus <= 199711L
354 
355 bret += print_macro
356     (
357     PRINT_MACRO(xglue(HIGH, LOW)),
358     std::string("\"hello\" \", world\""),
359     PRINT_EXPANSION(xglue(HIGH, LOW))
360     );
361 
362 #else
363 
364 bret += PRINT_MACRO_RESULTS(xglue(HIGH, LOW),"hello" ", world");
365 
366 #endif
367 
368 #undef str
369 #undef xstr
370 #undef debug
371 #undef INCFILE
372 #undef glue
373 #undef xglue
374 #undef HIGHLOW
375 #undef LOW
376 
377   return bret;
378 
379 }
380 
381 int print_macros_common_2()
382 {
383 
384   int bret = 0;
385 
386 #define hash_hash # ## #
387 #define mkstr(a) # a
388 #define in_between(a) mkstr(a)
389 #define join(c, d) in_between(c hash_hash d)
390 
391 // char p[] = join(x, y);
392 
393 // equivalent to
394 
395 // char p[] = "x ## y";
396 
397 bret += PRINT_MACRO_RESULTS(char p[] = join(x, y);,char p[] = "x ## y";);
398 
399 #undef hash_hash
400 #undef mkstr
401 #undef in_between
402 #undef join
403 
404   return bret;
405 
406 }
407 
408 #if BOOST_PP_VARIADICS && __cplusplus > 199711L
409 
410 int print_macros_common_3()
411 {
412 
413   int bret = 0;
414 
415 #define p() int
416 #define q(x) x
417 #define r(x,y) x ## y
418 #define str(x) # x
419 
420 // p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };
421 // char c[2][6] = { str(hello), str() };
422 
423 // results in
424 
425 // int i[] = { 1, 23, 4, 5, };
426 // char c[2][6] = { "hello", "" };
427 
428 bret += print_macro
429     (
430     PRINT_MACRO(p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };),
431     PRINT_EXPECTED(int i[] = { 1, 23, 4, 5, };),
432     PRINT_EXPANSION(p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };)
433     );
434 bret += print_macro
435     (
436     PRINT_MACRO(char c[2][6] = { str(hello), str() };),
437     PRINT_EXPECTED(char c[2][6] = { "hello", "" };),
438     PRINT_EXPANSION(char c[2][6] = { str(hello), str() };)
439     );
440 
441 #undef p
442 #undef q
443 #undef r
444 #undef str
445 
446 bret += print_macros_common_4();
447 
448 #define t(x,y,z) x ## y ## z
449 
450 // int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) };
451 
452 // results in
453 
454 // int j[] = { 123, 45, 67, 89, 10, 11, 12, };
455 
456 bret += print_macro
457     (
458     PRINT_MACRO(int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) };),
459     PRINT_EXPECTED(int j[] = { 123, 45, 67, 89, 10, 11, 12, };),
460     PRINT_EXPANSION(int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) };)
461     );
462 
463 #undef t
464 
465 #define debug(...) fprintf(stderr, __VA_ARGS__)
466 #define showlist(...) puts(#__VA_ARGS__)
467 #define report(test, ...) ((test) ? puts(#test) : printf(__VA_ARGS__))
468 
469 // debug("Flag");
470 // debug("X = %d\n", x);
471 // showlist(The first, second, and third items.);
472 // report(x>y, "x is %d but y is %d", x, y);
473 
474 // results in
475 
476 // fprintf(stderr, "Flag");
477 // fprintf(stderr, "X = %d\n", x);
478 // puts("The first, second, and third items.");
479 // ((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y));
480 
481 #define save_stderr stderr
482 #undef stderr
483 
484 bret += PRINT_MACRO_RESULTS(debug("Flag");,fprintf(stderr, "Flag"););
485 bret += PRINT_MACRO_RESULTS(debug("X = %d\n", x);,fprintf(stderr, "X = %d\n", x););
486 
487 #define stderr save_stderr
488 
489 bret += PRINT_MACRO_RESULTS(showlist(The first, second, and third items.);,puts("The first, second, and third items."););
490 bret += PRINT_MACRO_RESULTS(report(x>y, "x is %d but y is %d", x, y);,((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y)););
491 
492 #undef debug
493 #undef showlist
494 #undef report
495 
496   return bret;
497 
498 }
499 
500 #endif
501 
502 int print_macros()
503 {
504   int bret = 0;
505 
506   print_separator();
507 
508   std::cout << "__cplusplus = " << __cplusplus;
509 
510   print_separator();
511 
512 #define OBJ_LIKE (1-1)
513 #define OBJ_LIKE /* white space */ (1-1) /* other */
514 #define FTN_LIKE(a) ( a )
515 #define FTN_LIKE( a )( /* note the white space */ a /* other stuff on this line */ )
516 
517 #if !BOOST_PP_VARIADICS
518 
519 bret += print_macros_common_1();
520 bret += print_macros_common_4();
521 
522 #elif __cplusplus <= 199711L
523 
524 bret += print_macros_common_2();
525 bret += print_macros_common_1();
526 bret += print_macros_common_4();
527 
528 #elif __cplusplus <= 201703L
529 
530 bret += print_macros_common_2();
531 bret += print_macros_common_1();
532 bret += print_macros_common_3();
533 
534 #else
535 
536 bret += print_macros_common_c20();
537 bret += print_macros_common_2();
538 bret += print_macros_common_1();
539 bret += print_macros_common_3();
540 
541 #endif
542 
543   print_separator();
544 
545   return bret;
546 }
547 
548 int main()
549 {
550   return (print_macros());
551 }
552