doc/output.tex: Add a missing member reference in vtable initializer.
[sod] / test / kwtest.c
CommitLineData
9e91c8e7
MW
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
34static 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")
55KWSET_STRUCT(t1);
56static KWSET_PARSEFN(t1)
57static 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
67static 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(_)
80KWSET_STRUCT(t3);
81static KWSET_PARSEFN(t3)
82static 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
100static jmp_buf kw_test_jmp;
101
102static 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
121int 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 -------------------------------------------------*/