Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.libc.cpp
Go to the documentation of this file.
1
29#include <cstdlib> // for bsearch, qsort
30#include <csignal> // for signal
31#include <csetjmp> // for setjmp, longjmp
32
33#include <rw_alg_test.h>
34#include <rw_value.h> // for UserClass
35#include <rw_driver.h> // for rw_test()
36
37
39// used as a special value in comp below
40static int global[] = { 0, 0 };
41
42
43extern "C" {
44
45 static std::jmp_buf jmp_env;
46
47 // SIGABRT handler
48 static void handle_ABRT (int)
49 {
50 // jump outta here to prevent abort() from trying too hard...
51 std::longjmp (jmp_env, 1);
52 }
53
54
55 static int c_comp (const void *x, const void *y)
56 {
57#ifndef _RWSTD_NO_EXCEPTIONS
58
59 // verify that a thrown exception can be caught
60 if (x >= global && x < global + sizeof global / sizeof *global)
61 throw x;
62
63#endif // _RWSTD_NO_EXCEPTIONS
64
65 return (*_RWSTD_STATIC_CAST (const UserClass*, x)).data_.val_
66 - (*_RWSTD_STATIC_CAST (const UserClass*, y)).data_.val_;
67 }
68}
69
70extern "C++" {
71
72 static int cxx_comp (const void *x, const void *y)
73 {
74#ifndef _RWSTD_NO_EXCEPTIONS
75
76 // verify that a thrown exception can be caught
77 if (x >= global && x < global + sizeof global / sizeof *global)
78 throw x;
79
80#endif // _RWSTD_NO_EXCEPTIONS
81
82 return (*_RWSTD_STATIC_CAST (const UserClass*, x)).data_.val_
83 - (*_RWSTD_STATIC_CAST (const UserClass*, y)).data_.val_;
84 }
85}
86
87
89// exrcises std::qqsort (25.4.4)
90static void
91test_qsort (int line,
92 const char *src,
93 std::size_t nsrc,
94 bool cxx)
95{
96 UserClass* const xsrc = UserClass::from_char (src, nsrc);
97 UserClass* const xsrc_end = xsrc + nsrc;
98 RW_ASSERT (0 == nsrc || 0 != xsrc);
99
100 if (cxx)
101 std::qsort (xsrc, nsrc, sizeof *xsrc, cxx_comp);
102 else
103 std::qsort (xsrc, nsrc, sizeof *xsrc, c_comp);
104
105 bool success = is_sorted_lt (xsrc, xsrc_end);
106 rw_assert (success, 0, line,
107 "line %d: extern \"C%{?}++%{;}\" qsort (\"%s\", ...) ==> "
108 "\"%{X=*.*}\" not sorted",
109 __LINE__, cxx, src, int (sizeof (*xsrc)), int (nsrc), -1, xsrc);
110
111 delete[] xsrc;
112}
113
114
116// exrcises std::qsort (25.4.4 Note)
117static void
118test_qsort_exception (int line,
119 int *src,
120 std::size_t nsrc,
121 bool cxx)
122{
123#ifndef _RWSTD_NO_EXCEPTIONS
124
125 // install a SIGABRT handler in case libc can't throw
126 // exceptions and aborts instead (e.g., glibc/gcc)
127 std::signal (SIGABRT, handle_ABRT);
128
129 bool success = false;
130 try {
131 if (0 == setjmp (jmp_env)) {
132 if (cxx)
133 std::qsort (src, nsrc, sizeof *src, cxx_comp);
134 else
135 std::qsort (src, nsrc, sizeof *src, c_comp);
136 }
137 else {
138 // prevent double assertion
139 success = true;
140 rw_assert (false, 0, line,
141 "line %d: extern \"C%{?}++%{;}\" qsort() aborted "
142 "on exception", __LINE__, cxx);
143 }
144 }
145 catch (const void* x) {
146 success = x >= src && x < src + nsrc;
147 }
148 catch (...) {
149 }
150
151 rw_assert (success, 0, line,
152 "line %d: extern \"C%{?}++%{;}\" qsort() failed to propagate "
153 "exception", __LINE__, cxx);
154
155#else // if defined (_RWSTD_NO_EXCEPTIONS)
156
158 _RWSTD_UNUSED (src);
160 _RWSTD_UNUSED (key);
161 _RWSTD_UNUSED (cxx);
162
163#endif // _RWSTD_NO_EXCEPTIONS
164}
165
166
168// exrcises std::bsearch (25.4.3)
169static void
170test_bsearch (int line,
171 const char *src,
172 std::size_t nsrc,
173 const char key_val,
174 std::size_t res,
175 bool cxx)
176{
177 UserClass* const xsrc = UserClass::from_char (src, nsrc,
178 true); // must be sorted
179 RW_ASSERT (0 == nsrc || 0 != xsrc);
180
181 UserClass key;
182 key.data_.val_ = key_val;
183
184 const void* result = cxx ?
185 std::bsearch (&key, xsrc, nsrc, sizeof *xsrc, cxx_comp)
186 : std::bsearch (&key, xsrc, nsrc, sizeof *xsrc, c_comp);
187
188 const UserClass* exp_res = res == _RWSTD_SIZE_MAX ? 0 : xsrc + res;
189
190 bool success = result == exp_res;
191 rw_assert (success, 0, line,
192 "line %d: extern \"C%{?}++%{;}\" bsearch (\"%s\", %#c, ...) "
193 "== %p, got %p, difference is %td elements",
194 __LINE__, cxx, src, key_val, result, exp_res,
195 _RWSTD_STATIC_CAST (const UserClass*, result) - exp_res);
196
197 delete[] xsrc;
198}
199
200
202// exrcises std::bsearch (25.4.4 Note)
203static void
204test_bsearch_exception (int line,
205 const int *src,
206 std::size_t nsrc,
207 const int *key,
208 bool cxx)
209{
210#ifndef _RWSTD_NO_EXCEPTIONS
211
212 // install a SIGABRT handler in case libc can't throw
213 // exceptions and aborts instead (e.g., glibc/gcc)
214 std::signal (SIGABRT, handle_ABRT);
215
216 bool success = false;
217 try {
218 if (0 == setjmp (jmp_env)) {
219 if (cxx)
220 std::bsearch (key, src, nsrc, sizeof *src, cxx_comp);
221 else
222 std::bsearch (key, src, nsrc, sizeof *src, c_comp);
223 }
224 else {
225 // prevent double assertion
226 success = true;
227 rw_assert (false, 0, line,
228 "line %d: extern \"C%{?}++%{;}\" bsearch() aborted "
229 "on exception", __LINE__, cxx);
230 }
231 }
232 catch (const void* x) {
233 success = x >= src && x < src + nsrc;
234 }
235 catch (...) {
236 }
237
238 rw_assert (success, 0, line,
239 "line %d: extern \"C%{?}++%{;}\" bsearch() failed to propagate "
240 "exception", __LINE__, cxx);
241
242#else // if defined (_RWSTD_NO_EXCEPTIONS)
243
245 _RWSTD_UNUSED (src);
247 _RWSTD_UNUSED (key);
248 _RWSTD_UNUSED (cxx);
249
250#endif // _RWSTD_NO_EXCEPTIONS
251}
252
253
255static int rw_opt_no_c; // --no-c
256static int rw_opt_no_cxx; // --no-cpp
257static int rw_opt_no_bsearch; // --no-bsearch
258static int rw_opt_no_qsort; // --no-qsort
259static int rw_opt_no_exceptions; // --no-exceptions
260
261
263static void
264test_qsort (bool cxx)
265{
266 rw_info (0, 0, 0,
267 "extern \"C%{?}++%{;}\" qsort (void*, size_t, size_t, "
268 "int (*compar)(const void*, const void*))", cxx);
269
270#define TEST(src) \
271 test_qsort (__LINE__, src, sizeof src - 1, cxx)
272
273 TEST ("a");
274
275 TEST ("ba");
276 TEST ("cba");
277 TEST ("dcba");
278 TEST ("edcba");
279 TEST ("fedcba");
280 TEST ("gfedcba");
281 TEST ("hgfedcba");
282 TEST ("ihgfedcba");
283 TEST ("jihgfedcba");
284
285 TEST ("ab");
286 TEST ("abc");
287 TEST ("abcd");
288 TEST ("abcde");
289 TEST ("abcdef");
290 TEST ("abcdefg");
291 TEST ("abcdefgh");
292 TEST ("abcdefghi");
293 TEST ("abcdefghij");
294
295 TEST ("aa");
296 TEST ("aabb");
297 TEST ("bbccaa");
298 TEST ("ddbbccaa");
299 TEST ("ddeebbccaa");
300
301 TEST ("aaaaaaaaaa");
302 TEST ("ababababab");
303 TEST ("bababababa");
304
305#undef TEST
306
307 if (rw_opt_no_exceptions) {
308 rw_note (0, 0, 0, "extern \"C%{?}++%{;}\" qsort() exceptions tests "
309 "disabled", cxx);
310 }
311 else {
312 test_qsort_exception (__LINE__, global,
313 sizeof global / sizeof *global, cxx);
314 }
315}
316
317
319static void
320test_bsearch (bool cxx)
321{
322 rw_info (0, 0, 0,
323 "extern \"C%{?}++%{;}\" bsearch (const void*, const void*, "
324 "size_t, size_t, int (*compar)(const void*, const void*))",
325 cxx);
326
327#define TEST(src, key, res) \
328 test_bsearch (__LINE__, src, sizeof src - 1, key, \
329 std::size_t (res), cxx)
330
331 TEST ("", 'a', -1);
332 TEST ("a", 'a', 0);
333 TEST ("a", 'b', -1);
334 TEST ("b", 'a', -1);
335
336 TEST ("ab", 'a', 0);
337 TEST ("ac", 'a', 0);
338 TEST ("ab", 'b', 1);
339 TEST ("bc", 'a', -1);
340
341 TEST ("acegi", 'i', 4);
342 TEST ("acegi", 'b', -1);
343 TEST ("acegi", 'g', 3);
344 TEST ("acegi", 'f', -1);
345 TEST ("acegi", 'e', 2);
346 TEST ("acegi", 'j', -1);
347 TEST ("acegi", 'c', 1);
348 TEST ("bdfhj", 'a', -1);
349
350 TEST ("abcdefghij", 'a', 0);
351 TEST ("abcdefghij", 'c', 2);
352 TEST ("abcdefghij", 'f', 5);
353 TEST ("abcdefghij", 'h', 7);
354 TEST ("abcdefghij", 'j', 9);
355
356#undef TEST
357
358 if (rw_opt_no_exceptions) {
359 rw_note (0, 0, 0, "extern \"C%{?}++%{;}\" bsearch() exceptions "
360 "tests disabled", cxx);
361 }
362 else {
363 test_bsearch_exception (__LINE__, global,
364 sizeof global / sizeof *global, global, cxx);
365 }
366}
367
368
370static void
371test_libc (bool cxx)
372{
373 if (rw_opt_no_qsort)
374 rw_note (0, 0, 0, "qsort test disabled");
375 else
376 test_qsort (cxx);
377
378 if (rw_opt_no_bsearch)
379 rw_note (0, 0, 0, "bsearch test disabled");
380 else
381 test_bsearch (cxx);
382}
383
384
386static int
387run_test (int, char*[])
388{
389 if (rw_opt_no_c)
390 rw_note (0, 0, 0, "tests of extern \"C\" cfunctions disabled");
391 else
392 test_libc (false);
393
394 if (rw_opt_no_cxx)
395 rw_note (0, 0, 0, "tests of extern \"C++\" functions disabled");
396 else
397 test_libc (true);
398
399 return 0;
400}
401
402
404int main (int argc, char *argv[])
405{
406 return rw_test (argc, argv, __FILE__,
407 "lib.alg.c.library",
408 0 /* no comment */,
409 run_test,
410 "|-no-extern_c# "
411 "|-no-extern_cxx# "
412 "|-no-bsearch# "
413 "|-no-qsort# "
414 "|-no-exceptions",
415 &rw_opt_no_c,
416 &rw_opt_no_cxx,
417 &rw_opt_no_bsearch,
418 &rw_opt_no_qsort,
419 &rw_opt_no_exceptions);
420}
#define y
Definition 17.names.cpp:141
#define line
Definition 17.names.cpp:490
#define res
Definition 17.names.cpp:531
#define x
Definition 17.names.cpp:140
volatile int result
const MyBuffer< char > nsrc[]
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define TEST(src)
#define main
void handle_ABRT(int)
#define setjmp
Definition _csetjmp.h:52
#define SIGABRT
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _RWSTD_STATIC_CAST(T, x)
Definition _defs.h:534
Definition json.h:5363
bool is_sorted_lt(InputIterator first, InputIterator last)
Definition rw_alg_test.h:75
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
Definition driver.cpp:1681
_TEST_EXPORT int rw_note(int, const char *, int, const char *,...)
Definition driver.cpp:1664
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630
#define RW_ASSERT(expr)
static UserClass from_char(char c)
Definition rw_value.h:221