Commit | Line | Data |
---|---|---|
e6591bec MW |
1 | /* -*-c-*- |
2 | * | |
3 | * Test the control-flow metaprogramming macros | |
4 | * | |
5 | * (c) 2022 Straylight/Edgeware | |
6 | */ | |
7 | ||
8 | /*----- Licensing notice --------------------------------------------------* | |
9 | * | |
10 | * This file is part of the mLib utilities library. | |
11 | * | |
12 | * mLib is free software: you can redistribute it and/or modify it under | |
13 | * the terms of the GNU Library General Public License as published by | |
14 | * the Free Software Foundation; either version 2 of the License, or (at | |
15 | * your option) any later version. | |
16 | * | |
17 | * mLib is distributed in the hope that it will be useful, but WITHOUT | |
18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
19 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public | |
20 | * License for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU Library General Public | |
23 | * License along with mLib. If not, write to the Free Software | |
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
25 | * USA. | |
26 | */ | |
27 | ||
28 | /*----- Header files ------------------------------------------------------*/ | |
29 | ||
30 | #include <stdio.h> | |
31 | #include <stdlib.h> | |
32 | ||
33 | #include "control.h" | |
34 | ||
35 | /*----- Main code ---------------------------------------------------------*/ | |
36 | ||
37 | static int step = 0; | |
38 | static int rc = 0; | |
39 | ||
40 | #define STEP(s) check_step(s, __FILE__ ": " STR(__LINE__)) | |
41 | #define MISSTEP STEP(-1) | |
42 | static void check_step(int s, const char *where) | |
43 | { | |
44 | if (step != s) { | |
45 | fprintf(stderr, "misstep at %s: expected %d but found %d\n", | |
46 | where, step, s); | |
47 | rc = 2; | |
48 | } | |
49 | step++; | |
50 | } | |
51 | ||
52 | #define LASTSTEP(s) laststep(s, __FILE__ ": " STR(__LINE__)) | |
53 | static void laststep(int s, const char *where) | |
54 | { check_step(s, where); step = 0; } | |
55 | ||
2edecb46 MW |
56 | #define FORELSE(head) \ |
57 | MC_GOTO(top) \ | |
58 | MC_LABEL(out) MC_ACT({ ; }) \ | |
59 | MC_LABEL(top) ALLOWELSE(els) \ | |
60 | AFTER(outer, { GOELSE(els); }) \ | |
61 | for (head) \ | |
62 | WRAP(inner, { ; }, \ | |
63 | { ; }, \ | |
64 | { MC_GOTO(out); }) | |
65 | ||
e6591bec | 66 | #define FOR_FIZZBUZZ(var, base, limit) \ |
2edecb46 MW |
67 | MC_GOTO(top) \ |
68 | MC_LABEL(out) MC_ACT({ ; }) \ | |
69 | MC_LABEL(top) DECL(bounds, \ | |
70 | int _i = base COMMA _limit = limit) \ | |
71 | for (; _i < _limit; _i++) \ | |
72 | DECL(buf, char _buf[24]) \ | |
73 | DECL(var, const char *var) \ | |
74 | WRAP(wrap, { \ | |
75 | switch (_i%15) { \ | |
76 | case 0: \ | |
77 | var = "fizzbuzz"; \ | |
78 | break; \ | |
79 | case 3: case 6: case 9: case 12: \ | |
80 | var = "fizz"; \ | |
81 | break; \ | |
82 | case 5: case 10: \ | |
83 | var = "buzz"; \ | |
84 | break; \ | |
85 | default: \ | |
86 | sprintf(_buf, "%d", _i); var = _buf; \ | |
87 | break; \ | |
88 | } \ | |
89 | }, \ | |
90 | { ; }, \ | |
91 | { MC_GOTO(out); }) | |
e6591bec MW |
92 | |
93 | int main(void) | |
94 | { | |
2edecb46 MW |
95 | int i; |
96 | ||
65135ebd MW |
97 | BEFORE(before0, { STEP(0); }) STEP(1); |
98 | AFTER(after0, { STEP(3); }) STEP(2); | |
e6591bec MW |
99 | LASTSTEP(4); |
100 | ||
101 | WRAP(wrap0, { STEP(0); }, { STEP(2); }, { MISSTEP; }) STEP(1); | |
102 | WRAP(wrap1, { STEP(3); }, { MISSTEP; }, { STEP(5); }) { STEP(4); break; } | |
103 | LASTSTEP(6); | |
104 | ||
55d45d31 MW |
105 | STEP(0); |
106 | for (;;) { | |
107 | AFTER(after1, { STEP(2); break; }) STEP(1); | |
108 | MISSTEP; break; | |
109 | } | |
110 | LASTSTEP(3); | |
111 | ||
2edecb46 MW |
112 | FORELSE (i = 0; i < 10; i++) { |
113 | STEP(i); | |
114 | if (i == 7) break; | |
115 | } else | |
116 | MISSTEP; | |
117 | LASTSTEP(8); | |
118 | ||
119 | FORELSE (i = 0; i < 10; i++) { | |
120 | STEP(i); | |
121 | if (i == 12) break; | |
122 | } else | |
123 | STEP(10); | |
124 | LASTSTEP(11); | |
125 | ||
126 | #define TEST \ | |
127 | MC_ACT({ STEP(0); MC_GOTO(in_plain); }) \ | |
128 | MC_LABEL(done_plain) MC_ACT({ STEP(5); GOELSE(elsie); }) \ | |
129 | MC_LABEL(in_plain) WRAP(outer_wrap, { STEP(1); }, \ | |
130 | { STEP(7); }, \ | |
131 | { MISSTEP; }) \ | |
132 | ALLOWELSE(elsie) \ | |
133 | WRAP(inner_wrap, { STEP(2); }, \ | |
134 | { STEP(4); \ | |
135 | MC_GOTO(done_plain); }, \ | |
136 | { MISSTEP; }) \ | |
137 | STEP(3); \ | |
138 | else \ | |
139 | STEP(6); \ | |
140 | LASTSTEP(8); | |
141 | TEST | |
142 | #undef TEST | |
143 | ||
144 | #if __STDC_VERSION__ >= 199901 || defined(__cplusplus) | |
e6591bec | 145 | STEP(0); |
2edecb46 | 146 | DECL(decl0, int j = 1) STEP(j); |
e6591bec | 147 | LASTSTEP(2); |
2edecb46 | 148 | #endif |
e6591bec | 149 | |
55d45d31 | 150 | FOR_FIZZBUZZ(fb, 19, 32) printf("%s\n", fb); |
e6591bec MW |
151 | |
152 | return (rc); | |
153 | } | |
154 | ||
155 | /*----- That's all, folks -------------------------------------------------*/ |