debian/: Bump to Debhelper 10.
[sod] / test / kwtest.c
1 /* -*-c-*-
2 *
3 * Test program for the keyword-argument machinery
4 *
5 * (c) 2015 Straylight/Edgeware
6 */
7
8 /*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of the Sensible Object Design, an object system for C.
11 *
12 * SOD is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * SOD is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with SOD; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
27 #include <setjmp.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 #include "keyword.h"
33
34 static void show_kwval(const char *what, int f, const char *fmt, ...)
35 {
36 va_list ap;
37
38 printf(" %s = ", what);
39 if (!f)
40 puts("<unset>");
41 else {
42 va_start(ap, fmt);
43 vprintf(fmt, ap);
44 va_end(ap);
45 putchar('\n');
46 }
47 }
48
49 #define SHOW(mem, fmt) show_kwval(#mem, kw.mem##_suppliedp, fmt, kw.mem)
50
51 #define t1_KWSET(_) \
52 _(int, x, 0) \
53 _(double, y, 69.0) \
54 _(const char *, z, "default")
55 KWSET_STRUCT(t1);
56 static KWSET_PARSEFN(t1)
57 static KWCALL void t1(const char *what, KWTAIL)
58 {
59 KWPARSE(t1);
60
61 printf("t1: %s\n", what);
62 SHOW(x, "%d");
63 SHOW(y, "%g");
64 SHOW(z, "`%s'");
65 }
66
67 static KWCALL void t2(const char *what, ...)
68 {
69 va_list ap;
70
71 printf("t2: %s\n", what);
72 va_start(ap, what);
73 t1("via t2", KWARGS(K_VALIST(ap)));
74 va_end(ap);
75 }
76
77 #define t3_KWSET(_) \
78 _(int, q, 0) \
79 t1_KWSET(_)
80 KWSET_STRUCT(t3);
81 static KWSET_PARSEFN(t3)
82 static KWCALL void t3(const char *what, KWTAIL)
83 {
84 struct kwval v[KW_COUNT(t1)];
85 size_t n = 0;
86 KWPARSE(t3);
87
88 printf("t3: %s\n", what);
89 SHOW(q, "%c");
90 SHOW(z, "`%s'");
91
92 KW_COPY(t3, t1, kw, v, n);
93 t1("via t3", KWARGS(K_TAB(v, n)
94 K(x, kw.x_suppliedp ? kw.x + 1 : 42)));
95 }
96
97 /* The @KW_TEST@ machinery from the manpage... */
98 #define KWARGS_TEST(k, val) KWARGS(K(k, val) K(kw.unknown, 0))
99
100 static jmp_buf kw_test_jmp;
101
102 static void kw_test_unknown(const char *set, const char *kw)
103 {
104 if (strcmp(kw, "kw.unknown") == 0) longjmp(kw_test_jmp, 1);
105 else longjmp(kw_test_jmp, 2);
106 }
107
108 #define KW_TEST(flag, set, call) do { \
109 kw_unkhookfn *oldunk = kw_unkhook; \
110 kw_unkhook = kw_test_unknown; \
111 switch (setjmp(kw_test_jmp)) { \
112 case 0: call; abort(); \
113 case 1: flag = 1; break; \
114 case 2: flag = 0; break; \
115 default: abort(); \
116 } \
117 kw_unkhook = oldunk; \
118 } while (0)
119 /* END */
120
121 int main(void)
122 {
123 t1("no args", NO_KWARGS);
124 t1("some args", KWARGS(K(z, "set") K(x, 42)));
125
126 t2("indirection", KWARGS(K(y, 6.283)));
127
128 t3("no args", NO_KWARGS);
129 t3("x initially 19", KWARGS(K(q, 't') K(x, 19) K(z, "boing")));
130
131 #define TEST_KWTEST(kw, val) do { \
132 int f_; \
133 KW_TEST(f_, t3, t3(0, KWARGS_TEST(kw, val))); \
134 printf("t3 arg `%s' %s\n", #kw, f_ ? "present" : "absent"); \
135 } while (0)
136 TEST_KWTEST(q, '!');
137 TEST_KWTEST(z, "splat");
138 TEST_KWTEST(nope, 0);
139
140 return (0);
141 }
142
143 /*----- That's all, folks -------------------------------------------------*/