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