1 /* $NetBSD: grammar.y,v 1.9 2005/07/01 00:48:34 jmc 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.9 2005/07/01 00:48:34 jmc Exp $"); 68 #endif 69 #endif /* not lint */ 70 71 int errors = 0; 72 int line = 1; 73 %} 74 75 %% 76 file: 77 bunch_of_defs { if (checkdefs() < 0) return (errors); } bunch_of_lines 78 { 79 if (sp->num_exits + sp->num_airports < 2) 80 yyerror("Need at least 2 airports and/or exits."); 81 return (errors); 82 } 83 ; 84 85 bunch_of_defs: 86 def bunch_of_defs 87 | def 88 ; 89 90 def: 91 udef 92 | ndef 93 | wdef 94 | hdef 95 ; 96 97 udef: 98 UpdateOp '=' ConstOp ';' 99 { 100 if (sp->update_secs != 0) 101 return (yyerror("Redefinition of 'update'.")); 102 else if ($3 < 1) 103 return (yyerror("'update' is too small.")); 104 else 105 sp->update_secs = $3; 106 } 107 ; 108 109 ndef: 110 NewplaneOp '=' ConstOp ';' 111 { 112 if (sp->newplane_time != 0) 113 return (yyerror("Redefinition of 'newplane'.")); 114 else if ($3 < 1) 115 return (yyerror("'newplane' is too small.")); 116 else 117 sp->newplane_time = $3; 118 } 119 ; 120 121 hdef: 122 HeightOp '=' ConstOp ';' 123 { 124 if (sp->height != 0) 125 return (yyerror("Redefinition of 'height'.")); 126 else if ($3 < 3) 127 return (yyerror("'height' is too small.")); 128 else 129 sp->height = $3; 130 } 131 ; 132 133 wdef: 134 WidthOp '=' ConstOp ';' 135 { 136 if (sp->width != 0) 137 return (yyerror("Redefinition of 'width'.")); 138 else if ($3 < 3) 139 return (yyerror("'width' is too small.")); 140 else 141 sp->width = $3; 142 } 143 ; 144 145 bunch_of_lines: 146 line bunch_of_lines 147 {} 148 | line 149 {} 150 ; 151 152 line: 153 BeaconOp ':' Bpoint_list ';' 154 {} 155 | ExitOp ':' Epoint_list ';' 156 {} 157 | LineOp ':' Lline_list ';' 158 {} 159 | AirportOp ':' Apoint_list ';' 160 {} 161 ; 162 163 Bpoint_list: 164 Bpoint Bpoint_list 165 {} 166 | Bpoint 167 {} 168 ; 169 170 Bpoint: 171 '(' ConstOp ConstOp ')' 172 { 173 if (sp->num_beacons % REALLOC == 0) { 174 if (sp->beacon == NULL) 175 sp->beacon = (BEACON *) malloc((sp->num_beacons 176 + REALLOC) * sizeof (BEACON)); 177 else 178 sp->beacon = (BEACON *) realloc(sp->beacon, 179 (sp->num_beacons + REALLOC) * 180 sizeof (BEACON)); 181 if (sp->beacon == NULL) 182 return (yyerror("No memory available.")); 183 } 184 sp->beacon[sp->num_beacons].x = $2; 185 sp->beacon[sp->num_beacons].y = $3; 186 check_point($2, $3); 187 sp->num_beacons++; 188 } 189 ; 190 191 Epoint_list: 192 Epoint Epoint_list 193 {} 194 | Epoint 195 {} 196 ; 197 198 Epoint: 199 '(' ConstOp ConstOp DirOp ')' 200 { 201 int dir; 202 203 if (sp->num_exits % REALLOC == 0) { 204 if (sp->exit == NULL) 205 sp->exit = (EXIT *) malloc((sp->num_exits + 206 REALLOC) * sizeof (EXIT)); 207 else 208 sp->exit = (EXIT *) realloc(sp->exit, 209 (sp->num_exits + REALLOC) * 210 sizeof (EXIT)); 211 if (sp->exit == NULL) 212 return (yyerror("No memory available.")); 213 } 214 dir = dir_no($4); 215 sp->exit[sp->num_exits].x = $2; 216 sp->exit[sp->num_exits].y = $3; 217 sp->exit[sp->num_exits].dir = dir; 218 check_edge($2, $3); 219 check_edir($2, $3, dir); 220 sp->num_exits++; 221 } 222 ; 223 224 Apoint_list: 225 Apoint Apoint_list 226 {} 227 | Apoint 228 {} 229 ; 230 231 Apoint: 232 '(' ConstOp ConstOp DirOp ')' 233 { 234 int dir; 235 236 if (sp->num_airports % REALLOC == 0) { 237 if (sp->airport == NULL) 238 sp->airport=(AIRPORT *)malloc((sp->num_airports 239 + REALLOC) * sizeof(AIRPORT)); 240 else 241 sp->airport = (AIRPORT *) realloc(sp->airport, 242 (sp->num_airports + REALLOC) * 243 sizeof(AIRPORT)); 244 if (sp->airport == NULL) 245 return (yyerror("No memory available.")); 246 } 247 dir = dir_no($4); 248 sp->airport[sp->num_airports].x = $2; 249 sp->airport[sp->num_airports].y = $3; 250 sp->airport[sp->num_airports].dir = dir; 251 check_point($2, $3); 252 sp->num_airports++; 253 } 254 ; 255 256 Lline_list: 257 Lline Lline_list 258 {} 259 | Lline 260 {} 261 ; 262 263 Lline: 264 '[' '(' ConstOp ConstOp ')' '(' ConstOp ConstOp ')' ']' 265 { 266 if (sp->num_lines % REALLOC == 0) { 267 if (sp->line == NULL) 268 sp->line = (LINE *) malloc((sp->num_lines + 269 REALLOC) * sizeof (LINE)); 270 else 271 sp->line = (LINE *) realloc(sp->line, 272 (sp->num_lines + REALLOC) * 273 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 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 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 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 void 314 check_line(int px1, int py1, int px2, int py2) 315 { 316 int d1, d2; 317 318 check_linepoint(px1, py1); 319 check_linepoint(px2, py2); 320 321 d1 = ABS(px2 - px1); 322 d2 = ABS(py2 - py1); 323 324 if (!(d1 == d2) && !(d1 == 0) && !(d2 == 0)) 325 yyerror("Bad line endpoints."); 326 } 327 328 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 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 int 370 checkdefs(void) 371 { 372 int error = 0; 373 374 if (sp->width == 0) { 375 yyerror("'width' undefined."); 376 error++; 377 } 378 if (sp->height == 0) { 379 yyerror("'height' undefined."); 380 error++; 381 } 382 if (sp->update_secs == 0) { 383 yyerror("'update' undefined."); 384 error++; 385 } 386 if (sp->newplane_time == 0) { 387 yyerror("'newplane' undefined."); 388 error++; 389 } 390 if (error) 391 return (-1); 392 else 393 return (0); 394 } 395