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