chiark / gitweb /
lib/: Pure C machinery for handling `keyword arguments' to functions.
[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 -------------------------------------------------*/