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