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