1 %{ 2 /* NetHack 3.6 lev_comp.l $NHDT-Date: 1543371690 2018/11/28 02:21:30 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.25 $ */ 3 /* Copyright (c) 1989 by Jean-Christophe Collet */ 4 /* NetHack may be freely redistributed. See license for details. */ 5 6 #define LEV_LEX_C 7 8 #include "hack.h" 9 #include "lev_comp.h" 10 #include "sp_lev.h" 11 12 /* Most of these don't exist in flex, yywrap is macro and 13 * yyunput is properly declared in flex.skel. 14 */ 15 #if !defined(FLEX_SCANNER) && !defined(FLEXHACK_SCANNER) 16 int FDECL(yyback, (int *,int)); 17 int NDECL(yylook); 18 int NDECL(yyinput); 19 int NDECL(yywrap); 20 int NDECL(yylex); 21 /* Traditional lexes let yyunput() and yyoutput() default to int; 22 * newer ones may declare them as void since they don't return 23 * values. For even more fun, the lex supplied as part of the 24 * newer unbundled compiler for SunOS 4.x adds the void declarations 25 * (under __STDC__ or _cplusplus ifdefs -- otherwise they remain 26 * int) while the bundled lex and the one with the older unbundled 27 * compiler do not. To detect this, we need help from outside -- 28 * sys/unix/Makefile.utl. 29 * 30 * Digital UNIX is difficult and still has int in spite of all 31 * other signs. 32 */ 33 # if defined(NeXT) || defined(SVR4) || defined(_AIX32) 34 # define VOIDYYPUT 35 # endif 36 # if !defined(VOIDYYPUT) && defined(POSIX_TYPES) 37 # if !defined(BOS) && !defined(HISX) && !defined(_M_UNIX) && !defined(VMS) 38 # define VOIDYYPUT 39 # endif 40 # endif 41 # if !defined(VOIDYYPUT) && defined(WEIRD_LEX) 42 # if defined(SUNOS4) && defined(__STDC__) && (WEIRD_LEX > 1) 43 # define VOIDYYPUT 44 # endif 45 # endif 46 # if defined(VOIDYYPUT) && defined(__osf__) 47 # undef VOIDYYPUT 48 # endif 49 # ifdef VOIDYYPUT 50 void FDECL(yyunput, (int)); 51 void FDECL(yyoutput, (int)); 52 # else 53 int FDECL(yyunput, (int)); 54 int FDECL(yyoutput, (int)); 55 # endif 56 57 #else /* !FLEX_SCANNER && !FLEXHACK_SCANNER */ 58 /* most recent flex allows suppressing yyunput() altogether when not needed */ 59 #define YY_NO_UNPUT 60 #define YY_NO_INPUT 61 #endif 62 63 #if defined(FLEX_SCANNER) || defined(FLEXHACK_SCANNER) 64 /* older flex wants this */ 65 #define YY_MALLOC_DECL genericptr_t FDECL(malloc, (size_t)); \ 66 genericptr_t FDECL(realloc, (genericptr_t, size_t)); 67 /* newer flex assumes <stdlib.h> so needs this in case it's been suppressed */ 68 YY_MALLOC_DECL 69 #endif 70 71 void FDECL(init_yyin, (FILE *)); 72 void FDECL(init_yyout, (FILE *)); 73 74 long NDECL(handle_varstring_check); 75 long FDECL(corefunc_str_check, (char *, long)); 76 77 extern void VDECL(lc_error, (const char *, ...)); 78 extern struct lc_vardefs *FDECL(vardef_defined,(struct lc_vardefs *,char *, int)); 79 80 extern struct lc_vardefs *vardefs; 81 82 extern long FDECL(method_defined, (char *, long, long *)); 83 84 void FDECL(savetoken, (char *)); 85 void NDECL(newline); 86 void FDECL(advancepos, (char *)); 87 88 /* 89 * This doesn't always get put in lev_comp.h 90 * (esp. when using older versions of bison). 91 */ 92 extern YYSTYPE yylval; 93 94 int nh_line_number = 1; 95 int token_start_pos = 0; 96 char curr_token[512]; 97 static char map[4096]; 98 static int map_cnt = 0; 99 100 FILE *orig_yyin = NULL; 101 102 #define ST_RET(x) do { savetoken(yytext); return x; } while (0); 103 #define ST_RETF(y, x) do { savetoken(yytext); y; return x; } while (0); 104 105 %} 106 %e 2500 107 %p 10000 108 %n 1500 109 %s MAPC 110 %% 111 <MAPC>ENDMAP { 112 savetoken(yytext); 113 BEGIN(INITIAL); 114 yylval.map = (char *) alloc(map_cnt + 1); 115 (void) strncpy(yylval.map, map, map_cnt); 116 yylval.map[map_cnt] = 0; 117 map_cnt = 0; 118 return MAP_ID; 119 } 120 <MAPC>[-|}{+xABCISHKPLWTF\\#. 0123456789]*\r?\n { 121 int len = yyleng; 122 savetoken(yytext); 123 /* convert \r\n to \n */ 124 if (len >= 2 && yytext[len - 2] == '\r') 125 len -= 1; 126 (void) strncpy(map + map_cnt, yytext, len); 127 map_cnt += len; 128 map[map_cnt - 1] = '\n'; 129 map[map_cnt] = '\0'; 130 newline(); 131 } 132 ^[ \t]*#.*\n { savetoken(yytext); newline(); } 133 MESSAGE ST_RET(MESSAGE_ID); 134 NOMAP ST_RET(NOMAP_ID); 135 MAZE ST_RET(MAZE_ID); 136 LEVEL ST_RET(LEVEL_ID); 137 INIT_MAP ST_RET(LEV_INIT_ID); 138 mazegrid ST_RET(MAZE_GRID_ID); 139 solidfill ST_RET(SOLID_FILL_ID); 140 mines ST_RET(MINES_ID); 141 rogue ST_RET(ROGUELEV_ID); 142 FLAGS ST_RET(FLAGS_ID); 143 GEOMETRY ST_RET(GEOMETRY_ID); 144 ^MAP\r?\n { savetoken(yytext); BEGIN(MAPC); newline(); } 145 obj(ect)? ST_RET(object_ID); 146 OBJECT ST_RET(OBJECT_ID); 147 CONTAINER ST_RET(COBJECT_ID); 148 MONSTER ST_RET(MONSTER_ID); 149 monster ST_RET(monster_ID); 150 TRAP ST_RET(TRAP_ID); 151 DOOR ST_RET(DOOR_ID); 152 ROOMDOOR ST_RET(ROOMDOOR_ID); 153 DRAWBRIDGE ST_RET(DRAWBRIDGE_ID); 154 MAZEWALK ST_RET(MAZEWALK_ID); 155 WALLIFY ST_RET(WALLIFY_ID); 156 REGION ST_RET(REGION_ID); 157 ALTAR ST_RET(ALTAR_ID); 158 LADDER ST_RET(LADDER_ID); 159 STAIR ST_RET(STAIR_ID); 160 PORTAL ST_RET(PORTAL_ID); 161 TELEPORT_REGION ST_RET(TELEPRT_ID); 162 BRANCH ST_RET(BRANCH_ID); 163 FOUNTAIN ST_RET(FOUNTAIN_ID); 164 SINK ST_RET(SINK_ID); 165 POOL ST_RET(POOL_ID); 166 NON_DIGGABLE ST_RET(NON_DIGGABLE_ID); 167 NON_PASSWALL ST_RET(NON_PASSWALL_ID); 168 IF ST_RET(IF_ID); 169 ELSE ST_RET(ELSE_ID); 170 EXIT ST_RET(EXIT_ID); 171 ROOM ST_RET(ROOM_ID); 172 SUBROOM ST_RET(SUBROOM_ID); 173 RANDOM_CORRIDORS ST_RET(RAND_CORRIDOR_ID); 174 CORRIDOR ST_RET(CORRIDOR_ID); 175 TERRAIN ST_RET(TERRAIN_ID); 176 terrain ST_RET(terrain_ID); 177 REPLACE_TERRAIN ST_RET(REPLACE_TERRAIN_ID); 178 GOLD ST_RET(GOLD_ID); 179 GRAVE ST_RET(GRAVE_ID); 180 ENGRAVING ST_RET(ENGRAVING_ID); 181 MINERALIZE ST_RET(MINERALIZE_ID); 182 (NAME|name) ST_RET(NAME_ID); 183 FOR ST_RET(FOR_ID); 184 TO ST_RET(TO_ID); 185 LOOP ST_RET(LOOP_ID); 186 SWITCH ST_RET(SWITCH_ID); 187 CASE ST_RET(CASE_ID); 188 BREAK ST_RET(BREAK_ID); 189 DEFAULT ST_RET(DEFAULT_ID); 190 FUNCTION ST_RET(FUNCTION_ID); 191 SHUFFLE ST_RET(SHUFFLE_ID); 192 montype ST_RET(MONTYPE_ID); 193 selection ST_RET(selection_ID); 194 rect ST_RET(rect_ID); 195 fillrect ST_RET(fillrect_ID); 196 line ST_RET(line_ID); 197 randline ST_RET(randline_ID); 198 grow ST_RET(grow_ID); 199 floodfill ST_RET(flood_ID); 200 rndcoord ST_RET(rndcoord_ID); 201 circle ST_RET(circle_ID); 202 ellipse ST_RET(ellipse_ID); 203 filter ST_RET(filter_ID); 204 gradient ST_RET(gradient_ID); 205 complement ST_RET(complement_ID); 206 radial { savetoken(yytext); yylval.i=SEL_GRADIENT_RADIAL; return GRADIENT_TYPE; } 207 square { savetoken(yytext); yylval.i=SEL_GRADIENT_SQUARE; return GRADIENT_TYPE; } 208 dry { savetoken(yytext); yylval.i=DRY; return HUMIDITY_TYPE; } 209 wet { savetoken(yytext); yylval.i=WET; return HUMIDITY_TYPE; } 210 hot { savetoken(yytext); yylval.i=HOT; return HUMIDITY_TYPE; } 211 solid { savetoken(yytext); yylval.i=SOLID; return HUMIDITY_TYPE; } 212 any { savetoken(yytext); yylval.i=ANY_LOC; return HUMIDITY_TYPE; } 213 levregion ST_RET(LEV); 214 quantity ST_RET(QUANTITY_ID); 215 buried ST_RET(BURIED_ID); 216 eroded ST_RET(ERODED_ID); 217 erodeproof ST_RET(ERODEPROOF_ID); 218 trapped { savetoken(yytext); yylval.i=1; return TRAPPED_STATE; } 219 not_trapped { savetoken(yytext); yylval.i=0; return TRAPPED_STATE; } 220 recharged ST_RET(RECHARGED_ID); 221 invisible ST_RET(INVIS_ID); 222 greased ST_RET(GREASED_ID); 223 female ST_RET(FEMALE_ID); 224 cancelled ST_RET(CANCELLED_ID); 225 revived ST_RET(REVIVED_ID); 226 avenge ST_RET(AVENGE_ID); 227 fleeing ST_RET(FLEEING_ID); 228 blinded ST_RET(BLINDED_ID); 229 paralyzed ST_RET(PARALYZED_ID); 230 stunned ST_RET(STUNNED_ID); 231 confused ST_RET(CONFUSED_ID); 232 seen_traps ST_RET(SEENTRAPS_ID); 233 all ST_RET(ALL_ID); 234 horizontal ST_RETF((yylval.i=1), HORIZ_OR_VERT); 235 vertical { savetoken(yytext); yylval.i=2; return HORIZ_OR_VERT; } 236 open { savetoken(yytext); yylval.i=D_ISOPEN; return DOOR_STATE; } 237 closed { savetoken(yytext); yylval.i=D_CLOSED; return DOOR_STATE; } 238 locked { savetoken(yytext); yylval.i=D_LOCKED; return DOOR_STATE; } 239 nodoor { savetoken(yytext); yylval.i=D_NODOOR; return DOOR_STATE; } 240 broken { savetoken(yytext); yylval.i=D_BROKEN; return DOOR_STATE; } 241 secret { savetoken(yytext); yylval.i=D_SECRET; return DOOR_STATE; } 242 north { savetoken(yytext); yylval.i=W_NORTH; return DIRECTION; } 243 east { savetoken(yytext); yylval.i=W_EAST; return DIRECTION; } 244 south { savetoken(yytext); yylval.i=W_SOUTH; return DIRECTION; } 245 west { savetoken(yytext); yylval.i=W_WEST; return DIRECTION; } 246 random { savetoken(yytext); yylval.i = -1; return RANDOM_TYPE; } 247 random\[ { savetoken(yytext); yylval.i = -1; return RANDOM_TYPE_BRACKET; } 248 none { savetoken(yytext); yylval.i = -2; return NONE; } 249 align ST_RET(A_REGISTER); 250 left { savetoken(yytext); yylval.i=1; return LEFT_OR_RIGHT; } 251 half-left { savetoken(yytext); yylval.i=2; return LEFT_OR_RIGHT; } 252 center { savetoken(yytext); yylval.i=3; return CENTER; } 253 half-right { savetoken(yytext); yylval.i=4; return LEFT_OR_RIGHT; } 254 right { savetoken(yytext); yylval.i=5; return LEFT_OR_RIGHT; } 255 top { savetoken(yytext); yylval.i=1; return TOP_OR_BOT; } 256 bottom { savetoken(yytext); yylval.i=5; return TOP_OR_BOT; } 257 lit { savetoken(yytext); yylval.i=1; return LIGHT_STATE; } 258 unlit { savetoken(yytext); yylval.i=0; return LIGHT_STATE; } 259 filled { savetoken(yytext); yylval.i=1; return FILLING; } 260 unfilled { savetoken(yytext); yylval.i=0; return FILLING; } 261 regular { savetoken(yytext); yylval.i=0; return IRREGULAR; } 262 irregular { savetoken(yytext); yylval.i=1; return IRREGULAR; } 263 unjoined { savetoken(yytext); yylval.i=1; return JOINED; } 264 joined { savetoken(yytext); yylval.i=0; return JOINED; } 265 limited { savetoken(yytext); yylval.i=1; return LIMITED; } 266 unlimited { savetoken(yytext); yylval.i=0; return LIMITED; } 267 noalign { savetoken(yytext); yylval.i= AM_NONE; return ALIGNMENT; } 268 law { savetoken(yytext); yylval.i= AM_LAWFUL; return ALIGNMENT; } 269 neutral { savetoken(yytext); yylval.i= AM_NEUTRAL; return ALIGNMENT; } 270 chaos { savetoken(yytext); yylval.i= AM_CHAOTIC; return ALIGNMENT; } 271 coaligned { savetoken(yytext); yylval.i= AM_SPLEV_CO; return ALIGNMENT; } 272 noncoaligned { savetoken(yytext); yylval.i= AM_SPLEV_NONCO; return ALIGNMENT; } 273 peaceful { savetoken(yytext); yylval.i=1; return MON_ATTITUDE; } 274 hostile { savetoken(yytext); yylval.i=0; return MON_ATTITUDE; } 275 asleep { savetoken(yytext); yylval.i=1; return MON_ALERTNESS; } 276 awake { savetoken(yytext); yylval.i=0; return MON_ALERTNESS; } 277 m_feature { savetoken(yytext); yylval.i= M_AP_FURNITURE; return MON_APPEARANCE; } 278 m_monster { savetoken(yytext); yylval.i= M_AP_MONSTER; return MON_APPEARANCE; } 279 m_object { savetoken(yytext); yylval.i= M_AP_OBJECT; return MON_APPEARANCE; } 280 sanctum { savetoken(yytext); yylval.i=2; return ALTAR_TYPE; } 281 shrine { savetoken(yytext); yylval.i=1; return ALTAR_TYPE; } 282 altar { savetoken(yytext); yylval.i=0; return ALTAR_TYPE; } 283 up { savetoken(yytext); yylval.i=1; return UP_OR_DOWN; } 284 down { savetoken(yytext); yylval.i=0; return UP_OR_DOWN; } 285 false { savetoken(yytext); yylval.i=0; return BOOLEAN; } 286 true { savetoken(yytext); yylval.i=1; return BOOLEAN; } 287 dust { savetoken(yytext); yylval.i=DUST; return ENGRAVING_TYPE; } 288 engrave { savetoken(yytext); yylval.i=ENGRAVE; return ENGRAVING_TYPE; } 289 burn { savetoken(yytext); yylval.i=BURN; return ENGRAVING_TYPE; } 290 mark { savetoken(yytext); yylval.i=MARK; return ENGRAVING_TYPE; } 291 blood { savetoken(yytext); yylval.i=ENGR_BLOOD; return ENGRAVING_TYPE; } 292 blessed { savetoken(yytext); yylval.i=1; return CURSE_TYPE; } 293 uncursed { savetoken(yytext); yylval.i=2; return CURSE_TYPE; } 294 cursed { savetoken(yytext); yylval.i=3; return CURSE_TYPE; } 295 noteleport { savetoken(yytext); yylval.i=NOTELEPORT; return FLAG_TYPE; } 296 hardfloor { savetoken(yytext); yylval.i=HARDFLOOR; return FLAG_TYPE; } 297 nommap { savetoken(yytext); yylval.i=NOMMAP; return FLAG_TYPE; } 298 arboreal { savetoken(yytext); yylval.i=ARBOREAL; return FLAG_TYPE; } /* KMH */ 299 shortsighted { savetoken(yytext); yylval.i=SHORTSIGHTED; return FLAG_TYPE; } 300 mazelevel { savetoken(yytext); yylval.i=MAZELEVEL; return FLAG_TYPE; } 301 premapped { savetoken(yytext); yylval.i=PREMAPPED; return FLAG_TYPE; } 302 shroud { savetoken(yytext); yylval.i=SHROUD; return FLAG_TYPE; } 303 graveyard { savetoken(yytext); yylval.i=GRAVEYARD; return FLAG_TYPE; } 304 icedpools { savetoken(yytext); yylval.i=ICEDPOOLS; return FLAG_TYPE; } 305 solidify { savetoken(yytext); yylval.i=SOLIDIFY; return FLAG_TYPE; } 306 corrmaze { savetoken(yytext); yylval.i=CORRMAZE; return FLAG_TYPE; } 307 inaccessibles { savetoken(yytext); yylval.i=CHECK_INACCESSIBLES; return FLAG_TYPE; } 308 [0-9]+d[0-9]+ { char *p = index(yytext, 'd'); 309 savetoken(yytext); 310 if (p) { 311 *p++ = '\0'; 312 yylval.dice.num = atoi(yytext); 313 yylval.dice.die = atoi(p); 314 } else { 315 yylval.dice.num = yylval.dice.die = 1; 316 } 317 return DICE; 318 } 319 \[\ *[0-9]+\%\ *\] { savetoken(yytext); yylval.i = atoi(yytext + 1); 320 if (yylval.i < 0 || yylval.i > 100) 321 lc_error("Unexpected percentile '%li%%'", yylval.i); 322 return PERCENT; } 323 -[0-9]+ { savetoken(yytext); yylval.i=atoi(yytext); return MINUS_INTEGER; } 324 \+[0-9]+ { savetoken(yytext); yylval.i=atoi(yytext); return PLUS_INTEGER; } 325 [0-9]+\% { savetoken(yytext); yylval.i = atoi(yytext); 326 if (yylval.i < 0 || yylval.i > 100) 327 lc_error("Unexpected percentile '%li%%'", yylval.i); 328 return SPERCENT; } 329 [0-9]+ { savetoken(yytext); yylval.i=atoi(yytext); return INTEGER; } 330 \"[^"]*\" { savetoken(yytext); 331 yytext[yyleng - 1] = '\0'; /* discard the trailing \" */ 332 yylval.map = dupstr(yytext + 1); /* skip the first \" */ 333 return STRING; } 334 \$[a-zA-Z_]+ { savetoken(yytext); return handle_varstring_check(); } 335 "==" { savetoken(yytext); yylval.i = SPO_JE; return COMPARE_TYPE; } 336 "!=" { savetoken(yytext); yylval.i = SPO_JNE; return COMPARE_TYPE; } 337 "<>" { savetoken(yytext); yylval.i = SPO_JNE; return COMPARE_TYPE; } 338 "<=" { savetoken(yytext); yylval.i = SPO_JLE; return COMPARE_TYPE; } 339 ">=" { savetoken(yytext); yylval.i = SPO_JGE; return COMPARE_TYPE; } 340 "<" { savetoken(yytext); yylval.i = SPO_JL; return COMPARE_TYPE; } 341 ">" { savetoken(yytext); yylval.i = SPO_JG; return COMPARE_TYPE; } 342 \r?\n { newline(); } 343 [ \t]+ { advancepos(yytext); } 344 '\\.' { savetoken(yytext); yylval.i = yytext[2]; return CHAR; } 345 '.' { savetoken(yytext); yylval.i = yytext[1]; return CHAR; } 346 [-_a-zA-Z0-9]+ ST_RET(UNKNOWN_TYPE); 347 . { savetoken(yytext); return yytext[0]; } 348 %% 349 #ifdef AMIGA 350 long * 351 alloc(n) 352 unsigned n; 353 { 354 return (long *) malloc(n); 355 } 356 #endif 357 358 /* routine to switch to another input file; needed for flex */ 359 void 360 init_yyin( input_f ) 361 FILE *input_f; 362 { 363 #if defined(FLEX_SCANNER) || defined(FLEXHACK_SCANNER) 364 if (yyin) 365 yyrestart(input_f); 366 else 367 #endif 368 yyin = input_f; 369 370 if (!orig_yyin) 371 orig_yyin = yyin; 372 } 373 /* analogous routine (for completeness) */ 374 void 375 init_yyout( output_f ) 376 FILE *output_f; 377 { 378 yyout = output_f; 379 } 380 381 long 382 handle_varstring_check() 383 { 384 struct lc_vardefs *vd; 385 386 yylval.map = dupstr(yytext); 387 if ((vd = vardef_defined(vardefs, yytext, 1)) != 0) { 388 long l = vd->var_type; 389 int a = ((l & SPOVAR_ARRAY) == SPOVAR_ARRAY); 390 391 l &= ~SPOVAR_ARRAY; 392 if (l == SPOVAR_INT) 393 return (a ? VARSTRING_INT_ARRAY : VARSTRING_INT); 394 if (l == SPOVAR_STRING) 395 return (a ? VARSTRING_STRING_ARRAY : VARSTRING_STRING); 396 if (l == SPOVAR_VARIABLE) 397 return (a ? VARSTRING_VAR_ARRAY : VARSTRING_VAR); 398 if (l == SPOVAR_COORD) 399 return (a ? VARSTRING_COORD_ARRAY : VARSTRING_COORD); 400 if (l == SPOVAR_REGION) 401 return (a ? VARSTRING_REGION_ARRAY : VARSTRING_REGION); 402 if (l == SPOVAR_MAPCHAR) 403 return (a ? VARSTRING_MAPCHAR_ARRAY : VARSTRING_MAPCHAR); 404 if (l == SPOVAR_MONST) 405 return (a ? VARSTRING_MONST_ARRAY : VARSTRING_MONST); 406 if (l == SPOVAR_OBJ) 407 return (a ? VARSTRING_OBJ_ARRAY : VARSTRING_OBJ); 408 if (l == SPOVAR_SEL) 409 return (a ? VARSTRING_SEL_ARRAY : VARSTRING_SEL); 410 } 411 return VARSTRING; 412 } 413 414 void 415 newline() 416 { 417 nh_line_number++; 418 token_start_pos = 0; 419 (void) memset((genericptr_t) curr_token, 0, 512); 420 } 421 422 void 423 savetoken(s) 424 char *s; 425 { 426 Sprintf(curr_token, "%s", s); 427 advancepos(s); 428 } 429 430 void 431 advancepos(s) 432 char *s; 433 { 434 token_start_pos += strlen(s); 435 } 436 437 /*lev_comp.l*/ 438