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