]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/format/tools/format_matrix.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / format / tools / format_matrix.cpp
1 // ------------------------------------------------------------------------------
2 // format_matrix.cpp : tool to check for regressions between boost format
3 // releases and compare format specification handling
4 // ------------------------------------------------------------------------------
5
6 // Copyright 2017 James E. King, III. Use, modification, and distribution
7 // are subject to the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9
10 // See http://www.boost.org/libs/format for library home page
11
12 // ------------------------------------------------------------------------------
13 // reference (ISO C99) : http://en.cppreference.com/w/cpp/io/c/fprintf
14 // reference (Java) : http://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html
15 // reference (Microsoft) : https://docs.microsoft.com/en-us/cpp/c-runtime-library/format-specification-syntax-printf-and-wprintf-functions
16 // reference (POSIX 2008): http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html
17
18 #include <boost/array.hpp>
19 #include <boost/config.hpp>
20 #include <boost/cstdint.hpp>
21 #include <boost/filesystem/path.hpp>
22 #include <boost/format.hpp>
23 #include <boost/io/ios_state.hpp>
24 #include <boost/predef.h>
25 #include <boost/program_options.hpp>
26 #include <cerrno>
27 #include <climits>
28 #include <clocale>
29 #if BOOST_COMP_MSVC && BOOST_VERSION_NUMBER_MAJOR(BOOST_COMP_MSVC) >= 19
30 #include <corecrt.h> // wint_t
31 #endif
32 #include <cstdio>
33 #include <cstdlib>
34 #include <cstring>
35 #include <cwchar>
36 #include <fstream>
37 #include <iomanip>
38 #include <iostream>
39 #include <math.h>
40
41 #define SNPRINTF snprintf
42 #if BOOST_COMP_MSVC && BOOST_VERSION_NUMBER_MAJOR(BOOST_COMP_MSVC) < 19
43 #undef SNPRINTF
44 #define SNPRINTF _snprintf
45 #endif
46
47 namespace fs = boost::filesystem;
48 namespace po = boost::program_options;
49 using namespace std;
50
51 namespace matrix
52 {
53
54 enum interop_datatype
55 {
56 // special types:
57 ID_UNDEF, // undefined behavior according to the spec, so combination is not tested
58 ID_NOTSUP, // behavior is not supported and therefore not tested currently
59
60 // boolean type values:
61 ID_BOOLF, // false
62 ID_BOOLT, // true
63
64 // string type values:
65 ID_CHAR, // single signed character
66 ID_UCHAR, // single unsigned character
67 ID_WCHAR, // single wide character
68 ID_STR, // C style string
69 ID_WSTR, // C style wide string
70
71 // integer type values:
72 ID_ZERO, // zero value
73 ID_BYTE, // int8_t
74 ID_UBYTE, // uint8_t
75 ID_SHORT, // signed short
76 ID_USHORT, // unsigned short
77 ID_INT, // signed integer
78 ID_UINT, // unsigned integer
79 ID_LONG, // signed long
80 ID_ULONG, // unsigned long
81 ID_LLONG, // signed long long
82 ID_ULLONG, // unsigned long long
83 ID_INTMAX, // intmax_t
84 ID_SSIZET, // ssize_t
85 ID_SIZET, // size_t
86 ID_SPTRDF, // signed ptrdiff_t
87 ID_PTRDIF, // ptrdiff_t
88
89 // floating type values:
90 ID_INF, // infinity
91 ID_NAN, // not a number
92 ID_DOUBLE, // double
93 ID_NEGDBL, // negative double
94 ID_LNGDBL, // long double
95 ID_NEGLNG // negative long double
96 };
97
98 BOOST_CONSTEXPR const bool g_bf = false;
99 BOOST_CONSTEXPR const bool g_bt = true;
100 BOOST_CONSTEXPR const uint64_t g_z = 0;
101 BOOST_CONSTEXPR const char g_by = 0x60;
102 BOOST_CONSTEXPR const unsigned char g_uby = 0xA0;
103 BOOST_CONSTEXPR const char g_c = 0x58;
104 BOOST_CONSTEXPR const wint_t g_wc = L'X'; // 'X', but wide
105 BOOST_CONSTEXPR const char * g_s = " string";
106 BOOST_CONSTEXPR const wchar_t * g_ws = L"widestr";
107 BOOST_CONSTEXPR const short g_h = numeric_limits<short>::min() + 12345;
108 BOOST_CONSTEXPR const unsigned short g_uh = numeric_limits<unsigned short>::max() - 12345;
109 BOOST_CONSTEXPR const int g_i = numeric_limits<int>::max() - 12345;
110 BOOST_CONSTEXPR const unsigned int g_ui = numeric_limits<unsigned int>::max() - 12345;
111 BOOST_CONSTEXPR const long g_l = numeric_limits<long>::max() - 12345;
112 BOOST_CONSTEXPR const unsigned long g_ul = numeric_limits<unsigned long>::max() - 12345;
113 BOOST_CONSTEXPR const int64_t g_ll = numeric_limits<int64_t>::max() - 12345;
114 BOOST_CONSTEXPR const uint64_t g_ull = numeric_limits<uint64_t>::max() - 12345;
115 BOOST_CONSTEXPR const intmax_t g_max = numeric_limits<intmax_t>::max() - 12345;
116 BOOST_CONSTEXPR const size_t g_sst = numeric_limits<size_t>::min() - 12345;
117 BOOST_CONSTEXPR const size_t g_st = numeric_limits<size_t>::max() - 12345;
118 BOOST_CONSTEXPR const ptrdiff_t g_pt = numeric_limits<ptrdiff_t>::max() - 12345;
119 BOOST_CONSTEXPR const double g_db = 1234567.891234f;
120 BOOST_CONSTEXPR const double g_ndb = -1234567.891234f;
121 BOOST_CONSTEXPR const long double g_ldb = 6543211234567.891234l;
122 BOOST_CONSTEXPR const long double g_nld = -6543211234567.891234l;
123 #if defined(INFINITY)
124 BOOST_CONSTEXPR const double g_inf = INFINITY;
125 #endif
126 #if defined(NAN)
127 BOOST_CONSTEXPR const double g_nan = NAN;
128 #endif
129
130 boost::array<const char *, 12> length_modifier = { { "hh", "h", "", "l", "ll", "j", "z", "L", "w", "I", "I32", "I64" } };
131 boost::array<const char *, 6> format_flags = { { "", "-", "+", " ", "#", "0" } };
132 boost::array<const char *, 6> minimum_width = { { "", "1", "2", "5", "10", "20" } }; // TODO: , "*" } };
133 boost::array<const char *, 7> precision = { { "", ".", ".0", ".2", ".5", ".10", ".20" } }; // TODO: , ".*" } };
134
135 struct interop_row
136 {
137 char conversion_specifier;
138 interop_datatype datatype[12];
139 };
140
141 // Each row represents a conversion specifier which is indicated in the first column
142 // The subsequent columns are argument type specifiers for that conversion specifier
143 // The data in the cell is the value to pass into snprintf and format to see what comes out
144
145 interop_row interop_matrix[] = {
146 // |----------------------------------- ISO C99 ---------------------------------------| |-------------- Microsoft --------------|
147 // spc, hh , h , (none) , l , ll , j , z , L , w , I , I32 , I64
148 { 'c', { ID_UNDEF , ID_UNDEF , ID_CHAR , ID_WCHAR , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_WCHAR , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
149 { 's', { ID_UNDEF , ID_UNDEF , ID_STR , ID_WSTR , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_WSTR , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
150
151 { 'd', { ID_BYTE , ID_SHORT , ID_INT , ID_LONG , ID_LLONG , ID_INTMAX, ID_SSIZET, ID_UNDEF , ID_UNDEF , ID_SPTRDF, ID_INT , ID_LLONG } },
152 { 'd', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
153 { 'd', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
154 { 'i', { ID_BYTE , ID_SHORT , ID_INT , ID_LONG , ID_LLONG , ID_INTMAX, ID_SSIZET, ID_UNDEF , ID_UNDEF , ID_SPTRDF, ID_INT , ID_LLONG } },
155 { 'i', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
156 { 'i', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
157
158 { 'o', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
159 { 'o', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
160 { 'x', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
161 { 'x', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
162 { 'X', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
163 { 'X', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
164 { 'u', { ID_UBYTE , ID_USHORT, ID_UINT , ID_ULONG , ID_ULLONG, ID_INTMAX, ID_SIZET , ID_UNDEF , ID_UNDEF , ID_PTRDIF, ID_UINT , ID_ULLONG} },
165 { 'u', { ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_ZERO } },
166
167 { 'f', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
168 { 'f', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
169 { 'f', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
170 { 'f', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
171 { 'f', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
172 { 'F', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
173 { 'F', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
174 { 'F', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
175 { 'F', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
176 { 'F', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
177 { 'e', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
178 { 'e', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
179 { 'e', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
180 { 'e', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
181 { 'e', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
182 { 'E', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
183 { 'E', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
184 { 'E', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
185 { 'E', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
186 { 'E', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
187 { 'a', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
188 { 'a', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
189 { 'a', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
190 { 'a', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
191 { 'a', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
192 { 'A', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
193 { 'A', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
194 { 'A', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
195 { 'A', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
196 { 'A', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
197 { 'g', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
198 { 'g', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
199 { 'g', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
200 { 'g', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
201 { 'g', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
202 { 'G', { ID_UNDEF , ID_UNDEF , ID_DOUBLE, ID_DOUBLE, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_LNGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
203 { 'G', { ID_UNDEF , ID_UNDEF , ID_NEGDBL, ID_NEGDBL, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NEGLNG, ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
204 { 'G', { ID_UNDEF , ID_UNDEF , ID_INF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_INF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
205 { 'G', { ID_UNDEF , ID_UNDEF , ID_NAN , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_NAN , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
206 { 'G', { ID_UNDEF , ID_UNDEF , ID_ZERO , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_ZERO , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
207
208 // boolalpha - not supported in snprintf per ISO C99 but is by boost::format so...
209 { 'b', { ID_UNDEF , ID_UNDEF , ID_BOOLF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
210 { 'b', { ID_UNDEF , ID_UNDEF , ID_BOOLT , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
211
212 // this is the terminator for conversion specifier loops:
213 { 0 , { ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF , ID_UNDEF } },
214 };
215
216 std::string call_snprintf(const std::string& fmtStr, interop_datatype type)
217 {
218 // enough space to hold any value in this test
219 char buf[BUFSIZ];
220 int len = 0;
221
222 switch (type)
223 {
224 case ID_ZERO: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_z ); break;
225 case ID_BOOLF: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_bf ); break;
226 case ID_BOOLT: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_bt ); break;
227 case ID_BYTE: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_by ); break;
228 case ID_UBYTE: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_uby); break;
229 case ID_CHAR: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_c ); break;
230 case ID_WCHAR: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_wc ); break;
231 case ID_STR: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_s ); break;
232 case ID_WSTR: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ws ); break;
233 case ID_SHORT: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_h ); break;
234 case ID_USHORT: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_uh ); break;
235 case ID_INT: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_i ); break;
236 case ID_UINT: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ui ); break;
237 case ID_LONG: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_l ); break;
238 case ID_ULONG: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ul ); break;
239 case ID_LLONG: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ll ); break;
240 case ID_ULLONG: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ull); break;
241 case ID_INTMAX: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_max); break;
242 case ID_SSIZET: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_sst); break;
243 case ID_SIZET: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_st ); break;
244 case ID_SPTRDF: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_pt ); break;
245 case ID_PTRDIF: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_pt ); break;
246 #if defined(INFINITY)
247 case ID_INF: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_inf); break;
248 #endif
249 #if defined(NAN)
250 case ID_NAN: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_nan); break;
251 #endif
252 case ID_DOUBLE: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_db ); break;
253 case ID_NEGDBL: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ndb); break;
254 case ID_LNGDBL: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_ldb); break;
255 case ID_NEGLNG: len = SNPRINTF(buf, BUFSIZ, fmtStr.c_str(), g_nld); break;
256 default: throw logic_error("unhandled type in call_snprintf");
257 }
258
259 if (len < 0)
260 {
261 throw logic_error("snprintf length 0");
262 }
263
264 return std::string(buf, len);
265 }
266
267 std::string call_format(const std::string& fmtStr, interop_datatype type)
268 {
269 switch (type)
270 {
271 case ID_ZERO: return ::boost::str(::boost::format(fmtStr) % g_z );
272 case ID_BOOLF: return ::boost::str(::boost::format(fmtStr) % g_bf );
273 case ID_BOOLT: return ::boost::str(::boost::format(fmtStr) % g_bt );
274 case ID_BYTE: return ::boost::str(::boost::format(fmtStr) % g_by );
275 case ID_UBYTE: return ::boost::str(::boost::format(fmtStr) % g_uby);
276 case ID_CHAR: return ::boost::str(::boost::format(fmtStr) % g_c );
277 case ID_WCHAR: return ::boost::str(::boost::format(fmtStr) % g_wc );
278 case ID_STR: return ::boost::str(::boost::format(fmtStr) % g_s );
279 case ID_WSTR: return ::boost::str(::boost::format(fmtStr) % g_ws );
280 case ID_SHORT: return ::boost::str(::boost::format(fmtStr) % g_h );
281 case ID_USHORT: return ::boost::str(::boost::format(fmtStr) % g_uh );
282 case ID_INT: return ::boost::str(::boost::format(fmtStr) % g_i );
283 case ID_UINT: return ::boost::str(::boost::format(fmtStr) % g_ui );
284 case ID_LONG: return ::boost::str(::boost::format(fmtStr) % g_l );
285 case ID_ULONG: return ::boost::str(::boost::format(fmtStr) % g_ul );
286 case ID_LLONG: return ::boost::str(::boost::format(fmtStr) % g_ll );
287 case ID_ULLONG: return ::boost::str(::boost::format(fmtStr) % g_ull);
288 case ID_INTMAX: return ::boost::str(::boost::format(fmtStr) % g_max);
289 case ID_SSIZET: return ::boost::str(::boost::format(fmtStr) % g_sst);
290 case ID_SIZET: return ::boost::str(::boost::format(fmtStr) % g_st );
291 case ID_SPTRDF: return ::boost::str(::boost::format(fmtStr) % g_pt );
292 case ID_PTRDIF: return ::boost::str(::boost::format(fmtStr) % g_pt );
293 #if defined(INFINITY)
294 case ID_INF: return ::boost::str(::boost::format(fmtStr) % g_inf);
295 #endif
296 #if defined(NAN)
297 case ID_NAN: return ::boost::str(::boost::format(fmtStr) % g_nan);
298 #endif
299 case ID_DOUBLE: return ::boost::str(::boost::format(fmtStr) % g_db );
300 case ID_NEGDBL: return ::boost::str(::boost::format(fmtStr) % g_ndb);
301 case ID_LNGDBL: return ::boost::str(::boost::format(fmtStr) % g_ldb);
302 case ID_NEGLNG: return ::boost::str(::boost::format(fmtStr) % g_nld);
303 default: throw logic_error("unhandled type in call_format");
304 }
305 }
306
307 po::variables_map g_args;
308 ofstream g_os;
309
310 void
311 write_header()
312 {
313 if (g_args.count("snprintf"))
314 {
315 #if BOOST_LIB_C_GNU
316 g_os << "# glibc.version = " << BOOST_VERSION_NUMBER_MAJOR(BOOST_LIB_C_GNU) << "."
317 << BOOST_VERSION_NUMBER_MINOR(BOOST_LIB_C_GNU) << "."
318 << BOOST_VERSION_NUMBER_PATCH(BOOST_LIB_C_GNU)
319 << endl;
320 #elif BOOST_COMP_MSVC
321 g_os << "# msvc.version = " << BOOST_VERSION_NUMBER_MAJOR(BOOST_COMP_MSVC) << "."
322 << BOOST_VERSION_NUMBER_MINOR(BOOST_COMP_MSVC) << "."
323 << BOOST_VERSION_NUMBER_PATCH(BOOST_COMP_MSVC)
324 << endl;
325 #else
326 g_os << "# libc.version = unknown" << endl;
327 #endif
328 }
329 else
330 {
331 g_os << "# boost.version = " << BOOST_VERSION / 100000 << "." // major version
332 << BOOST_VERSION / 100 % 1000 << "." // minor version
333 << BOOST_VERSION % 100 // patch level
334 << endl;
335 }
336 }
337
338 void
339 log(const std::string& spec, bool ok, const std::string& result)
340 {
341 boost::io::ios_all_saver saver(g_os);
342 g_os << setw(20) << right << spec << "\t"
343 << (ok ? "OK " : "ERR") << "\t" << "\"" << result << "\"" << endl;
344 }
345
346 void cell(std::size_t nrow, std::size_t ncol)
347 {
348 const interop_row& row(interop_matrix[nrow]);
349
350 const interop_datatype& dataType(row.datatype[ncol]);
351 if (dataType == ID_UNDEF || dataType == ID_NOTSUP)
352 {
353 return;
354 }
355
356 #if !defined(INFINITY)
357 if (dataType == ID_INF)
358 {
359 return;
360 }
361 #endif
362
363 #if !defined(NAN)
364 if (dataType == ID_NAN)
365 {
366 return;
367 }
368 #endif
369
370 // TODO: every combination of format flags - right now we do only one
371 for (std::size_t ffi = 0; ffi < format_flags.size(); ++ffi)
372 {
373 for (std::size_t mwi = 0; mwi < minimum_width.size(); ++mwi)
374 {
375 for (std::size_t pri = 0; pri < precision.size(); ++pri)
376 {
377 // Make the format string
378 std::stringstream fss;
379 fss << '%';
380 fss << format_flags[ffi];
381 fss << minimum_width[mwi];
382 fss << precision[pri];
383 fss << length_modifier[ncol];
384 fss << row.conversion_specifier;
385 std::string fmtStr = fss.str();
386
387 try
388 {
389 std::string result = g_args.count("snprintf") ?
390 call_snprintf(fmtStr, dataType) :
391 call_format (fmtStr, dataType) ;
392 log(fmtStr, true, result);
393 }
394 catch (const std::exception& ex)
395 {
396 log(fmtStr, false, ex.what());
397 }
398 }
399 }
400 }
401 }
402
403 void
404 matrix()
405 {
406 for (std::size_t row = 0; interop_matrix[row].conversion_specifier != 0x00; ++row)
407 {
408 for (std::size_t col = 0; col < length_modifier.size(); ++col)
409 {
410 cell(row, col);
411 }
412 }
413 }
414
415 void
416 write_pctpct()
417 {
418 if (g_args.count("snprintf"))
419 {
420 char buf[BUFSIZ];
421 int len = SNPRINTF(buf, BUFSIZ, "%%");
422 log("%%", len == 1, len == 1 ? buf : "snprintf length != 1");
423 }
424 else
425 {
426 try
427 {
428 log("%%", true, ::boost::format("%%").str());
429 }
430 catch (std::exception& ex)
431 {
432 log("%%", false, ex.what());
433 }
434 }
435 }
436
437 void
438 generate()
439 {
440 string genpath = g_args["generate"].as<string>();
441 g_os.open(genpath.c_str(), ios::out | ios::trunc);
442 write_header();
443 write_pctpct();
444 matrix();
445 g_os.close();
446 }
447
448 } // matrix
449
450 ///////////////////////////////////////////////////////////////////////////////
451 // main entry point
452 int
453 main(int argc, char *argv[])
454 {
455 using matrix::g_args;
456
457 po::options_description desc("Allowed options");
458 desc.add_options()
459 ("generate,g", po::value<string>()->required(), "generate output filename")
460 ("help,h", "produce help message")
461 ("snprintf,s", "use snprintf instead of boost::format")
462 ;
463
464 po::store(po::command_line_parser(argc, argv).options(desc).run(), g_args);
465 po::notify(g_args);
466
467 if (g_args.count("help")) {
468 cout << "Usage: format_matrix [options]\n";
469 cout << desc;
470 return 0;
471 }
472
473 matrix::generate();
474
475 return 0;
476 }