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