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