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