Remove ASR_MEASURE_PERFORMANCE, it doesn't work anyway.
[dragonfly.git] / games / atc / grammar.y
1 /*-
2  * Copyright (c) 1990, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ed James.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * @(#)grammar.y        8.1 (Berkeley) 5/31/93
37  */
38
39 /*
40  * Copyright (c) 1987 by Ed James, UC Berkeley.  All rights reserved.
41  *
42  * Copy permission is hereby granted provided that this notice is
43  * retained on all partial or complete copies.
44  *
45  * For more info on this and all of my stuff, mail edjames@berkeley.edu.
46  */
47
48 %token <ival>   HeightOp
49 %token <ival>   WidthOp
50 %token <ival>   UpdateOp
51 %token <ival>   NewplaneOp
52 %token <cval>   DirOp
53 %token <ival>   ConstOp
54 %token <ival>   LineOp
55 %token <ival>   AirportOp
56 %token <ival>   BeaconOp
57 %token <ival>   ExitOp
58 %union {
59         int     ival;
60         char    cval;
61 }
62
63 %{
64 #include "include.h"
65
66 int     errors = 0;
67 int     line = 1;
68 %}
69
70 %%
71 file:
72         bunch_of_defs { if (checkdefs() < 0) return (errors); } bunch_of_lines
73                 { 
74                 if (sp->num_exits + sp->num_airports < 2)
75                         yyerror("Need at least 2 airports and/or exits.");
76                 return (errors);
77                 }
78         ;
79
80 bunch_of_defs:
81         def bunch_of_defs
82         | def
83         ;
84
85 def:
86         udef
87         | ndef
88         | wdef
89         | hdef
90         ;
91
92 udef:
93         UpdateOp '=' ConstOp ';'
94                 {
95                 if (sp->update_secs != 0)
96                         return (yyerror("Redefinition of 'update'."));
97                 else if ($3 < 1)
98                         return (yyerror("'update' is too small."));
99                 else
100                         sp->update_secs = $3;
101                 }
102         ;
103
104 ndef:
105         NewplaneOp '=' ConstOp ';'
106                 {
107                 if (sp->newplane_time != 0)
108                         return (yyerror("Redefinition of 'newplane'."));
109                 else if ($3 < 1)
110                         return (yyerror("'newplane' is too small."));
111                 else
112                         sp->newplane_time = $3;
113                 }
114         ;
115
116 hdef:
117         HeightOp '=' ConstOp ';'
118                 {
119                 if (sp->height != 0)
120                         return (yyerror("Redefinition of 'height'."));
121                 else if ($3 < 3)
122                         return (yyerror("'height' is too small."));
123                 else
124                         sp->height = $3; 
125                 }
126         ;
127
128 wdef:
129         WidthOp '=' ConstOp ';'
130                 {
131                 if (sp->height != 0)
132                         return (yyerror("Redefinition of 'width'."));
133                 else if ($3 < 3)
134                         return (yyerror("'width' is too small."));
135                 else
136                         sp->width = $3; 
137                 }
138         ;
139
140 bunch_of_lines:
141         line bunch_of_lines
142                 {}
143         | line
144                 {}
145         ;
146
147 line:
148         BeaconOp ':' Bpoint_list ';'
149                 {}
150         | ExitOp ':' Epoint_list ';'
151                 {}
152         | LineOp ':' Lline_list ';'
153                 {}
154         | AirportOp ':' Apoint_list ';'
155                 {}
156         ;
157
158 Bpoint_list:
159         Bpoint Bpoint_list
160                 {}
161         | Bpoint
162                 {}
163         ;
164
165 Bpoint:
166         '(' ConstOp ConstOp ')'
167                 {
168                 if (sp->num_beacons % REALLOC == 0) {
169                         if (sp->beacon == NULL)
170                                 sp->beacon = (BEACON *) malloc((sp->num_beacons
171                                         + REALLOC) * sizeof (BEACON));
172                         else
173                                 sp->beacon = (BEACON *) realloc(sp->beacon,
174                                         (sp->num_beacons + REALLOC) * 
175                                         sizeof (BEACON));
176                         if (sp->beacon == NULL)
177                                 return (yyerror("No memory available."));
178                 }
179                 sp->beacon[sp->num_beacons].x = $2;
180                 sp->beacon[sp->num_beacons].y = $3;
181                 check_point($2, $3);
182                 sp->num_beacons++;
183                 }
184         ;
185
186 Epoint_list:
187         Epoint Epoint_list
188                 {}
189         | Epoint
190                 {}
191         ;
192
193 Epoint:
194         '(' ConstOp ConstOp DirOp ')'
195                 {
196                 int     dir;
197
198                 if (sp->num_exits % REALLOC == 0) {
199                         if (sp->exit == NULL)
200                                 sp->exit = (EXIT *) malloc((sp->num_exits + 
201                                         REALLOC) * sizeof (EXIT));
202                         else
203                                 sp->exit = (EXIT *) realloc(sp->exit,
204                                         (sp->num_exits + REALLOC) * 
205                                         sizeof (EXIT));
206                         if (sp->exit == NULL)
207                                 return (yyerror("No memory available."));
208                 }
209                 dir = dir_no($4);
210                 sp->exit[sp->num_exits].x = $2;
211                 sp->exit[sp->num_exits].y = $3;
212                 sp->exit[sp->num_exits].dir = dir;
213                 check_edge($2, $3);
214                 check_edir($2, $3, dir);
215                 sp->num_exits++;
216                 }
217         ;
218
219 Apoint_list:
220         Apoint Apoint_list
221                 {}
222         | Apoint
223                 {}
224         ;
225
226 Apoint:
227         '(' ConstOp ConstOp DirOp ')'
228                 {
229                 int     dir;
230
231                 if (sp->num_airports % REALLOC == 0) {
232                         if (sp->airport == NULL)
233                                 sp->airport=(AIRPORT *)malloc((sp->num_airports
234                                         + REALLOC) * sizeof(AIRPORT));
235                         else
236                                 sp->airport = (AIRPORT *) realloc(sp->airport,
237                                         (sp->num_airports + REALLOC) * 
238                                         sizeof(AIRPORT));
239                         if (sp->airport == NULL)
240                                 return (yyerror("No memory available."));
241                 }
242                 dir = dir_no($4);
243                 sp->airport[sp->num_airports].x = $2;
244                 sp->airport[sp->num_airports].y = $3;
245                 sp->airport[sp->num_airports].dir = dir;
246                 check_point($2, $3);
247                 check_adir($2, $3, dir);
248                 sp->num_airports++;
249                 }
250         ;
251
252 Lline_list:
253         Lline Lline_list
254                 {}
255         | Lline
256                 {}
257         ;
258
259 Lline:
260         '[' '(' ConstOp ConstOp ')' '(' ConstOp ConstOp ')' ']'
261                 {
262                 if (sp->num_lines % REALLOC == 0) {
263                         if (sp->line == NULL)
264                                 sp->line = (LINE *) malloc((sp->num_lines + 
265                                         REALLOC) * sizeof (LINE));
266                         else
267                                 sp->line = (LINE *) realloc(sp->line,
268                                         (sp->num_lines + REALLOC) *
269                                         sizeof (LINE));
270                         if (sp->line == NULL)
271                                 return (yyerror("No memory available."));
272                 }
273                 sp->line[sp->num_lines].p1.x = $3;
274                 sp->line[sp->num_lines].p1.y = $4;
275                 sp->line[sp->num_lines].p2.x = $7;
276                 sp->line[sp->num_lines].p2.y = $8;
277                 check_line($3, $4, $7, $8);
278                 sp->num_lines++;
279                 }
280         ;
281 %%
282
283 check_edge(x, y)
284 {
285         if (!(x == 0) && !(x == sp->width - 1) && 
286             !(y == 0) && !(y == sp->height - 1))
287                 yyerror("edge value not on edge.");
288 }
289
290 check_point(x, y)
291 {
292         if (x < 1 || x >= sp->width - 1)
293                 yyerror("X value out of range.");
294         if (y < 1 || y >= sp->height - 1)
295                 yyerror("Y value out of range.");
296 }
297
298 check_linepoint(x, y)
299 {
300         if (x < 0 || x >= sp->width)
301                 yyerror("X value out of range.");
302         if (y < 0 || y >= sp->height)
303                 yyerror("Y value out of range.");
304 }
305
306 check_line(x1, y1, x2, y2)
307 {
308         int     d1, d2;
309
310         check_linepoint(x1, y1);
311         check_linepoint(x2, y2);
312
313         d1 = ABS(x2 - x1);
314         d2 = ABS(y2 - y1);
315
316         if (!(d1 == d2) && !(d1 == 0) && !(d2 == 0))
317                 yyerror("Bad line endpoints.");
318 }
319
320 yyerror(s)
321         char *s;
322 {
323         fprintf(stderr, "\"%s\": line %d: %s\n", file, line, s);
324         errors++;
325
326         return (errors);
327 }
328
329 check_edir(x, y, dir)
330 {
331         int     bad = 0;
332
333         if (x == sp->width - 1)
334                 x = 2;
335         else if (x != 0)
336                 x = 1;
337         if (y == sp->height - 1)
338                 y = 2;
339         else if (y != 0)
340                 y = 1;
341         
342         switch (x * 10 + y) {
343         case 00: if (dir != 3) bad++; break;
344         case 01: if (dir < 1 || dir > 3) bad++; break;
345         case 02: if (dir != 1) bad++; break;
346         case 10: if (dir < 3 || dir > 5) bad++; break;
347         case 11: break;
348         case 12: if (dir > 1 && dir < 7) bad++; break;
349         case 20: if (dir != 5) bad++; break;
350         case 21: if (dir < 5) bad++; break;
351         case 22: if (dir != 7) bad++; break;
352         default:
353                 yyerror("Unknown value in checkdir!  Get help!");
354                 break;
355         }
356         if (bad)
357                 yyerror("Bad direction for entrance at exit.");
358 }
359
360 check_adir(x, y, dir)
361 {
362 }
363
364 checkdefs()
365 {
366         int     err = 0;
367
368         if (sp->width == 0) {
369                 yyerror("'width' undefined.");
370                 err++;
371         }
372         if (sp->height == 0) {
373                 yyerror("'height' undefined.");
374                 err++;
375         }
376         if (sp->update_secs == 0) {
377                 yyerror("'update' undefined.");
378                 err++;
379         }
380         if (sp->newplane_time == 0) {
381                 yyerror("'newplane' undefined.");
382                 err++;
383         }
384         if (err)
385                 return (-1);
386         else
387                 return (0);
388 }