Commit | Line | Data |
---|---|---|
a9cea16d WJ |
1 | /*- |
2 | * Copyright (c) 1990 The Regents of the University of California. | |
3 | * 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 | ||
37 | /* | |
38 | * Copyright (c) 1987 by Ed James, UC Berkeley. All rights reserved. | |
39 | * | |
40 | * Copy permission is hereby granted provided that this notice is | |
41 | * retained on all partial or complete copies. | |
42 | * | |
43 | * For more info on this and all of my stuff, mail edjames@berkeley.edu. | |
44 | */ | |
45 | ||
46 | %token <ival> HeightOp | |
47 | %token <ival> WidthOp | |
48 | %token <ival> UpdateOp | |
49 | %token <ival> NewplaneOp | |
50 | %token <cval> DirOp | |
51 | %token <ival> ConstOp | |
52 | %token <ival> LineOp | |
53 | %token <ival> AirportOp | |
54 | %token <ival> BeaconOp | |
55 | %token <ival> ExitOp | |
56 | %union { | |
57 | int ival; | |
58 | char cval; | |
59 | } | |
60 | ||
61 | %{ | |
62 | #include "include.h" | |
63 | ||
64 | #ifndef lint | |
65 | static char sccsid[] = "@(#)grammar.y 5.2 (Berkeley) 4/30/90"; | |
66 | #endif /* not lint */ | |
67 | ||
68 | int errors = 0; | |
69 | int line = 1; | |
70 | %} | |
71 | ||
72 | %% | |
73 | file: | |
74 | bunch_of_defs { if (checkdefs() < 0) return (errors); } bunch_of_lines | |
75 | { | |
76 | if (sp->num_exits + sp->num_airports < 2) | |
77 | yyerror("Need at least 2 airports and/or exits."); | |
78 | return (errors); | |
79 | } | |
80 | ; | |
81 | ||
82 | bunch_of_defs: | |
83 | def bunch_of_defs | |
84 | | def | |
85 | ; | |
86 | ||
87 | def: | |
88 | udef | |
89 | | ndef | |
90 | | wdef | |
91 | | hdef | |
92 | ; | |
93 | ||
94 | udef: | |
95 | UpdateOp '=' ConstOp ';' | |
96 | { | |
97 | if (sp->update_secs != 0) | |
98 | return (yyerror("Redefinition of 'update'.")); | |
99 | else if ($3 < 1) | |
100 | return (yyerror("'update' is too small.")); | |
101 | else | |
102 | sp->update_secs = $3; | |
103 | } | |
104 | ; | |
105 | ||
106 | ndef: | |
107 | NewplaneOp '=' ConstOp ';' | |
108 | { | |
109 | if (sp->newplane_time != 0) | |
110 | return (yyerror("Redefinition of 'newplane'.")); | |
111 | else if ($3 < 1) | |
112 | return (yyerror("'newplane' is too small.")); | |
113 | else | |
114 | sp->newplane_time = $3; | |
115 | } | |
116 | ; | |
117 | ||
118 | hdef: | |
119 | HeightOp '=' ConstOp ';' | |
120 | { | |
121 | if (sp->height != 0) | |
122 | return (yyerror("Redefinition of 'height'.")); | |
123 | else if ($3 < 3) | |
124 | return (yyerror("'height' is too small.")); | |
125 | else | |
126 | sp->height = $3; | |
127 | } | |
128 | ; | |
129 | ||
130 | wdef: | |
131 | WidthOp '=' ConstOp ';' | |
132 | { | |
133 | if (sp->height != 0) | |
134 | return (yyerror("Redefinition of 'width'.")); | |
135 | else if ($3 < 3) | |
136 | return (yyerror("'width' is too small.")); | |
137 | else | |
138 | sp->width = $3; | |
139 | } | |
140 | ; | |
141 | ||
142 | bunch_of_lines: | |
143 | line bunch_of_lines | |
144 | {} | |
145 | | line | |
146 | {} | |
147 | ; | |
148 | ||
149 | line: | |
150 | BeaconOp ':' Bpoint_list ';' | |
151 | {} | |
152 | | ExitOp ':' Epoint_list ';' | |
153 | {} | |
154 | | LineOp ':' Lline_list ';' | |
155 | {} | |
156 | | AirportOp ':' Apoint_list ';' | |
157 | {} | |
158 | ; | |
159 | ||
160 | Bpoint_list: | |
161 | Bpoint Bpoint_list | |
162 | {} | |
163 | | Bpoint | |
164 | {} | |
165 | ; | |
166 | ||
167 | Bpoint: | |
168 | '(' ConstOp ConstOp ')' | |
169 | { | |
170 | if (sp->num_beacons % REALLOC == 0) { | |
171 | if (sp->beacon == NULL) | |
172 | sp->beacon = (BEACON *) malloc((sp->num_beacons | |
173 | + REALLOC) * sizeof (BEACON)); | |
174 | else | |
175 | sp->beacon = (BEACON *) realloc(sp->beacon, | |
176 | (sp->num_beacons + REALLOC) * | |
177 | sizeof (BEACON)); | |
178 | if (sp->beacon == NULL) | |
179 | return (yyerror("No memory available.")); | |
180 | } | |
181 | sp->beacon[sp->num_beacons].x = $2; | |
182 | sp->beacon[sp->num_beacons].y = $3; | |
183 | check_point($2, $3); | |
184 | sp->num_beacons++; | |
185 | } | |
186 | ; | |
187 | ||
188 | Epoint_list: | |
189 | Epoint Epoint_list | |
190 | {} | |
191 | | Epoint | |
192 | {} | |
193 | ; | |
194 | ||
195 | Epoint: | |
196 | '(' ConstOp ConstOp DirOp ')' | |
197 | { | |
198 | int dir; | |
199 | ||
200 | if (sp->num_exits % REALLOC == 0) { | |
201 | if (sp->exit == NULL) | |
202 | sp->exit = (EXIT *) malloc((sp->num_exits + | |
203 | REALLOC) * sizeof (EXIT)); | |
204 | else | |
205 | sp->exit = (EXIT *) realloc(sp->exit, | |
206 | (sp->num_exits + REALLOC) * | |
207 | sizeof (EXIT)); | |
208 | if (sp->exit == NULL) | |
209 | return (yyerror("No memory available.")); | |
210 | } | |
211 | dir = dir_no($4); | |
212 | sp->exit[sp->num_exits].x = $2; | |
213 | sp->exit[sp->num_exits].y = $3; | |
214 | sp->exit[sp->num_exits].dir = dir; | |
215 | check_edge($2, $3); | |
216 | check_edir($2, $3, dir); | |
217 | sp->num_exits++; | |
218 | } | |
219 | ; | |
220 | ||
221 | Apoint_list: | |
222 | Apoint Apoint_list | |
223 | {} | |
224 | | Apoint | |
225 | {} | |
226 | ; | |
227 | ||
228 | Apoint: | |
229 | '(' ConstOp ConstOp DirOp ')' | |
230 | { | |
231 | int dir; | |
232 | ||
233 | if (sp->num_airports % REALLOC == 0) { | |
234 | if (sp->airport == NULL) | |
235 | sp->airport=(AIRPORT *)malloc((sp->num_airports | |
236 | + REALLOC) * sizeof(AIRPORT)); | |
237 | else | |
238 | sp->airport = (AIRPORT *) realloc(sp->airport, | |
239 | (sp->num_airports + REALLOC) * | |
240 | sizeof(AIRPORT)); | |
241 | if (sp->airport == NULL) | |
242 | return (yyerror("No memory available.")); | |
243 | } | |
244 | dir = dir_no($4); | |
245 | sp->airport[sp->num_airports].x = $2; | |
246 | sp->airport[sp->num_airports].y = $3; | |
247 | sp->airport[sp->num_airports].dir = dir; | |
248 | check_point($2, $3); | |
249 | check_adir($2, $3, dir); | |
250 | sp->num_airports++; | |
251 | } | |
252 | ; | |
253 | ||
254 | Lline_list: | |
255 | Lline Lline_list | |
256 | {} | |
257 | | Lline | |
258 | {} | |
259 | ; | |
260 | ||
261 | Lline: | |
262 | '[' '(' ConstOp ConstOp ')' '(' ConstOp ConstOp ')' ']' | |
263 | { | |
264 | if (sp->num_lines % REALLOC == 0) { | |
265 | if (sp->line == NULL) | |
266 | sp->line = (LINE *) malloc((sp->num_lines + | |
267 | REALLOC) * sizeof (LINE)); | |
268 | else | |
269 | sp->line = (LINE *) realloc(sp->line, | |
270 | (sp->num_lines + REALLOC) * | |
271 | sizeof (LINE)); | |
272 | if (sp->line == NULL) | |
273 | return (yyerror("No memory available.")); | |
274 | } | |
275 | sp->line[sp->num_lines].p1.x = $3; | |
276 | sp->line[sp->num_lines].p1.y = $4; | |
277 | sp->line[sp->num_lines].p2.x = $7; | |
278 | sp->line[sp->num_lines].p2.y = $8; | |
279 | check_line($3, $4, $7, $8); | |
280 | sp->num_lines++; | |
281 | } | |
282 | ; | |
283 | %% | |
284 | ||
285 | check_edge(x, y) | |
286 | { | |
287 | if (!(x == 0) && !(x == sp->width - 1) && | |
288 | !(y == 0) && !(y == sp->height - 1)) | |
289 | yyerror("edge value not on edge."); | |
290 | } | |
291 | ||
292 | check_point(x, y) | |
293 | { | |
294 | if (x < 1 || x >= sp->width - 1) | |
295 | yyerror("X value out of range."); | |
296 | if (y < 1 || y >= sp->height - 1) | |
297 | yyerror("Y value out of range."); | |
298 | } | |
299 | ||
300 | check_linepoint(x, y) | |
301 | { | |
302 | if (x < 0 || x >= sp->width) | |
303 | yyerror("X value out of range."); | |
304 | if (y < 0 || y >= sp->height) | |
305 | yyerror("Y value out of range."); | |
306 | } | |
307 | ||
308 | check_line(x1, y1, x2, y2) | |
309 | { | |
310 | int d1, d2; | |
311 | ||
312 | check_linepoint(x1, y1); | |
313 | check_linepoint(x2, y2); | |
314 | ||
315 | d1 = ABS(x2 - x1); | |
316 | d2 = ABS(y2 - y1); | |
317 | ||
318 | if (!(d1 == d2) && !(d1 == 0) && !(d2 == 0)) | |
319 | yyerror("Bad line endpoints."); | |
320 | } | |
321 | ||
322 | yyerror(s) | |
323 | { | |
324 | fprintf(stderr, "\"%s\": line %d: %s\n", file, line, s); | |
325 | errors++; | |
326 | ||
327 | return (errors); | |
328 | } | |
329 | ||
330 | check_edir(x, y, dir) | |
331 | { | |
332 | int bad = 0; | |
333 | ||
334 | if (x == sp->width - 1) | |
335 | x = 2; | |
336 | else if (x != 0) | |
337 | x = 1; | |
338 | if (y == sp->height - 1) | |
339 | y = 2; | |
340 | else if (y != 0) | |
341 | y = 1; | |
342 | ||
343 | switch (x * 10 + y) { | |
344 | case 00: if (dir != 3) bad++; break; | |
345 | case 01: if (dir < 1 || dir > 3) bad++; break; | |
346 | case 02: if (dir != 1) bad++; break; | |
347 | case 10: if (dir < 3 || dir > 5) bad++; break; | |
348 | case 11: break; | |
349 | case 12: if (dir > 1 && dir < 7) bad++; break; | |
350 | case 20: if (dir != 5) bad++; break; | |
351 | case 21: if (dir < 5) bad++; break; | |
352 | case 22: if (dir != 7) bad++; break; | |
353 | default: | |
354 | yyerror("Unknown value in checkdir! Get help!"); | |
355 | break; | |
356 | } | |
357 | if (bad) | |
358 | yyerror("Bad direction for entrance at exit."); | |
359 | } | |
360 | ||
361 | check_adir(x, y, dir) | |
362 | { | |
363 | } | |
364 | ||
365 | checkdefs() | |
366 | { | |
367 | int err = 0; | |
368 | ||
369 | if (sp->width == 0) { | |
370 | yyerror("'width' undefined."); | |
371 | err++; | |
372 | } | |
373 | if (sp->height == 0) { | |
374 | yyerror("'height' undefined."); | |
375 | err++; | |
376 | } | |
377 | if (sp->update_secs == 0) { | |
378 | yyerror("'update' undefined."); | |
379 | err++; | |
380 | } | |
381 | if (sp->newplane_time == 0) { | |
382 | yyerror("'newplane' undefined."); | |
383 | err++; | |
384 | } | |
385 | if (err) | |
386 | return (-1); | |
387 | else | |
388 | return (0); | |
389 | } |