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