]>
Commit | Line | Data |
---|---|---|
1 | # Torturing Bison. -*- Autotest -*- | |
2 | # Copyright (C) 2001, 2002 Free Software Foundation, Inc. | |
3 | ||
4 | # This program is free software; you can redistribute it and/or modify | |
5 | # it under the terms of the GNU General Public License as published by | |
6 | # the Free Software Foundation; either version 2, or (at your option) | |
7 | # any later version. | |
8 | ||
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. | |
13 | ||
14 | # You should have received a copy of the GNU General Public License | |
15 | # along with this program; if not, write to the Free Software | |
16 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
17 | # 02111-1307, USA. | |
18 | ||
19 | AT_BANNER([[Torture Tests.]]) | |
20 | ||
21 | ||
22 | ## ------------------------------------- ## | |
23 | ## Creating a large artificial grammar. ## | |
24 | ## ------------------------------------- ## | |
25 | ||
26 | # AT_DATA_TRIANGULAR_GRAMMAR(FILE-NAME, SIZE) | |
27 | # ------------------------------------------- | |
28 | # Create FILE-NAME, containing a self checking parser for a huge | |
29 | # triangular grammar. | |
30 | # FIXME: The `10 *' below are there to avoid clashes with predefined | |
31 | # tokens. These clashes should be exercised, I'm afraid something | |
32 | # is broken wrt previous Bisons. | |
33 | m4_define([AT_DATA_TRIANGULAR_GRAMMAR], | |
34 | [AT_DATA([[gengram.pl]], | |
35 | [[#! /usr/bin/perl -w | |
36 | ||
37 | use strict; | |
38 | my $max = $ARGV[0] || 10; | |
39 | ||
40 | print <<EOF; | |
41 | %{ | |
42 | #include <stdio.h> | |
43 | #include <stdlib.h> | |
44 | #include <assert.h> | |
45 | ||
46 | #define YYERROR_VERBOSE 1 | |
47 | #define YYDEBUG 1 | |
48 | ||
49 | static int yylex (void); | |
50 | static void yyerror (const char *msg); | |
51 | %} | |
52 | %union | |
53 | { | |
54 | int val; | |
55 | }; | |
56 | ||
57 | %token END "end" | |
58 | %type <val> exp input | |
59 | EOF | |
60 | ||
61 | for my $size (1 .. $max) | |
62 | { | |
63 | print "%token \"$size\" ", $size * 10, "\n"; | |
64 | }; | |
65 | ||
66 | print <<EOF; | |
67 | %% | |
68 | input: | |
69 | exp { assert (\@S|@1 == 0); \$\$ = \@S|@1; } | |
70 | | input exp { assert (\@S|@2 == \@S|@1 + 1); \$\$ = \@S|@2; } | |
71 | ; | |
72 | ||
73 | exp: | |
74 | END | |
75 | { \$\$ = 0; } | |
76 | EOF | |
77 | ||
78 | for my $size (1 .. $max) | |
79 | { | |
80 | use Text::Wrap; | |
81 | print wrap ("| ", " ", | |
82 | (map { "\"$_\"" } (1 .. $size)), | |
83 | " END \n"), | |
84 | " { \$\$ = $size; }\n"; | |
85 | }; | |
86 | print ";\n"; | |
87 | ||
88 | print <<EOF; | |
89 | %% | |
90 | static int | |
91 | yylex (void) | |
92 | { | |
93 | static int inner = 1; | |
94 | static int outer = 0; | |
95 | if (outer > $max) | |
96 | return 0; | |
97 | else if (inner > outer) | |
98 | { | |
99 | inner = 1; | |
100 | ++outer; | |
101 | return END; | |
102 | } | |
103 | return inner++ * 10; | |
104 | } | |
105 | ||
106 | static void | |
107 | yyerror (const char *msg) | |
108 | { | |
109 | fprintf (stderr, "%s\\n", msg); | |
110 | } | |
111 | ||
112 | int | |
113 | main (void) | |
114 | { | |
115 | yydebug = !!getenv ("YYDEBUG"); | |
116 | return yyparse (); | |
117 | } | |
118 | EOF | |
119 | ]]) | |
120 | ||
121 | AT_CHECK([perl -w ./gengram.pl $2 || exit 77], 0, [stdout]) | |
122 | mv stdout $1 | |
123 | ]) | |
124 | ||
125 | ||
126 | ## -------------- ## | |
127 | ## Big triangle. ## | |
128 | ## -------------- ## | |
129 | ||
130 | AT_SETUP([Big triangle]) | |
131 | ||
132 | # I have been able to go up to 2000 on my machine. | |
133 | # I tried 3000, a 29Mb grammar file, but then my system killed bison. | |
134 | AT_DATA_TRIANGULAR_GRAMMAR([input.y], [500]) | |
135 | AT_CHECK([bison input.y -v -o input.c]) | |
136 | AT_CHECK([$CC $CFLAGS $CPPFLAGS input.c -o input], 0, [], [ignore]) | |
137 | AT_CHECK([./input]) | |
138 | ||
139 | AT_CLEANUP | |
140 | ||
141 | ||
142 | ||
143 | # AT_DATA_HORIZONTAL_GRAMMAR(FILE-NAME, SIZE) | |
144 | # ------------------------------------------- | |
145 | # Create FILE-NAME, containing a self checking parser for a huge | |
146 | # horizontal grammar. | |
147 | # FIXME: The `10 *' below are there to avoid clashes with predefined | |
148 | # tokens. These clashes should be exercised, I'm afraid something | |
149 | # is broken wrt previous Bisons. | |
150 | m4_define([AT_DATA_HORIZONTAL_GRAMMAR], | |
151 | [AT_DATA([[gengram.pl]], | |
152 | [[#! /usr/bin/perl -w | |
153 | ||
154 | use strict; | |
155 | my $max = $ARGV[0] || 10; | |
156 | ||
157 | print <<EOF; | |
158 | %{ | |
159 | #include <stdio.h> | |
160 | #include <stdlib.h> | |
161 | #include <assert.h> | |
162 | ||
163 | #define YYERROR_VERBOSE 1 | |
164 | #define YYDEBUG 1 | |
165 | ||
166 | static int yylex (void); | |
167 | static void yyerror (const char *msg); | |
168 | %} | |
169 | EOF | |
170 | ||
171 | for my $size (1 .. $max) | |
172 | { | |
173 | print "%token \"$size\" ", $size * 10, "\n"; | |
174 | }; | |
175 | ||
176 | print <<EOF; | |
177 | %% | |
178 | EOF | |
179 | ||
180 | use Text::Wrap; | |
181 | ||
182 | wrap ("exp: ", " ", | |
183 | (map { "\"$_\"" } (1 .. $max)), ";"), | |
184 | "\n"; | |
185 | ||
186 | print <<EOF; | |
187 | %% | |
188 | static int | |
189 | yylex (void) | |
190 | { | |
191 | static int counter = 1; | |
192 | if (counter > $max) | |
193 | return 0; | |
194 | else | |
195 | return counter++ * 10; | |
196 | } | |
197 | ||
198 | static void | |
199 | yyerror (const char *msg) | |
200 | { | |
201 | fprintf (stderr, "%s\\n", msg); | |
202 | } | |
203 | ||
204 | int | |
205 | main (void) | |
206 | { | |
207 | yydebug = !!getenv ("YYDEBUG"); | |
208 | return yyparse (); | |
209 | } | |
210 | EOF | |
211 | ]]) | |
212 | ||
213 | AT_CHECK([perl -w ./gengram.pl $2 || exit 77], 0, [stdout]) | |
214 | mv stdout $1 | |
215 | ]) | |
216 | ||
217 | ||
218 | ## ---------------- ## | |
219 | ## Big horizontal. ## | |
220 | ## ---------------- ## | |
221 | ||
222 | AT_SETUP([Big horizontal]) | |
223 | ||
224 | # I have been able to go up to 10000 on my machine, but I had to | |
225 | # increase the maximum stack size (* 100). It gave: | |
226 | # | |
227 | # input.y 263k | |
228 | # input.tab.c 1.3M | |
229 | # input 453k | |
230 | # | |
231 | # gengram.pl 10000 0.70s user 0.01s sys 99% cpu 0.711 total | |
232 | # bison input.y 730.56s user 0.53s sys 99% cpu 12:12.34 total | |
233 | # gcc -Wall input.tab.c -o input 5.81s user 0.20s sys 100% cpu 6.01 total | |
234 | # ./input 0.00s user 0.01s sys 108% cpu 0.01 total | |
235 | # | |
236 | AT_DATA_HORIZONTAL_GRAMMAR([input.y], [1000]) | |
237 | AT_CHECK([bison input.y -v -o input.c]) | |
238 | AT_CHECK([$CC $CFLAGS $CPPFLAGS input.c -o input], 0, [], [ignore]) | |
239 | AT_CHECK([./input]) | |
240 | ||
241 | AT_CLEANUP | |
242 | ||
243 | ||
244 | ||
245 | # AT_DATA_STACK_TORTURE(C-PROLOGUE) | |
246 | # --------------------------------- | |
247 | # A parser specialized in torturing the stack size. | |
248 | m4_define([AT_DATA_STACK_TORTURE], | |
249 | [# A grammar of parens growing the stack thanks to right recursion. | |
250 | # exp: | |
251 | AT_DATA([input.y], | |
252 | [[%{ | |
253 | #include <stdio.h> | |
254 | #include <stdlib.h> | |
255 | #include <assert.h> | |
256 | ]$1[ | |
257 | static int yylex (void); | |
258 | static void yyerror (const char *msg); | |
259 | #define YYPRINT(File, Type, Value) \ | |
260 | fprintf (File, " (%d, stack size = %d, max = %d)", \ | |
261 | Value, yyssp - yyss + 1, yystacksize); | |
262 | %} | |
263 | %error-verbose | |
264 | %debug | |
265 | %token WAIT_FOR_EOF | |
266 | %% | |
267 | exp: WAIT_FOR_EOF exp | ; | |
268 | %% | |
269 | static void | |
270 | yyerror (const char *msg) | |
271 | { | |
272 | fprintf (stderr, "%s\n", msg); | |
273 | exit (1); | |
274 | } | |
275 | ||
276 | /* There are YYLVAL_MAX of WAIT_FOR_EOFs. */ | |
277 | unsigned int yylval_max; | |
278 | ||
279 | static int | |
280 | yylex (void) | |
281 | { | |
282 | if (yylval--) | |
283 | return WAIT_FOR_EOF; | |
284 | else | |
285 | return EOF; | |
286 | } | |
287 | ||
288 | int | |
289 | main (int argc, const char **argv) | |
290 | { | |
291 | assert (argc == 2); | |
292 | yylval = atoi (argv[1]); | |
293 | yydebug = 1; | |
294 | return yyparse (); | |
295 | } | |
296 | ]]) | |
297 | AT_CHECK([bison input.y -o input.c]) | |
298 | AT_CHECK([$CC $CFLAGS $CPPFLAGS input.c -o input], 0, [], [ignore]) | |
299 | ]) | |
300 | ||
301 | ||
302 | ## -------------------------------------- ## | |
303 | ## Exploding the Stack Size with Alloca. ## | |
304 | ## -------------------------------------- ## | |
305 | ||
306 | AT_SETUP([Exploding the Stack Size with Alloca]) | |
307 | ||
308 | AT_DATA_STACK_TORTURE | |
309 | ||
310 | # Below the limit of 200. | |
311 | AT_CHECK([./input 20], 0, [], [ignore]) | |
312 | # Two enlargements: 2 * 2 * 200. | |
313 | AT_CHECK([./input 900], 0, [], [ignore]) | |
314 | # Fails: beyond the limit of 10,000 (which we don't reach anyway since we | |
315 | # multiply by two starting at 200 => 5120 is the last possible). | |
316 | AT_CHECK([./input 10000], 1, [], [ignore]) | |
317 | ||
318 | AT_CLEANUP | |
319 | ||
320 | ||
321 | ||
322 | ||
323 | ## -------------------------------------- ## | |
324 | ## Exploding the Stack Size with Malloc. ## | |
325 | ## -------------------------------------- ## | |
326 | ||
327 | AT_SETUP([Exploding the Stack Size with Malloc]) | |
328 | ||
329 | AT_DATA_STACK_TORTURE([[#define YYSTACK_USE_ALLOCA 0]]) | |
330 | ||
331 | # Below the limit of 200. | |
332 | AT_CHECK([./input 20], 0, [], [ignore]) | |
333 | # Two enlargements: 2 * 2 * 200. | |
334 | AT_CHECK([./input 900], 0, [], [ignore]) | |
335 | # Fails: beyond the limit of 10,000 (which we don't reach anyway since we | |
336 | # multiply by two starting at 200 => 5120 is the possible). | |
337 | AT_CHECK([./input 10000], 1, [], [ignore]) | |
338 | ||
339 | AT_CLEANUP |