1 %{ 2 /* SCCS Id: @(#)lev_lex.c 3.4 2002/03/27 */ 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 #endif /* !FLEX_SCANNER && !FLEXHACK_SCANNER */ 57 58 #ifdef FLEX_SCANNER 59 #define YY_MALLOC_DECL \ 60 genericptr_t FDECL(malloc, (size_t)); \ 61 genericptr_t FDECL(realloc, (genericptr_t,size_t)); 62 #endif 63 64 void FDECL(init_yyin, (FILE *)); 65 void FDECL(init_yyout, (FILE *)); 66 67 void FDECL(include_push, (const char *)); 68 int NDECL(include_pop); 69 70 long NDECL(handle_varstring_check); 71 72 extern struct lc_vardefs *FDECL(vardef_defined,(struct lc_vardefs *,char *, int)); 73 74 extern struct lc_vardefs *variable_definitions; 75 76 /* 77 * This doesn't always get put in lev_comp.h 78 * (esp. when using older versions of bison). 79 */ 80 extern YYSTYPE yylval; 81 82 int line_number = 1, colon_line_number = 1; 83 static char map[4096]; 84 static int map_cnt = 0; 85 86 int doing_included_file = 0; 87 YY_BUFFER_STATE include_stack[5]; 88 int include_line[5]; 89 char *include_file[5]; 90 91 FILE *orig_yyin = NULL; 92 93 %} 94 %e 1500 95 %p 5000 96 %n 700 97 %s MAPC 98 %% 99 <MAPC>ENDMAP { 100 BEGIN(INITIAL); 101 yylval.map = (char *) alloc(map_cnt + 1); 102 (void) strncpy(yylval.map, map, map_cnt); 103 yylval.map[map_cnt] = 0; 104 map_cnt = 0; 105 return MAP_ID; 106 } 107 <MAPC>[-|}{+xABCISHKPLWTF\\#. 0123456789]*\r?\n { 108 int len = yyleng; 109 /* convert \r\n to \n */ 110 if (len >= 2 && yytext[len - 2] == '\r') len -= 1; 111 line_number++; 112 (void) strncpy(map + map_cnt, yytext, len); 113 map_cnt += len; 114 map[map_cnt - 1] = '\n'; 115 map[map_cnt] = '\0'; 116 } 117 ^[ \t]*#.*\n { line_number++; } 118 : { colon_line_number = line_number; return ':'; } 119 MESSAGE return MESSAGE_ID; 120 NOMAP return NOMAP_ID; 121 LEVEL return LEVEL_ID; 122 INIT_MAP return LEV_INIT_ID; 123 mazegrid return MAZE_GRID_ID; 124 solidfill return SOLID_FILL_ID; 125 mines return MINES_ID; 126 FLAGS return FLAGS_ID; 127 GEOMETRY return GEOMETRY_ID; 128 ^MAP\r?\n { BEGIN(MAPC); line_number++; } 129 OBJECT return OBJECT_ID; 130 CONTAINER return COBJECT_ID; 131 MONSTER return MONSTER_ID; 132 TRAP return TRAP_ID; 133 DOOR return DOOR_ID; 134 ROOMDOOR return ROOMDOOR_ID; 135 DRAWBRIDGE return DRAWBRIDGE_ID; 136 MAZEWALK return MAZEWALK_ID; 137 WALLIFY return WALLIFY_ID; 138 REGION return REGION_ID; 139 ALTAR return ALTAR_ID; 140 LADDER return LADDER_ID; 141 STAIR return STAIR_ID; 142 PORTAL return PORTAL_ID; 143 TELEPORT_REGION return TELEPRT_ID; 144 BRANCH return BRANCH_ID; 145 FOUNTAIN return FOUNTAIN_ID; 146 SINK return SINK_ID; 147 POOL return POOL_ID; 148 WALLWALK return WALLWALK_ID; 149 NON_DIGGABLE return NON_DIGGABLE_ID; 150 NON_PASSWALL return NON_PASSWALL_ID; 151 IF return IF_ID; 152 ELSE return ELSE_ID; 153 EXIT return EXIT_ID; 154 ROOM return ROOM_ID; 155 SUBROOM return SUBROOM_ID; 156 RANDOM_CORRIDORS return RAND_CORRIDOR_ID; 157 CORRIDOR return CORRIDOR_ID; 158 SPILL return SPILL_ID; 159 TERRAIN return TERRAIN_ID; 160 REPLACE_TERRAIN return REPLACE_TERRAIN_ID; 161 MON_GENERATION return MON_GENERATION_ID; 162 GOLD return GOLD_ID; 163 GRAVE return GRAVE_ID; 164 ENGRAVING return ENGRAVING_ID; 165 NAME return NAME_ID; 166 CHANCE return CHANCE_ID; 167 LOOP return LOOP_ID; 168 SWITCH return SWITCH_ID; 169 CASE return CASE_ID; 170 BREAK return BREAK_ID; 171 DEFAULT return DEFAULT_ID; 172 FUNCTION return FUNCTION_ID; 173 INCLUDE return INCLUDE_ID; 174 SOUNDS return SOUNDS_ID; 175 SHUFFLE return SHUFFLE_ID; 176 montype return MONTYPE_ID; 177 selection return selection_ID; 178 rect return rect_ID; 179 fillrect return fillrect_ID; 180 line return line_ID; 181 randline return randline_ID; 182 grow return grow_ID; 183 floodfill return flood_ID; 184 rndcoord return rndcoord_ID; 185 circle return circle_ID; 186 ellipse return ellipse_ID; 187 filter return filter_ID; 188 hear { yylval.i=LVLSND_HEARD; return MSG_OUTPUT_TYPE; } 189 pline { yylval.i=LVLSND_PLINED; return MSG_OUTPUT_TYPE; } 190 verbal { yylval.i=LVLSND_VERBAL; return MSG_OUTPUT_TYPE; } 191 feel { yylval.i=LVLSND_FELT; return MSG_OUTPUT_TYPE; } 192 levregion return LEV; 193 quantity return QUANTITY_ID; 194 buried return BURIED_ID; 195 eroded return ERODED_ID; 196 erodeproof return ERODEPROOF_ID; 197 trapped return TRAPPED_ID; 198 recharged return RECHARGED_ID; 199 invisible return INVIS_ID; 200 greased return GREASED_ID; 201 female return FEMALE_ID; 202 cancelled return CANCELLED_ID; 203 revived return REVIVED_ID; 204 avenge return AVENGE_ID; 205 fleeing return FLEEING_ID; 206 blinded return BLINDED_ID; 207 paralyzed return PARALYZED_ID; 208 stunned return STUNNED_ID; 209 confused return CONFUSED_ID; 210 seen_traps return SEENTRAPS_ID; 211 all return ALL_ID; 212 horizontal { yylval.i=1; return HORIZ_OR_VERT; } 213 vertical { yylval.i=2; return HORIZ_OR_VERT; } 214 open { yylval.i=D_ISOPEN; return DOOR_STATE; } 215 closed { yylval.i=D_CLOSED; return DOOR_STATE; } 216 locked { yylval.i=D_LOCKED; return DOOR_STATE; } 217 nodoor { yylval.i=D_NODOOR; return DOOR_STATE; } 218 broken { yylval.i=D_BROKEN; return DOOR_STATE; } 219 secret { yylval.i=D_SECRET; return DOOR_STATE; } 220 north { yylval.i=W_NORTH; return DIRECTION; } 221 east { yylval.i=W_EAST; return DIRECTION; } 222 south { yylval.i=W_SOUTH; return DIRECTION; } 223 west { yylval.i=W_WEST; return DIRECTION; } 224 random { yylval.i = -1; return RANDOM_TYPE; } 225 none { yylval.i = -2; return NONE; } 226 align return A_REGISTER; 227 left { yylval.i=1; return LEFT_OR_RIGHT; } 228 half-left { yylval.i=2; return LEFT_OR_RIGHT; } 229 center { yylval.i=3; return CENTER; } 230 half-right { yylval.i=4; return LEFT_OR_RIGHT; } 231 right { yylval.i=5; return LEFT_OR_RIGHT; } 232 top { yylval.i=1; return TOP_OR_BOT; } 233 bottom { yylval.i=5; return TOP_OR_BOT; } 234 lit { yylval.i=1; return LIGHT_STATE; } 235 unlit { yylval.i=0; return LIGHT_STATE; } 236 filled { yylval.i=0; return FILLING; } 237 unfilled { yylval.i=1; return FILLING; } 238 noalign { yylval.i= AM_NONE; return ALIGNMENT; } 239 law { yylval.i= AM_LAWFUL; return ALIGNMENT; } 240 neutral { yylval.i= AM_NEUTRAL; return ALIGNMENT; } 241 chaos { yylval.i= AM_CHAOTIC; return ALIGNMENT; } 242 coaligned { yylval.i= AM_SPLEV_CO; return ALIGNMENT; } 243 noncoaligned { yylval.i= AM_SPLEV_NONCO; return ALIGNMENT; } 244 peaceful { yylval.i=1; return MON_ATTITUDE; } 245 hostile { yylval.i=0; return MON_ATTITUDE; } 246 asleep { yylval.i=1; return MON_ALERTNESS; } 247 awake { yylval.i=0; return MON_ALERTNESS; } 248 m_feature { yylval.i= M_AP_FURNITURE; return MON_APPEARANCE; } 249 m_monster { yylval.i= M_AP_MONSTER; return MON_APPEARANCE; } 250 m_object { yylval.i= M_AP_OBJECT; return MON_APPEARANCE; } 251 sanctum { yylval.i=2; return ALTAR_TYPE; } 252 shrine { yylval.i=1; return ALTAR_TYPE; } 253 altar { yylval.i=0; return ALTAR_TYPE; } 254 up { yylval.i=1; return UP_OR_DOWN; } 255 down { yylval.i=0; return UP_OR_DOWN; } 256 false { yylval.i=0; return BOOLEAN; } 257 true { yylval.i=1; return BOOLEAN; } 258 dust { yylval.i=DUST; return ENGRAVING_TYPE; } 259 engrave { yylval.i=ENGRAVE; return ENGRAVING_TYPE; } 260 burn { yylval.i=BURN; return ENGRAVING_TYPE; } 261 mark { yylval.i=MARK; return ENGRAVING_TYPE; } 262 blood { yylval.i=ENGR_BLOOD; return ENGRAVING_TYPE; } 263 blessed { yylval.i=1; return CURSE_TYPE; } 264 uncursed { yylval.i=2; return CURSE_TYPE; } 265 cursed { yylval.i=3; return CURSE_TYPE; } 266 noteleport { yylval.i=NOTELEPORT; return FLAG_TYPE; } 267 hardfloor { yylval.i=HARDFLOOR; return FLAG_TYPE; } 268 nommap { yylval.i=NOMMAP; return FLAG_TYPE; } 269 arboreal { yylval.i=ARBOREAL; return FLAG_TYPE; } /* KMH */ 270 shortsighted { yylval.i=SHORTSIGHTED; return FLAG_TYPE; } 271 noflipx { yylval.i=NOFLIPX; return FLAG_TYPE; } 272 noflipy { yylval.i=NOFLIPY; return FLAG_TYPE; } 273 noflip { yylval.i=(NOFLIPX + NOFLIPY); return FLAG_TYPE; } 274 mazelevel { yylval.i=MAZELEVEL; return FLAG_TYPE; } 275 premapped { yylval.i=PREMAPPED; return FLAG_TYPE; } 276 shroud { yylval.i=SHROUD; return FLAG_TYPE; } 277 stormy { yylval.i=STORMY; return FLAG_TYPE; } 278 graveyard { yylval.i=GRAVEYARD; return FLAG_TYPE; } 279 [0-9]+d[0-9]+ { char *p = strchr(yytext, 'd'); 280 if (p) { 281 *p = '\0'; 282 p++; 283 yylval.dice.num=atoi(yytext); 284 yylval.dice.die=atoi(p); 285 } else { yylval.dice.num = yylval.dice.die = 1; } 286 return DICE; 287 } 288 \[\ *[0-9]+\%\ *\] { yylval.i = atoi(yytext + 1); return PERCENT; } 289 -[0-9]+ { yylval.i=atoi(yytext); return MINUS_INTEGER; } 290 \+[0-9]+ { yylval.i=atoi(yytext); return PLUS_INTEGER; } 291 [0-9]+\% { yylval.i = atoi(yytext); return SPERCENT; } 292 [0-9]+ { yylval.i=atoi(yytext); return INTEGER; } 293 \"[^"]*\" { yytext[yyleng-1] = 0; /* Discard the trailing \" */ 294 yylval.map = (char *) alloc(strlen(yytext+1)+1); 295 Strcpy(yylval.map, yytext+1); /* Discard the first \" */ 296 return STRING; } 297 \$[a-zA-Z_][a-zA-Z_0-9]* { return handle_varstring_check(); } 298 [a-zA-Z_][a-zA-Z_0-9]* { yylval.map = (char *) alloc(strlen(yytext)+1); 299 Strcpy(yylval.map, yytext); 300 return NQSTRING; } 301 "==" { yylval.i = SPO_JE; return COMPARE_TYPE; } 302 "!=" { yylval.i = SPO_JNE; return COMPARE_TYPE; } 303 "<>" { yylval.i = SPO_JNE; return COMPARE_TYPE; } 304 "<=" { yylval.i = SPO_JLE; return COMPARE_TYPE; } 305 ">=" { yylval.i = SPO_JGE; return COMPARE_TYPE; } 306 "<" { yylval.i = SPO_JL; return COMPARE_TYPE; } 307 ">" { yylval.i = SPO_JG; return COMPARE_TYPE; } 308 \r?\n { line_number++; } 309 [ \t]+ ; 310 '\\.' { yylval.i = yytext[2]; return CHAR; } 311 '.' { yylval.i = yytext[1]; return CHAR; } 312 . { return yytext[0]; } 313 %% 314 #ifdef AMIGA 315 long *alloc(n) 316 unsigned n; 317 { 318 return ((long *)malloc (n)); 319 } 320 #endif 321 322 /* routine to switch to another input file; needed for flex */ 323 void init_yyin( input_f ) 324 FILE *input_f; 325 { 326 #if defined(FLEX_SCANNER) || defined(FLEXHACK_SCANNER) 327 if (yyin) 328 yyrestart(input_f); 329 else 330 #endif 331 yyin = input_f; 332 if (!orig_yyin) orig_yyin = yyin; 333 } 334 /* analogous routine (for completeness) */ 335 void init_yyout( output_f ) 336 FILE *output_f; 337 { 338 yyout = output_f; 339 } 340 341 void 342 include_push(fname) 343 const char *fname; 344 { 345 if (doing_included_file >= 5) 346 yyerror("Too deep includes"); 347 else { 348 FILE *fin; 349 fin = fopen(fname, "r"); 350 if (!fin) { 351 yyerror("Cannot open file for including."); 352 } else { 353 include_stack[doing_included_file] = YY_CURRENT_BUFFER; 354 include_line[doing_included_file] = line_number; 355 include_file[doing_included_file] = strdup(fname); 356 doing_included_file++; 357 yyin = fin; 358 yy_switch_to_buffer(yy_create_buffer(fin, YY_BUF_SIZE)); 359 BEGIN(INITIAL); 360 yyparse(); 361 } 362 } 363 } 364 365 int 366 include_pop() 367 { 368 if (--doing_included_file < 0) { 369 doing_included_file = 0; 370 init_yyin(orig_yyin); 371 yy_switch_to_buffer(yy_create_buffer(orig_yyin, YY_BUF_SIZE)); 372 } else { 373 if (include_file[doing_included_file]) 374 free(include_file[doing_included_file]); 375 yy_switch_to_buffer(include_stack[doing_included_file]); 376 line_number = include_line[doing_included_file]; 377 } 378 return 0; 379 } 380 381 /* 382 * Stub needed for lex interface. 383 */ 384 int 385 yywrap() 386 { 387 if (doing_included_file >= 0) include_pop(); 388 return 1; 389 } 390 391 long 392 handle_varstring_check() 393 { 394 struct lc_vardefs *vd; 395 yylval.map = (char *) alloc(strlen(yytext)+1); 396 Strcpy(yylval.map, yytext); 397 if ((vd = vardef_defined(variable_definitions, yytext, 1))) { 398 long l = vd->var_type; 399 long a = ((l & SPOVAR_ARRAY) == SPOVAR_ARRAY); 400 l = (l & ~SPOVAR_ARRAY); 401 if (l == SPOVAR_INT) return (a ? VARSTRING_INT_ARRAY : VARSTRING_INT); 402 if (l == SPOVAR_STRING) return (a ? VARSTRING_STRING_ARRAY : VARSTRING_STRING); 403 if (l == SPOVAR_VARIABLE) return (a ? VARSTRING_VAR_ARRAY : VARSTRING_VAR); 404 if (l == SPOVAR_COORD) return (a ? VARSTRING_COORD_ARRAY : VARSTRING_COORD); 405 if (l == SPOVAR_REGION) return (a ? VARSTRING_REGION_ARRAY : VARSTRING_REGION); 406 if (l == SPOVAR_MAPCHAR) return (a ? VARSTRING_MAPCHAR_ARRAY : VARSTRING_MAPCHAR); 407 if (l == SPOVAR_MONST) return (a ? VARSTRING_MONST_ARRAY : VARSTRING_MONST); 408 if (l == SPOVAR_OBJ) return (a ? VARSTRING_OBJ_ARRAY : VARSTRING_OBJ); 409 if (l == SPOVAR_SEL) return (a ? VARSTRING_SEL_ARRAY : VARSTRING_SEL); 410 } 411 return VARSTRING; 412 } 413 414 /*lev_comp.l*/ 415