Files
preprocessor/test/cpp_standard.cpp
2020-09-17 18:25:36 -04:00

534 lines
11 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <iostream>
#include <iomanip>
#include <string>
#include <boost/preprocessor/config/config.hpp>
static unsigned int indent = 4;
static unsigned int width = 90;
using std::cout;
using std::istream;
void print_separator()
{
std::cout <<
"\n\n*********************************************************************\n\n";
}
std::string remove_spaces(const std::string ss)
{
bool inquotes(false);
bool escape(false);
char qchar;
int len(static_cast<int>(ss.length()));
std::string ret;
for (int i = 0; i < len; ++i)
{
char ch(ss[i]);
if (inquotes)
{
if (escape)
{
escape = false;
}
else if (ch == '\\')
{
escape = true;
}
else if (ch == qchar)
{
inquotes = false;
}
ret.push_back(ch);
}
else
{
if (ch == '\'' || ch == '"')
{
inquotes = true;
qchar = ch;
ret.push_back(ch);
}
else if (ch != ' ')
{
ret.push_back(ch);
}
}
}
return ret;
}
int print_macro(const std::string name,const std::string expected, const std::string expansion)
{
int bret(0);
const std::string sg("Success: ");
const std::string sb("Failure: ");
for(unsigned i = 0; i < indent; ++i) std::cout.put(' ');
if (name == expansion)
{
if (expected == expansion)
{
std::cout << sg;
std::cout << std::setw(width);
cout.setf(istream::left, istream::adjustfield);
std::cout << name;
std::cout << " [no value]\n";
}
else
{
std::cout << sb;
std::cout << std::setw(width);
cout.setf(istream::left, istream::adjustfield);
std::cout << name;
std::cout << " [no value]: ";
std::cout << " [expected]: ";
std::cout << expected << "\n";
bret = 1;
}
}
else
{
std::string sexpected(remove_spaces(expected));
std::string sexpansion(remove_spaces(expansion));
if (sexpected == sexpansion)
{
std::cout << sg;
std::cout << std::setw(width);
cout.setf(istream::left, istream::adjustfield);
std::cout << name;
std::cout << expansion << "\n";
}
else
{
std::cout << sb;
std::cout << std::setw(width);
cout.setf(istream::left, istream::adjustfield);
std::cout << name;
std::cout << expansion;
std::cout << " [expected]: ";
std::cout << expected << "\n";
bret = 1;
}
}
return bret;
}
#define STRINGIZE(...) # __VA_ARGS__
#define PRINT_MACRO_RESULTS(X,...) print_macro(std::string(# X), std::string(# __VA_ARGS__), std::string(STRINGIZE(X)))
#define PRINT_MACRO(...) std::string(# __VA_ARGS__)
#define PRINT_EXPECTED(...) std::string(# __VA_ARGS__)
#define PRINT_EXPANSION(...) std::string(STRINGIZE(__VA_ARGS__))
#if __cplusplus > 201703L
int print_macros_common_c20()
{
int bret = 0;
#define LPAREN() (
#define G(Q) 42
#define F(R, X, ...) __VA_OPT__(G R X) )
// int x = F(LPAREN(), 0, <:-);
// replaced by
// int x = 42;
bret += PRINT_MACRO_RESULTS(int x = F(LPAREN(), 0, <:-);,int x = 42;);
#undef LPAREN
#undef G
#undef F
#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)
#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__)
#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })
#define EMP
// F(a, b, c)
// F()
// F(EMP)
// replaced by
// f(0, a, b, c)
// f(0)
// f(0)
// G(a, b, c)
// G(a, )
// G(a)
// replaced by
// f(0, a, b, c)
// f(0, a)
// f(0, a)
// SDEF(foo);
// SDEF(bar, 1, 2);
// replaced by
// S foo;
// S bar = { 1, 2 };
bret += PRINT_MACRO_RESULTS(F(a, b, c),f(0, a, b, c));
bret += PRINT_MACRO_RESULTS(F(),f(0));
bret += PRINT_MACRO_RESULTS(F(EMP),f(0));
bret += PRINT_MACRO_RESULTS(G(a, b, c),f(0, a, b, c));
bret += PRINT_MACRO_RESULTS(G(a, ),f(0, a));
bret += PRINT_MACRO_RESULTS(G(a),f(0, a));
bret += PRINT_MACRO_RESULTS(SDEF(foo);,S foo;);
bret += PRINT_MACRO_RESULTS(SDEF(bar, 1, 2);,S bar = { 1, 2 };);
#undef F
#undef G
#undef SDEF
#undef EMP
#define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__
#define H3(X, ...) #__VA_OPT__(X##X X##X)
#define H4(X, ...) __VA_OPT__(a X ## X) ## b
#define H5A(...) __VA_OPT__()/**/__VA_OPT__()
#define H5B(X) a ## X ## b
#define H5C(X) H5B(X)
// H2(a, b, c, d)
// replaced by
// ab, c, d
// H3(, 0)
// replaced by
// ""
// H4(, 1)
// replaced by
// a b
// H5C(H5A())
// replaced by
// ab
bret += PRINT_MACRO_RESULTS(H2(a, b, c, d),ab, c, d);
bret += PRINT_MACRO_RESULTS(H3(, 0),"");
bret += PRINT_MACRO_RESULTS(H4(, 1),a b);
bret += PRINT_MACRO_RESULTS(H5C(H5A()),ab);
#undef H2
#undef H3
#undef H4
#undef H5A
#undef H5B
#undef H5C
return bret;
}
#endif
int print_macros_common_1()
{
int bret = 0;
#define x 3
#define f(a) f(x * (a))
#undef x
#define x 2
#define g f
#define z z[0]
#define h g(~
#define m(a) a(w)
#define w 0,1
#define t(a) a
// f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
// g(x+(3,4)-w) | h 5) & m(f)^m(m);
// results in
// f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
// f(2 * (2+(3,4)-0,1)) | f(2 * ( ~ 5)) & f(2 * (0,1))^m(0,1);
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););
#define PRINT_INPUT g(x+(3,4)-w) | h 5) & m(f)^m(m);
bret += print_macro
(
std::string("g(x+(3,4)-w) | h 5) & m(f)^m(m);"),
PRINT_EXPECTED(f(2 * (2+(3,4)-0,1)) | f(2 * ( ~ 5)) & f(2 * (0,1))^m(0,1);),
PRINT_EXPANSION(PRINT_INPUT)
);
#undef PRINT_INPUT
#undef f
#undef x
#undef g
#undef z
#undef h
#undef m
#undef w
#undef t
return bret;
}
int print_macros_common_4()
{
int bret = 0;
#define str(s) # s
#define xstr(s) str(s)
#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", x ## s, x ## t)
#define INCFILE(n) vers ## n
#define glue(a, b) a ## b
#define xglue(a, b) glue(a, b)
#define HIGHLOW "hello"
#define LOW LOW ", world"
// debug(1, 2);
// fputs(str(strncmp("abc\0d", "abc", \4) // this goes away
// == 0) str(: @\n), s);
// #include xstr(INCFILE(2).h)
// glue(HIGH, LOW);
// xglue(HIGH, LOW)
// results in
// printf("x" "1" "= %d, x" "2" "= %s", x1, x2);
// fputs("strncmp(\"abc\\0d\", \"abc\", \\4) == 0" ": @\n", s);
// #include "vers2.h" (after macro replacement, before file access)
// "hello";
// "hello" ", world"
bret += PRINT_MACRO_RESULTS(debug(1, 2);,printf("x" "1" "= %d, x" "2" "= %s", x1, x2););
bret += print_macro
(
std::string("fputs(str(strncmp(\"abc\\0d\", \"abc\", '\\4') /* this goes away */== 0) str(: @\\n), s);"),
PRINT_EXPECTED(fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s);),
PRINT_EXPANSION(fputs(str(strncmp("abc\0d", "abc", '\4') /* this goes away */== 0) str(: @\n), s);)
);
bret += PRINT_MACRO_RESULTS(xstr(INCFILE(2).h),"vers2.h");
bret += PRINT_MACRO_RESULTS(glue(HIGH, LOW);,"hello";);
#if __cplusplus <= 199711L
bret += print_macro
(
PRINT_MACRO(xglue(HIGH, LOW)),
std::string("\"hello\" \", world\""),
PRINT_EXPANSION(xglue(HIGH, LOW))
);
#else
bret += PRINT_MACRO_RESULTS(xglue(HIGH, LOW),"hello" ", world");
#endif
#undef str
#undef xstr
#undef debug
#undef INCFILE
#undef glue
#undef xglue
#undef HIGHLOW
#undef LOW
return bret;
}
int print_macros_common_2()
{
int bret = 0;
#define hash_hash # ## #
#define mkstr(a) # a
#define in_between(a) mkstr(a)
#define join(c, d) in_between(c hash_hash d)
// char p[] = join(x, y);
// equivalent to
// char p[] = "x ## y";
bret += PRINT_MACRO_RESULTS(char p[] = join(x, y);,char p[] = "x ## y";);
#undef hash_hash
#undef mkstr
#undef in_between
#undef join
return bret;
}
#if __cplusplus > 199711L
int print_macros_common_3()
{
int bret = 0;
#define p() int
#define q(x) x
#define r(x,y) x ## y
#define str(x) # x
// p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };
// char c[2][6] = { str(hello), str() };
// results in
// int i[] = { 1, 23, 4, 5, };
// char c[2][6] = { "hello", "" };
bret += print_macro
(
PRINT_MACRO(p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };),
PRINT_EXPECTED(int i[] = { 1, 23, 4, 5, };),
PRINT_EXPANSION(p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };)
);
bret += print_macro
(
PRINT_MACRO(char c[2][6] = { str(hello), str() };),
PRINT_EXPECTED(char c[2][6] = { "hello", "" };),
PRINT_EXPANSION(char c[2][6] = { str(hello), str() };)
);
#undef p
#undef q
#undef r
#undef str
bret += print_macros_common_4();
#define t(x,y,z) x ## y ## z
// int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) };
// results in
// int j[] = { 123, 45, 67, 89, 10, 11, 12, };
bret += print_macro
(
PRINT_MACRO(int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) };),
PRINT_EXPECTED(int j[] = { 123, 45, 67, 89, 10, 11, 12, };),
PRINT_EXPANSION(int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), t(10,,), t(,11,), t(,,12), t(,,) };)
);
#undef t
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define showlist(...) puts(#__VA_ARGS__)
#define report(test, ...) ((test) ? puts(#test) : printf(__VA_ARGS__))
// debug("Flag");
// debug("X = %d\n", x);
// showlist(The first, second, and third items.);
// report(x>y, "x is %d but y is %d", x, y);
// results in
// fprintf(stderr, "Flag");
// fprintf(stderr, "X = %d\n", x);
// puts("The first, second, and third items.");
// ((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y));
#define save_stderr stderr
#undef stderr
bret += PRINT_MACRO_RESULTS(debug("Flag");,fprintf(stderr, "Flag"););
bret += PRINT_MACRO_RESULTS(debug("X = %d\n", x);,fprintf(stderr, "X = %d\n", x););
#define stderr save_stderr
bret += PRINT_MACRO_RESULTS(showlist(The first, second, and third items.);,puts("The first, second, and third items."););
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)););
#undef debug
#undef showlist
#undef report
return bret;
}
#endif
int print_macros()
{
int bret = 0;
print_separator();
std::cout << "__cplusplus = " << __cplusplus;
print_separator();
#define OBJ_LIKE (1-1)
#define OBJ_LIKE /* white space */ (1-1) /* other */
#define FTN_LIKE(a) ( a )
#define FTN_LIKE( a )( /* note the white space */ a /* other stuff on this line */ )
#if __cplusplus <= 199711L
bret += print_macros_common_2();
bret += print_macros_common_1();
bret += print_macros_common_4();
#elif __cplusplus <= 201703L
bret += print_macros_common_2();
bret += print_macros_common_1();
bret += print_macros_common_3();
#else
bret += print_macros_common_c20();
bret += print_macros_common_2();
bret += print_macros_common_1();
bret += print_macros_common_3();
#endif
print_separator();
return bret;
}
int main()
{
return (print_macros());
}