Commit | Line | Data |
---|---|---|
1dcdf455 RK |
1 | /* |
2 | * This file is part of DisOrder. | |
3 | * Copyright (C) 2008 Richard Kettlewell | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |
18 | * USA | |
19 | */ | |
20 | #include "test.h" | |
21 | #include "macros.h" | |
22 | ||
23 | static void test_macros(void) { | |
24 | const struct mx_node *m; | |
25 | #define L1 "this is just some\n" | |
26 | #define L2 "plain text\n" | |
27 | static const char plain[] = L1 L2; | |
b36be3a1 | 28 | char *s; |
1dcdf455 | 29 | |
b36be3a1 RK |
30 | /* Plain text ------------------------------------------------------------- */ |
31 | ||
1dcdf455 RK |
32 | /* As simple as it gets */ |
33 | m = mx_parse("plaintext1", 1, "", NULL); | |
34 | insist(m == 0); | |
35 | ||
36 | /* Almost as simple as that */ | |
37 | m = mx_parse("plaintext1", 1, plain, NULL); | |
915ea29a | 38 | check_integer(m->type, MX_TEXT); |
1dcdf455 | 39 | check_string(m->filename, "plaintext1"); |
915ea29a | 40 | check_integer(m->line, 1); |
1dcdf455 RK |
41 | check_string(m->text, L1 L2); |
42 | insist(m->next == 0); | |
9dbb630e | 43 | check_string(mx_dump(m), plain); |
1dcdf455 RK |
44 | |
45 | /* Check that partial parses stop in the right place */ | |
46 | m = mx_parse("plaintext2", 5, plain, plain + strlen(L1)); | |
915ea29a | 47 | check_integer(m->type, MX_TEXT); |
1dcdf455 | 48 | check_string(m->filename, "plaintext2"); |
915ea29a | 49 | check_integer(m->line, 5); |
1dcdf455 RK |
50 | check_string(m->text, L1); |
51 | insist(m->next == 0); | |
9dbb630e | 52 | check_string(mx_dump(m), L1); |
1dcdf455 | 53 | |
b36be3a1 RK |
54 | /* Simple macro parsing --------------------------------------------------- */ |
55 | ||
1dcdf455 RK |
56 | /* The simplest possible expansion */ |
57 | m = mx_parse("macro1", 1, "@macro@", NULL); | |
915ea29a | 58 | check_integer(m->type, MX_EXPANSION); |
1dcdf455 | 59 | check_string(m->filename, "macro1"); |
915ea29a | 60 | check_integer(m->line, 1); |
1dcdf455 | 61 | check_string(m->name, "macro"); |
915ea29a | 62 | check_integer(m->nargs, 0); |
1dcdf455 RK |
63 | insist(m->args == 0); |
64 | insist(m->next == 0); | |
9dbb630e | 65 | check_string(mx_dump(m), "@macro@"); |
1dcdf455 RK |
66 | |
67 | /* Spacing variants of the above */ | |
68 | m = mx_parse("macro2", 1, "@ macro@", NULL); | |
915ea29a | 69 | check_integer(m->type, MX_EXPANSION); |
1dcdf455 | 70 | check_string(m->filename, "macro2"); |
915ea29a | 71 | check_integer(m->line, 1); |
1dcdf455 | 72 | check_string(m->name, "macro"); |
915ea29a | 73 | check_integer(m->nargs, 0); |
1dcdf455 RK |
74 | insist(m->args == 0); |
75 | insist(m->next == 0); | |
9dbb630e | 76 | check_string(mx_dump(m), "@macro@"); |
1dcdf455 | 77 | m = mx_parse("macro3", 1, "@macro @", NULL); |
915ea29a | 78 | check_integer(m->type, MX_EXPANSION); |
1dcdf455 | 79 | check_string(m->filename, "macro3"); |
915ea29a | 80 | check_integer(m->line, 1); |
1dcdf455 | 81 | check_string(m->name, "macro"); |
915ea29a | 82 | check_integer(m->nargs, 0); |
1dcdf455 RK |
83 | insist(m->args == 0); |
84 | insist(m->next == 0); | |
9dbb630e | 85 | check_string(mx_dump(m), "@macro@"); |
1dcdf455 RK |
86 | |
87 | /* Unterminated variants */ | |
88 | m = mx_parse("macro4", 1, "@macro", NULL); | |
915ea29a | 89 | check_integer(m->type, MX_EXPANSION); |
1dcdf455 | 90 | check_string(m->filename, "macro4"); |
915ea29a | 91 | check_integer(m->line, 1); |
1dcdf455 | 92 | check_string(m->name, "macro"); |
915ea29a | 93 | check_integer(m->nargs, 0); |
1dcdf455 RK |
94 | insist(m->args == 0); |
95 | insist(m->next == 0); | |
9dbb630e | 96 | check_string(mx_dump(m), "@macro@"); |
1dcdf455 | 97 | m = mx_parse("macro5", 1, "@macro ", NULL); |
915ea29a | 98 | check_integer(m->type, MX_EXPANSION); |
1dcdf455 | 99 | check_string(m->filename, "macro5"); |
915ea29a | 100 | check_integer(m->line, 1); |
1dcdf455 | 101 | check_string(m->name, "macro"); |
915ea29a | 102 | check_integer(m->nargs, 0); |
1dcdf455 RK |
103 | insist(m->args == 0); |
104 | insist(m->next == 0); | |
9dbb630e | 105 | check_string(mx_dump(m), "@macro@"); |
1dcdf455 RK |
106 | |
107 | /* Macros with a :-separated argument */ | |
108 | m = mx_parse("macro5", 1, "@macro:arg@", NULL); | |
915ea29a | 109 | check_integer(m->type, MX_EXPANSION); |
1dcdf455 | 110 | check_string(m->filename, "macro5"); |
915ea29a | 111 | check_integer(m->line, 1); |
1dcdf455 | 112 | check_string(m->name, "macro"); |
915ea29a | 113 | check_integer(m->nargs, 1); |
1dcdf455 RK |
114 | insist(m->next == 0); |
115 | ||
915ea29a | 116 | check_integer(m->args[0]->type, MX_TEXT); |
1dcdf455 | 117 | check_string(m->args[0]->filename, "macro5"); |
915ea29a | 118 | check_integer(m->args[0]->line, 1); |
1dcdf455 RK |
119 | check_string(m->args[0]->text, "arg"); |
120 | insist(m->args[0]->next == 0); | |
121 | ||
9dbb630e RK |
122 | check_string(mx_dump(m), "@macro{arg}@"); |
123 | ||
1dcdf455 RK |
124 | /* Multiple :-separated arguments, and spacing, and newlines */ |
125 | m = mx_parse("macro6", 1, "@macro : \n arg1 : \n arg2@", NULL); | |
915ea29a | 126 | check_integer(m->type, MX_EXPANSION); |
1dcdf455 | 127 | check_string(m->filename, "macro6"); |
915ea29a | 128 | check_integer(m->line, 1); |
1dcdf455 | 129 | check_string(m->name, "macro"); |
915ea29a | 130 | check_integer(m->nargs, 2); |
1dcdf455 RK |
131 | insist(m->next == 0); |
132 | ||
915ea29a | 133 | check_integer(m->args[0]->type, MX_TEXT); |
1dcdf455 | 134 | check_string(m->args[0]->filename, "macro6"); |
915ea29a | 135 | check_integer(m->args[0]->line, 2); |
1dcdf455 RK |
136 | check_string(m->args[0]->text, "arg1"); |
137 | insist(m->args[0]->next == 0); | |
138 | ||
915ea29a | 139 | check_integer(m->args[1]->type, MX_TEXT); |
1dcdf455 | 140 | check_string(m->args[1]->filename, "macro6"); |
915ea29a | 141 | check_integer(m->args[1]->line, 3); |
1dcdf455 RK |
142 | check_string(m->args[1]->text, "arg2"); |
143 | insist(m->args[1]->next == 0); | |
144 | ||
9dbb630e RK |
145 | check_string(mx_dump(m), "@macro{arg1}{arg2}@"); |
146 | ||
147 | /* Multiple bracketed arguments */ | |
915ea29a RK |
148 | m = mx_parse("macro7", 1, "@macro{arg1}{arg2}@", NULL); |
149 | check_string(mx_dump(m), "@macro{arg1}{arg2}@"); | |
150 | ||
774eb34c | 151 | m = mx_parse("macro8", 1, "@macro{\narg1}{\narg2}@", NULL); |
915ea29a RK |
152 | check_string(mx_dump(m), "@macro{\narg1}{\narg2}@"); |
153 | check_integer(m->args[0]->line, 1); | |
154 | check_integer(m->args[1]->line, 2); | |
155 | /* ...yes, lines 1 and 2: the first character of the first arg is | |
774eb34c | 156 | * the \n at the end of line 1. Compare with macro9: */ |
1dcdf455 | 157 | |
774eb34c | 158 | m = mx_parse("macro9", 1, "@macro\n{arg1}\n{arg2}@", NULL); |
915ea29a RK |
159 | check_string(mx_dump(m), "@macro{arg1}{arg2}@"); |
160 | check_integer(m->args[0]->line, 2); | |
161 | check_integer(m->args[1]->line, 3); | |
774eb34c RK |
162 | |
163 | /* Arguments that themselves contain expansions */ | |
164 | m = mx_parse("macro10", 1, "@macro{@macro2{arg1}{arg2}@}@", NULL); | |
165 | check_string(mx_dump(m), "@macro{@macro2{arg1}{arg2}@}@"); | |
166 | ||
167 | /* ...and with omitted trailing @ */ | |
168 | m = mx_parse("macro11", 1, "@macro{@macro2{arg1}{arg2}}", NULL); | |
169 | check_string(mx_dump(m), "@macro{@macro2{arg1}{arg2}@}@"); | |
49472b7d RK |
170 | |
171 | /* Similarly but with more whitespace; NB that the whitespace is | |
172 | * preserved. */ | |
173 | m = mx_parse("macro12", 1, "@macro {@macro2 {arg1} {arg2} }\n", NULL); | |
174 | check_string(mx_dump(m), "@macro{@macro2{arg1}{arg2}@ }@\n"); | |
b36be3a1 RK |
175 | |
176 | /* Simple expansions ------------------------------------------------------ */ | |
177 | ||
178 | mx_register_builtin(); | |
179 | ||
180 | #define check_macro(NAME, INPUT, OUTPUT) do { \ | |
181 | m = mx_parse(NAME, 1, INPUT, NULL); \ | |
182 | check_integer(mx_expandstr(m, &s, 0/*u*/, NAME), 0); \ | |
183 | if(s && strcmp(s, OUTPUT)) { \ | |
184 | fprintf(stderr, "%s:%d: test %s\n" \ | |
c617bac5 | 185 | " INPUT:\n%s\n" \ |
b36be3a1 RK |
186 | " EXPECTED: '%s'\n" \ |
187 | " GOT: '%s'\n", \ | |
188 | __FILE__, __LINE__, NAME, INPUT, OUTPUT, s); \ | |
189 | count_error(); \ | |
190 | } \ | |
191 | } while(0) | |
192 | ||
193 | check_macro("empty", "", ""); | |
194 | check_macro("plain", plain, plain); | |
195 | ||
196 | check_macro("if1", "@if{true}{yes}{no}", "yes"); | |
197 | check_macro("if2", "@if{true}{yes}", "yes"); | |
198 | check_macro("if3", "@if{false}{yes}{no}", "no"); | |
199 | check_macro("if4", "@if{false}{yes}", ""); | |
200 | check_macro("if5", "@if{ true}{yes}", ""); | |
201 | ||
202 | check_macro("and1", "@and", "true"); | |
203 | check_macro("and2", "@and{true}", "true"); | |
204 | check_macro("and3", "@and{false}", "false"); | |
205 | check_macro("and4", "@and{true}{true}", "true"); | |
206 | check_macro("and5", "@and{false}{true}", "false"); | |
207 | check_macro("and6", "@and{true}{false}", "false"); | |
208 | check_macro("and7", "@and{false}{false}", "false"); | |
209 | ||
210 | check_macro("or1", "@or", "false"); | |
211 | check_macro("or2", "@or{true}", "true"); | |
212 | check_macro("or2", "@or{false}", "false"); | |
213 | check_macro("or3", "@or{true}{true}", "true"); | |
214 | check_macro("or4", "@or{false}{true}", "true"); | |
215 | check_macro("or5", "@or{true}{false}", "true"); | |
216 | check_macro("or7", "@or{false}{false}", "false"); | |
217 | ||
218 | check_macro("not1", "@not{true}", "false"); | |
219 | check_macro("not2", "@not{false}", "true"); | |
220 | check_macro("not3", "@not{wibble}", "true"); | |
221 | ||
222 | check_macro("comment1", "@#{wibble}", ""); | |
223 | check_macro("comment2", "@#{comment with a\nnewline in}", ""); | |
224 | ||
225 | check_macro("discard1", "@discard{wibble}", ""); | |
226 | check_macro("discard2", "@discard{comment with a\nnewline in}", ""); | |
227 | ||
228 | check_macro("eq1", "@eq", "true"); | |
229 | check_macro("eq2", "@eq{}", "true"); | |
230 | check_macro("eq3", "@eq{a}", "true"); | |
231 | check_macro("eq4", "@eq{a}{a}", "true"); | |
232 | check_macro("eq5", "@eq{a}{a}{a}", "true"); | |
233 | check_macro("eq7", "@eq{a}{b}", "false"); | |
234 | check_macro("eq8", "@eq{a}{b}{a}", "false"); | |
235 | check_macro("eq9", "@eq{a}{a}{b}", "false"); | |
236 | check_macro("eq10", "@eq{b}{a}{a}", "false"); | |
237 | ||
238 | check_macro("ne1", "@ne", "true"); | |
239 | check_macro("ne2", "@ne{}", "true"); | |
240 | check_macro("ne3", "@ne{a}", "true"); | |
241 | check_macro("ne4", "@ne{a}{a}", "false"); | |
242 | check_macro("ne5", "@ne{a}{a}{a}", "false"); | |
243 | check_macro("ne7", "@ne{a}{b}", "true"); | |
244 | check_macro("ne8", "@ne{a}{b}{a}", "false"); | |
245 | check_macro("ne9", "@ne{a}{a}{b}", "false"); | |
246 | check_macro("ne10", "@ne{b}{a}{a}", "false"); | |
247 | check_macro("ne11", "@ne{a}{b}{c}", "true"); | |
248 | ||
249 | check_macro("sh1", "@shell{true}", ""); | |
250 | check_macro("sh2", "@shell{echo spong}", "spong\n"); | |
8fc93a37 | 251 | fprintf(stderr, "expect error message from macro expander:\n"); |
b36be3a1 RK |
252 | check_macro("sh3", "@shell{echo spong;exit 3}", "spong\n"); |
253 | ||
254 | check_macro("url1", "@urlquote{unreserved}", "unreserved"); | |
255 | check_macro("url2", "@urlquote{has space}", "has%20space"); | |
256 | check_macro("url3", "@urlquote{\xc0\xc1}", "%c0%c1"); | |
257 | ||
8fc93a37 RK |
258 | /* Macro definitions ------------------------------------------------------ */ |
259 | ||
260 | check_macro("macro1", "@define{m}{a b c}{@c@ @b@ @a@}@" | |
261 | "@m{1}{2}{3}", | |
262 | "3 2 1"); | |
c617bac5 RK |
263 | check_macro("macro2", "@m{b}{c}{a}", |
264 | "a c b"); | |
265 | check_macro("macro3", "@m{@eq{z}{z}}{p}{q}", | |
266 | "q p true"); | |
267 | check_macro("macro4", | |
268 | "@discard{\n" | |
269 | " @define{n}{a b c}\n" | |
270 | " {@if{@eq{@a@}{@b@}} {@c@} {no}}\n" | |
271 | "}@" | |
272 | "@n{x}{y}{z}", | |
273 | "no"); | |
274 | check_macro("macro5", | |
275 | "@n{x}{x}{z}", | |
276 | "z"); | |
277 | ||
1dcdf455 RK |
278 | } |
279 | ||
280 | TEST(macros); | |
281 | ||
282 | /* | |
283 | Local Variables: | |
284 | c-basic-offset:2 | |
285 | comment-column:40 | |
286 | fill-column:79 | |
287 | indent-tabs-mode:nil | |
288 | End: | |
289 | */ |