1 /*	SCCS Id: @(#)lev_main.c	3.4	2002/03/27	*/
2 /*	Copyright (c) 1989 by Jean-Christophe Collet */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 /*
6  * This file contains the main function for the parser
7  * and some useful functions needed by yacc
8  */
9 #define SPEC_LEV	/* for MPW */
10 /* although, why don't we move those special defines here.. and in dgn_main? */
11 
12 #include <stdarg.h>
13 
14 #include "hack.h"
15 #include "date.h"
16 #include "sp_lev.h"
17 #ifdef STRICT_REF_DEF
18 #include "tcap.h"
19 #endif
20 
21 #ifdef MAC
22 # if defined(__SC__) || defined(__MRC__)
23 #  define MPWTOOL
24 #  define PREFIX ":dungeon:"	/* place output files here */
25 #  include <CursorCtl.h>
26 # else
27 #  if !defined(__MACH__)
28 #   define PREFIX ":lib:"	/* place output files here */
29 #  endif
30 # endif
31 #endif
32 
33 #ifdef WIN_CE
34 #define PREFIX "\\nethack\\dat\\"
35 #endif
36 
37 #ifndef MPWTOOL
38 # define SpinCursor(x)
39 #endif
40 
41 #if defined(AMIGA) && defined(DLB)
42 # define PREFIX "NH:slib/"
43 #endif
44 
45 #ifndef O_WRONLY
46 #include <fcntl.h>
47 #endif
48 #ifndef O_CREAT	/* some older BSD systems do not define O_CREAT in <fcntl.h> */
49 #include <sys/file.h>
50 #endif
51 #ifndef O_BINARY	/* used for micros, no-op for others */
52 # define O_BINARY 0
53 #endif
54 
55 #if defined(MICRO) || defined(WIN32)
56 # define OMASK FCMASK
57 #else
58 # define OMASK 0644
59 #endif
60 
61 #define ERR		(-1)
62 
63 #define NewTab(type, size)	(type **) alloc(sizeof(type *) * size)
64 #define Free(ptr)		if(ptr) free((genericptr_t) (ptr))
65 #define Write(fd, item, size)	if (write(fd, (genericptr_t)(item), size) != size) return FALSE;
66 
67 #if defined(__BORLANDC__) && !defined(_WIN32)
68 extern unsigned _stklen = STKSIZ;
69 #endif
70 #define MAX_ERRORS	25
71 
72 extern int  NDECL (yyparse);
73 extern void FDECL (init_yyin, (FILE *));
74 extern void FDECL (init_yyout, (FILE *));
75 
76 int  FDECL (main, (int, char **));
77 void FDECL (yyerror, (const char *));
78 void FDECL (yywarning, (const char *));
79 int  NDECL (yywrap);
80 int FDECL(get_floor_type, (CHAR_P));
81 int FDECL(get_room_type, (char *));
82 int FDECL(get_trap_type, (char *));
83 int FDECL(get_monster_id, (char *,CHAR_P));
84 int FDECL(get_object_id, (char *,CHAR_P));
85 boolean FDECL(check_monster_char, (CHAR_P));
86 boolean FDECL(check_object_char, (CHAR_P));
87 char FDECL(what_map_char, (CHAR_P));
88 void FDECL(scan_map, (char *, sp_lev *));
89 boolean FDECL(check_subrooms, (sp_lev *));
90 boolean FDECL(write_level_file, (char *,sp_lev *));
91 
92 struct lc_funcdefs *FDECL(funcdef_new,(long,char *));
93 void FDECL(funcdef_free_all,(struct lc_funcdefs *));
94 struct lc_funcdefs *FDECL(funcdef_defined,(struct lc_funcdefs *,char *, int));
95 
96 struct lc_vardefs *FDECL(vardef_new,(long,char *));
97 void FDECL(vardef_free_all,(struct lc_vardefs *));
98 struct lc_vardefs *FDECL(vardef_defined,(struct lc_vardefs *,char *, int));
99 
100 void FDECL(splev_add_from, (sp_lev *, sp_lev *));
101 
102 extern void NDECL(monst_init);
103 extern void NDECL(objects_init);
104 extern void NDECL(decl_init);
105 
106 void FDECL(add_opcode, (sp_lev *, int, genericptr_t));
107 
108 static boolean FDECL(write_common_data, (int,sp_lev *));
109 static boolean FDECL(write_maze, (int,sp_lev *));
110 static void NDECL(init_obj_classes);
111 
112 static struct {
113 	const char *name;
114 	int type;
115 } trap_types[] = {
116 	{ "arrow",	ARROW_TRAP },
117 	{ "dart",	DART_TRAP },
118 	{ "falling rock", ROCKTRAP },
119 	{ "board",	SQKY_BOARD },
120 	{ "bear",	BEAR_TRAP },
121 	{ "land mine",	LANDMINE },
122 	{ "rolling boulder",	ROLLING_BOULDER_TRAP },
123 	{ "sleep gas",	SLP_GAS_TRAP },
124 	{ "rust",	RUST_TRAP },
125 	{ "fire",	FIRE_TRAP },
126 	{ "pit",	PIT },
127 	{ "spiked pit",	SPIKED_PIT },
128 	{ "hole",	HOLE },
129 	{ "trap door",	TRAPDOOR },
130 	{ "teleport",	TELEP_TRAP },
131 	{ "level teleport", LEVEL_TELEP },
132 	{ "magic portal",   MAGIC_PORTAL },
133 	{ "web",	WEB },
134 	{ "statue",	STATUE_TRAP },
135 	{ "magic",	MAGIC_TRAP },
136 	{ "anti magic",	ANTI_MAGIC },
137 	{ "polymorph",	POLY_TRAP },
138 	{ 0, 0 }
139 };
140 
141 static struct {
142 	const char *name;
143 	int type;
144 } room_types[] = {
145 	/* for historical reasons, room types are not contiguous numbers */
146 	/* (type 1 is skipped) */
147 	{ "ordinary",	 OROOM },
148 	{ "throne",	 COURT },
149 	{ "swamp",	 SWAMP },
150 	{ "vault",	 VAULT },
151 	{ "beehive",	 BEEHIVE },
152 	{ "morgue",	 MORGUE },
153 	{ "barracks",	 BARRACKS },
154 	{ "zoo",	 ZOO },
155 	{ "delphi",	 DELPHI },
156 	{ "temple",	 TEMPLE },
157 	{ "lemurepit",   LEMUREPIT },
158 	{ "anthole",	 ANTHOLE },
159 	{ "cocknest",	 COCKNEST },
160 	{ "garden",	 GARDEN },
161 	{ "leprehall",	 LEPREHALL },
162 	{ "shop",	 SHOPBASE },
163 	{ "armor shop",	 ARMORSHOP },
164 	{ "scroll shop", SCROLLSHOP },
165 	{ "potion shop", POTIONSHOP },
166 	{ "weapon shop", WEAPONSHOP },
167 	{ "food shop",	 FOODSHOP },
168 	{ "ring shop",	 RINGSHOP },
169 	{ "wand shop",	 WANDSHOP },
170 	{ "tool shop",	 TOOLSHOP },
171 	{ "book shop",	 BOOKSHOP },
172 	{ "tin shop",	 TINSHOP },
173 	{ "music shop",	 INSTRUMENTSHOP },
174 	{ "candle shop", CANDLESHOP },
175 	{ "pet shop",	 PETSHOP },	/* Stephen White */
176 #ifdef BLACKMARKET
177 	{ "black market", BLACKSHOP },
178 #endif /* BLACKMARKET */
179 	{ 0, 0 }
180 };
181 
182 const char *fname = "(stdin)";
183 int fatal_error = 0;
184 int got_errors = 0;
185 int be_verbose = 0;
186 int decompile = 0;
187 
188 #ifdef FLEX23_BUG
189 /* Flex 2.3 bug work around; not needed for 2.3.6 or later */
190 int yy_more_len = 0;
191 #endif
192 
193 extern unsigned int max_x_map, max_y_map;
194 
195 extern int line_number, colon_line_number;
196 
197 struct lc_vardefs *variable_definitions = NULL;
198 
199 
200 int
main(argc,argv)201 main(argc, argv)
202 int argc;
203 char **argv;
204 {
205 	FILE *fin;
206 	int i;
207 	boolean errors_encountered = FALSE;
208 #if defined(MAC) && (defined(THINK_C) || defined(__MWERKS__))
209 	static char *mac_argv[] = {	"lev_comp",	/* dummy argv[0] */
210 				":dat:Arch.des",
211 				":dat:Barb.des",
212 				":dat:Caveman.des",
213 				":dat:Healer.des",
214 				":dat:Knight.des",
215 				":dat:Monk.des",
216 				":dat:Priest.des",
217 				":dat:Ranger.des",
218 				":dat:Rogue.des",
219 				":dat:Samurai.des",
220 				":dat:Tourist.des",
221 				":dat:Valkyrie.des",
222 				":dat:Wizard.des",
223 				":dat:bigroom.des",
224 				":dat:castle.des",
225 				":dat:endgame.des",
226 				":dat:gehennom.des",
227 				":dat:knox.des",
228 				":dat:medusa.des",
229 				":dat:mines.des",
230 				":dat:oracle.des",
231 				":dat:sokoban.des",
232 				":dat:tower.des",
233 				":dat:yendor.des"
234 				};
235 
236 	argc = SIZE(mac_argv);
237 	argv = mac_argv;
238 #endif
239 	/* Note:  these initializers don't do anything except guarantee that
240 		we're linked properly.
241 	*/
242 	monst_init();
243 	objects_init();
244 	decl_init();
245 	/* this one does something... */
246 	init_obj_classes();
247 
248 	init_yyout(stdout);
249 	if (argc == 1) {		/* Read standard input */
250 	    init_yyin(stdin);
251 	    (void) yyparse();
252 	    if (fatal_error > 0 || got_errors > 0) {
253 		    errors_encountered = TRUE;
254 	    }
255 	} else {			/* Otherwise every argument is a filename */
256 	    for(i=1; i<argc; i++) {
257 		    fname = argv[i];
258 		    if(!strcmp(fname, "-v")) {
259 			be_verbose++;
260 			continue;
261 		    }
262 		    if(!strcmp(fname, "-d")) {
263 			decompile = 1;
264 			continue;
265 		    }
266 		    fin = freopen(fname, "r", stdin);
267 		    if (!fin) {
268 			(void) fprintf(stderr,"Can't open \"%s\" for input.\n",
269 						fname);
270 			perror(fname);
271 			errors_encountered = TRUE;
272 		    } else {
273 			init_yyin(fin);
274 			(void) yyparse();
275 			line_number = 1;
276 			if (fatal_error > 0 || got_errors > 0) {
277 				errors_encountered = TRUE;
278 				fatal_error = 0;
279 			}
280 		    }
281 		    (void) fclose(fin);
282 	    }
283 	}
284 	exit(errors_encountered ? EXIT_FAILURE : EXIT_SUCCESS);
285 	/*NOTREACHED*/
286 	return 0;
287 }
288 
289 /*
290  * Each time the parser detects an error, it uses this function.
291  * Here we take count of the errors. To continue farther than
292  * MAX_ERRORS wouldn't be reasonable.
293  * Assume that explicit calls from lev_comp.y have the 1st letter
294  * capitalized, to allow printing of the line containing the start of
295  * the current declaration, instead of the beginning of the next declaration.
296  */
297 void
yyerror(s)298 yyerror(s)
299 const char *s;
300 {
301 	(void) fprintf(stderr, "%s: line %d : %s\n", fname,
302 		(*s >= 'A' && *s <= 'Z') ? colon_line_number : line_number, s);
303 	if (++fatal_error > MAX_ERRORS) {
304 		(void) fprintf(stderr,"Too many errors, good bye!\n");
305 		exit(EXIT_FAILURE);
306 	}
307 }
308 
309 
310 void
lc_error(const char * fmt,...)311 lc_error(const char *fmt, ...)
312 {
313     char buf[512];
314     va_list argp;
315 
316     va_start(argp, fmt);
317     (void) vsnprintf(buf, 511, fmt, argp);
318     va_end(argp);
319 
320     yyerror(buf);
321 }
322 
323 
324 /*
325  * Just display a warning (that is : a non fatal error)
326  */
327 void
yywarning(s)328 yywarning(s)
329 const char *s;
330 {
331 	(void) fprintf(stderr, "%s: line %d : WARNING : %s\n",
332 				fname, colon_line_number, s);
333 }
334 
335 void
lc_warning(const char * fmt,...)336 lc_warning(const char *fmt, ...)
337 {
338     char buf[512];
339     va_list argp;
340 
341     va_start(argp, fmt);
342     (void) vsnprintf(buf, 511, fmt, argp);
343     va_end(argp);
344 
345     yywarning(buf);
346 }
347 
348 
349 struct opvar *
set_opvar_int(ov,val)350 set_opvar_int(ov, val)
351 struct opvar *ov;
352 long  val;
353 {
354     if (ov) {
355         ov->spovartyp = SPOVAR_INT;
356         ov->vardata.l = val;
357     }
358     return ov;
359 }
360 
361 struct opvar *
set_opvar_coord(ov,val)362 set_opvar_coord(ov, val)
363 struct opvar *ov;
364 long  val;
365 {
366     if (ov) {
367         ov->spovartyp = SPOVAR_COORD;
368         ov->vardata.l = val;
369     }
370     return ov;
371 }
372 
373 struct opvar *
set_opvar_region(ov,val)374 set_opvar_region(ov, val)
375 struct opvar *ov;
376 long  val;
377 {
378     if (ov) {
379         ov->spovartyp = SPOVAR_REGION;
380         ov->vardata.l = val;
381     }
382     return ov;
383 }
384 
385 struct opvar *
set_opvar_mapchar(ov,val)386 set_opvar_mapchar(ov, val)
387 struct opvar *ov;
388 long  val;
389 {
390     if (ov) {
391         ov->spovartyp = SPOVAR_MAPCHAR;
392         ov->vardata.l = val;
393     }
394     return ov;
395 }
396 
397 struct opvar *
set_opvar_monst(ov,val)398 set_opvar_monst(ov, val)
399 struct opvar *ov;
400 long  val;
401 {
402     if (ov) {
403         ov->spovartyp = SPOVAR_MONST;
404         ov->vardata.l = val;
405     }
406     return ov;
407 }
408 
409 struct opvar *
set_opvar_obj(ov,val)410 set_opvar_obj(ov, val)
411 struct opvar *ov;
412 long  val;
413 {
414     if (ov) {
415         ov->spovartyp = SPOVAR_OBJ;
416         ov->vardata.l = val;
417     }
418     return ov;
419 }
420 
421 struct opvar *
set_opvar_str(ov,val)422 set_opvar_str(ov, val)
423 struct opvar *ov;
424 char *val;
425 {
426     if (ov) {
427         ov->spovartyp = SPOVAR_STRING;
428 	ov->vardata.str = (val) ? strdup(val) : NULL;
429     }
430     return ov;
431 }
432 
433 struct opvar *
set_opvar_var(ov,val)434 set_opvar_var(ov, val)
435 struct opvar *ov;
436 char *val;
437 {
438     if (ov) {
439         ov->spovartyp = SPOVAR_VARIABLE;
440 	ov->vardata.str = (val) ? strdup(val) : NULL;
441     }
442     return ov;
443 }
444 
445 #define New(type)		\
446 	(type *) memset((genericptr_t)alloc(sizeof(type)), 0, sizeof(type))
447 
448 void
add_opvars(sp_lev * sp,const char * fmt,...)449 add_opvars(sp_lev *sp, const char *fmt, ...)
450 {
451     const char *p;
452     va_list argp;
453 
454     va_start(argp, fmt);
455 
456     for(p = fmt; *p != '\0'; p++) {
457 	switch(*p) {
458 	case ' ': break;
459 	case 'i':
460 	    {
461 		struct opvar *ov = New(struct opvar);
462 		set_opvar_int(ov, va_arg(argp, long));
463 		add_opcode(sp, SPO_PUSH, ov);
464 		break;
465 	    }
466 	case 'c':
467 	    {
468 		struct opvar *ov = New(struct opvar);
469 		set_opvar_coord(ov, va_arg(argp, long));
470 		add_opcode(sp, SPO_PUSH, ov);
471 		break;
472 	    }
473 	case 'r':
474 	    {
475 		struct opvar *ov = New(struct opvar);
476 		set_opvar_region(ov, va_arg(argp, long));
477 		add_opcode(sp, SPO_PUSH, ov);
478 		break;
479 	    }
480 	case 'm':
481 	    {
482 		struct opvar *ov = New(struct opvar);
483 		set_opvar_mapchar(ov, va_arg(argp, long));
484 		add_opcode(sp, SPO_PUSH, ov);
485 		break;
486 	    }
487 	case 'M':
488 	    {
489 		struct opvar *ov = New(struct opvar);
490 		set_opvar_monst(ov, va_arg(argp, long));
491 		add_opcode(sp, SPO_PUSH, ov);
492 		break;
493 	    }
494 	case 'O':
495 	    {
496 		struct opvar *ov = New(struct opvar);
497 		set_opvar_obj(ov, va_arg(argp, long));
498 		add_opcode(sp, SPO_PUSH, ov);
499 		break;
500 	    }
501 	case 's':
502 	    {
503 		struct opvar *ov = New(struct opvar);
504 		set_opvar_str(ov, va_arg(argp, char *));
505 		add_opcode(sp, SPO_PUSH, ov);
506 		break;
507 	    }
508 	case 'v':
509 	    {
510 		struct opvar *ov = New(struct opvar);
511 		set_opvar_var(ov, va_arg(argp, char *));
512 		add_opcode(sp, SPO_PUSH, ov);
513 		break;
514 	    }
515 	case 'o':
516 	    {
517 		long i = va_arg(argp, int);
518 		if (i < 0 || i >= MAX_SP_OPCODES)
519 		    fprintf(stderr, "add_opvars: unknown opcode '%i'.\n", i);
520 		add_opcode(sp, i, NULL);
521 		break;
522 	    }
523 	default:
524 	    fprintf(stderr, "add_opvars: illegal format character '%c'.\n", *p);
525 	    break;
526 	}
527     }
528 
529     va_end(argp);
530 }
531 
532 
533 struct lc_funcdefs *
funcdef_new(addr,name)534 funcdef_new(addr, name)
535      long addr;
536      char *name;
537 {
538     struct lc_funcdefs *f = New(struct lc_funcdefs);
539     if (!f) {
540 	lc_error("Could not alloc function definition for '%s'.", name);
541 	return NULL;
542     }
543     f->next = NULL;
544     f->addr = addr;
545     f->name = strdup(name);
546     f->n_called = 0;
547     f->code.opcodes = NULL;
548     f->code.n_opcodes = 0;
549     return f;
550 }
551 
552 void
funcdef_free_all(fchain)553 funcdef_free_all(fchain)
554      struct lc_funcdefs *fchain;
555 {
556     struct lc_funcdefs *tmp = fchain;
557     struct lc_funcdefs *nxt;
558     while (tmp) {
559 	nxt = tmp->next;
560 	Free(tmp->name);
561 	/* FIXME: free tmp->code */
562 	Free(tmp);
563 	tmp = nxt;
564     }
565 }
566 
567 struct lc_funcdefs *
funcdef_defined(f,name,casesense)568 funcdef_defined(f, name, casesense)
569      struct lc_funcdefs *f;
570      char *name;
571      int casesense;
572 {
573     while (f) {
574 	if (casesense) {
575 	    if (!strcmp(name, f->name)) return f;
576 	} else {
577 	    if (!strcasecmp(name, f->name)) return f;
578 	}
579 	f = f->next;
580     }
581     return NULL;
582 }
583 
584 
585 struct lc_vardefs *
vardef_new(typ,name)586 vardef_new(typ, name)
587      long typ;
588      char *name;
589 {
590     struct lc_vardefs *f = New(struct lc_vardefs);
591     if (!f) {
592 	lc_error("Could not alloc variable definition for '%s'.", name);
593 	return NULL;
594     }
595     f->next = NULL;
596     f->var_type = typ;
597     f->name = strdup(name);
598     return f;
599 }
600 
601 void
vardef_free_all(fchain)602 vardef_free_all(fchain)
603      struct lc_vardefs *fchain;
604 {
605     struct lc_vardefs *tmp = fchain;
606     struct lc_vardefs *nxt;
607     while (tmp) {
608 	nxt = tmp->next;
609 	Free(tmp->name);
610 	Free(tmp);
611 	tmp = nxt;
612     }
613 }
614 
615 struct lc_vardefs *
vardef_defined(f,name,casesense)616 vardef_defined(f, name, casesense)
617      struct lc_vardefs *f;
618      char *name;
619      int casesense;
620 {
621     while (f) {
622 	if (casesense) {
623 	    if (!strcmp(name, f->name)) return f;
624 	} else {
625 	    if (!strcasecmp(name, f->name)) return f;
626 	}
627 	f = f->next;
628     }
629     return NULL;
630 }
631 
632 const char *
spovar2str(spovar)633 spovar2str(spovar)
634      long spovar;
635 {
636     static togl = 0;
637     static char buf[2][128];
638     char *n;
639     int is_array = (spovar & SPOVAR_ARRAY);
640     spovar &= ~SPOVAR_ARRAY;
641 
642     switch (spovar) {
643     default:		  lc_error("spovar2str(%li)", spovar); break;
644     case SPOVAR_INT:	  n = "integer"; break;
645     case SPOVAR_STRING:   n = "string"; break;
646     case SPOVAR_VARIABLE: n = "variable"; break;
647     case SPOVAR_COORD:	  n = "coordinate"; break;
648     case SPOVAR_REGION:	  n = "region"; break;
649     case SPOVAR_MAPCHAR:  n = "mapchar"; break;
650     case SPOVAR_MONST:	  n = "monster"; break;
651     case SPOVAR_OBJ:	  n = "object"; break;
652     }
653 
654     togl = ((togl + 1) % 2);
655 
656     snprintf(buf[togl], 127, "%s%s", n, (is_array ? " array" : ""));
657     return buf[togl];
658 }
659 
660 void
check_vardef_type(vd,varname,vartype)661 check_vardef_type(vd, varname, vartype)
662      struct lc_vardefs *vd;
663      char *varname;
664      long vartype;
665 {
666     struct lc_vardefs *tmp;
667     if ((tmp = vardef_defined(vd, varname, 1))) {
668 	if (tmp->var_type != vartype)
669 	    lc_error("Trying to use variable '%s' as %s, when it is %s.",
670 		     varname, spovar2str(vartype), spovar2str(tmp->var_type));
671     } else lc_error("Variable '%s' not defined.", varname);
672 }
673 
674 struct lc_vardefs *
add_vardef_type(vd,varname,vartype)675 add_vardef_type(vd, varname, vartype)
676      struct lc_vardefs *vd;
677      char *varname;
678      long vartype;
679 {
680     struct lc_vardefs *tmp;
681     if ((tmp = vardef_defined(vd, varname, 1))) {
682 	if (tmp->var_type != vartype)
683 	    lc_error("Trying to redefine variable '%s' as %s, when it is %s.",
684 		     varname, spovar2str(vartype), spovar2str(tmp->var_type));
685     } else {
686 	tmp = vardef_new(vartype, varname);
687 	tmp->next = vd;
688 	return tmp;
689     }
690     return vd;
691 }
692 
693 int
reverse_jmp_opcode(opcode)694 reverse_jmp_opcode(opcode)
695      int opcode;
696 {
697     switch (opcode) {
698     case SPO_JE:  return SPO_JNE;
699     case SPO_JNE: return SPO_JE;
700     case SPO_JL:  return SPO_JGE;
701     case SPO_JG:  return SPO_JLE;
702     case SPO_JLE: return SPO_JG;
703     case SPO_JGE: return SPO_JL;
704     default: lc_error("Cannot reverse comparison jmp opcode %i.", opcode); return SPO_NULL;
705     }
706 }
707 
708 /* basically copied from src/sp_lev.c */
709 struct opvar *
opvar_clone(ov)710 opvar_clone(ov)
711      struct opvar *ov;
712 {
713     if (ov) {
714 	struct opvar *tmpov = (struct opvar *)alloc(sizeof(struct opvar));
715 	if (!tmpov) panic("could not alloc opvar struct");
716 	switch (ov->spovartyp) {
717 	case SPOVAR_COORD:
718 	case SPOVAR_REGION:
719 	case SPOVAR_MAPCHAR:
720 	case SPOVAR_MONST:
721 	case SPOVAR_OBJ:
722 	case SPOVAR_INT:
723 	    {
724 		tmpov->spovartyp = ov->spovartyp;
725 		tmpov->vardata.l = ov->vardata.l;
726 	    }
727 	    break;
728 	case SPOVAR_VARIABLE:
729 	case SPOVAR_STRING:
730 	    {
731 		int len = strlen(ov->vardata.str);
732 		tmpov->spovartyp = ov->spovartyp;
733 		tmpov->vardata.str = (char *)alloc(len+1);
734 		(void)memcpy((genericptr_t)tmpov->vardata.str,
735 			     (genericptr_t)ov->vardata.str, len);
736 		tmpov->vardata.str[len] = '\0';
737 	    }
738 	    break;
739 	default:
740 	    {
741 		lc_error("Unknown opvar_clone value type (%i)!", ov->spovartyp);
742 	    }
743 	}
744 	return tmpov;
745     }
746     return NULL;
747 }
748 
749 
750 void
splev_add_from(splev,from_splev)751 splev_add_from(splev, from_splev)
752      sp_lev *splev;
753      sp_lev *from_splev;
754 {
755     int i;
756     if (splev && from_splev)
757 	for (i = 0; i < from_splev->n_opcodes; i++)
758 	    add_opcode(splev, from_splev->opcodes[i].opcode, opvar_clone(from_splev->opcodes[i].opdat));
759 }
760 
761 
762 /*
763  * Find the type of floor, knowing its char representation.
764  */
765 int
get_floor_type(c)766 get_floor_type(c)
767 char c;
768 {
769 	int val;
770 
771 	SpinCursor(3);
772 	val = what_map_char(c);
773 	if(val == INVALID_TYPE) {
774 	    val = ERR;
775 	    lc_warning("Invalid fill character '%c' in MAZE declaration", c);
776 	}
777 	return val;
778 }
779 
780 /*
781  * Find the type of a room in the table, knowing its name.
782  */
783 int
get_room_type(s)784 get_room_type(s)
785 char *s;
786 {
787 	register int i;
788 
789 	SpinCursor(3);
790 	for(i=0; room_types[i].name; i++)
791 	    if (!strcmp(s, room_types[i].name))
792 		return ((int) room_types[i].type);
793 	return ERR;
794 }
795 
796 /*
797  * Find the type of a trap in the table, knowing its name.
798  */
799 int
get_trap_type(s)800 get_trap_type(s)
801 char *s;
802 {
803 	register int i;
804 
805 	SpinCursor(3);
806 	for (i=0; trap_types[i].name; i++)
807 	    if(!strcmp(s,trap_types[i].name))
808 		return trap_types[i].type;
809 	return ERR;
810 }
811 
812 /*
813  * Find the index of a monster in the table, knowing its name.
814  */
815 int
get_monster_id(s,c)816 get_monster_id(s, c)
817 char *s;
818 char c;
819 {
820 	register int i, class;
821 
822 	SpinCursor(3);
823 	class = c ? def_char_to_monclass(c) : 0;
824 	if (class == MAXMCLASSES) return ERR;
825 
826 	for (i = LOW_PM; i < NUMMONS; i++)
827 	    if (!class || class == mons[i].mlet)
828 		if (!strcmp(s, mons[i].mname)) return i;
829 	/* didn't find it; lets try case insensitive search */
830 	for (i = LOW_PM; i < NUMMONS; i++)
831 	    if (!class || class == mons[i].mlet)
832 		if (!strcasecmp(s, mons[i].mname)) {
833 		    if (be_verbose)
834 			lc_warning("Monster type \"%s\" matches \"%s\".", s, mons[i].mname);
835 		    return i;
836 		}
837 	return ERR;
838 }
839 
840 /*
841  * Find the index of an object in the table, knowing its name.
842  */
843 int
get_object_id(s,c)844 get_object_id(s, c)
845 char *s;
846 char c;		/* class */
847 {
848 	int i, class;
849 	const char *objname;
850 
851 	SpinCursor(3);
852 	class = (c > 0) ? def_char_to_objclass(c) : 0;
853 	if (class == MAXOCLASSES) return ERR;
854 
855 	for (i = class ? bases[class] : 0; i < NUM_OBJECTS; i++) {
856 	    if (class && objects[i].oc_class != class) break;
857 	    objname = obj_descr[i].oc_name;
858 	    if (objname && !strcmp(s, objname))
859 		return i;
860 	}
861 
862 	for (i = class ? bases[class] : 0; i < NUM_OBJECTS; i++) {
863 	    if (class && objects[i].oc_class != class) break;
864 	    objname = obj_descr[i].oc_name;
865 	    if (objname && !strcasecmp(s, objname)) {
866 		if (be_verbose)
867 		    lc_warning("Object type \"%s\" matches \"%s\".", s, objname);
868 		return i;
869 	    }
870 	}
871 
872 	return ERR;
873 }
874 
875 static void
init_obj_classes()876 init_obj_classes()
877 {
878 	int i, class, prev_class;
879 
880 	prev_class = -1;
881 	for (i = 0; i < NUM_OBJECTS; i++) {
882 	    class = objects[i].oc_class;
883 	    if (class != prev_class) {
884 		bases[class] = i;
885 		prev_class = class;
886 	    }
887 	}
888 }
889 
890 /*
891  * Is the character 'c' a valid monster class ?
892  */
893 boolean
check_monster_char(c)894 check_monster_char(c)
895 char c;
896 {
897 	return (def_char_to_monclass(c) != MAXMCLASSES);
898 }
899 
900 /*
901  * Is the character 'c' a valid object class ?
902  */
903 boolean
check_object_char(c)904 check_object_char(c)
905 char c;
906 {
907 	return (def_char_to_objclass(c) != MAXOCLASSES);
908 }
909 
910 /*
911  * Convert .des map letter into floor type.
912  */
913 char
what_map_char(c)914 what_map_char(c)
915 char c;
916 {
917 	SpinCursor(3);
918 	switch(c) {
919 		  case ' '  : return(STONE);
920 		  case '#'  : return(CORR);
921 		  case '.'  : return(ROOM);
922 		  case '-'  : return(HWALL);
923 		  case '|'  : return(VWALL);
924 		  case '+'  : return(DOOR);
925 		  case 'A'  : return(AIR);
926 		  case 'B'  : return(CROSSWALL); /* hack: boundary location */
927 		  case 'C'  : return(CLOUD);
928 		  case 'S'  : return(SDOOR);
929 		  case 'H'  : return(SCORR);
930 		  case '{'  : return(FOUNTAIN);
931 		  case '\\' : return(THRONE);
932 		  case 'K'  :
933 #ifdef SINKS
934 		      return(SINK);
935 #else
936 		      lc_warning("Sinks ('K') are not allowed in this version!  Ignoring...");
937 		      return(ROOM);
938 #endif
939 		  case '}'  : return(MOAT);
940 		  case 'P'  : return(POOL);
941 		  case 'L'  : return(LAVAPOOL);
942 		  case 'I'  : return(ICE);
943 		  case 'W'  : return(WATER);
944 		  case 'T'	: return (TREE);
945 		  case 'F'	: return (IRONBARS);	/* Fe = iron */
946 		  case 'x'  : return(MAX_TYPE); /* 'see-through' */
947 	    }
948 	return(INVALID_TYPE);
949 }
950 
951 void
add_opcode(sp,opc,dat)952 add_opcode(sp, opc, dat)
953 sp_lev *sp;
954 int opc;
955 genericptr_t dat;
956 {
957    long nop = sp->n_opcodes;
958    _opcode *tmp;
959 
960    if ((opc < 0) || (opc >= MAX_SP_OPCODES))
961        lc_error("Unknown opcode '%i'", opc);
962 
963    tmp = (_opcode *)alloc(sizeof(_opcode)*(nop+1));
964    if (sp->opcodes && nop) {
965        (void) memcpy(tmp, sp->opcodes, sizeof(_opcode)*nop);
966        free(sp->opcodes);
967    } else if (!tmp)
968        lc_error("Could not alloc opcode space");
969 
970    sp->opcodes = tmp;
971 
972    sp->opcodes[nop].opcode = opc;
973    sp->opcodes[nop].opdat = dat;
974 
975    sp->n_opcodes++;
976 }
977 
978 /*
979  * Yep! LEX gives us the map in a raw mode.
980  * Just analyze it here.
981  */
982 void
scan_map(map,sp)983 scan_map(map, sp)
984 char *map;
985 sp_lev *sp;
986 {
987 	register int i, len;
988 	register char *s1, *s2;
989 	long max_len = 0;
990 	long max_hig = 0;
991 	char msg[256];
992 	char *tmpmap[ROWNO];
993 	int dx,dy;
994 	char *mbuf;
995 
996 	/* First, strip out digits 0-9 (line numbering) */
997 	for (s1 = s2 = map; *s1; s1++)
998 	    if (*s1 < '0' || *s1 > '9')
999 		*s2++ = *s1;
1000 	*s2 = '\0';
1001 
1002 	/* Second, find the max width of the map */
1003 	s1 = map;
1004 	while (s1 && *s1) {
1005 		s2 = index(s1, '\n');
1006 		if (s2) {
1007 			len = (int) (s2 - s1);
1008 			s1 = s2 + 1;
1009 		} else {
1010 			len = (int) strlen(s1);
1011 			s1 = (char *) 0;
1012 		}
1013 		if (len > max_len) max_len = len;
1014 	}
1015 
1016 	/* Then parse it now */
1017 	while (map && *map) {
1018 		tmpmap[max_hig] = (char *) alloc(max_len);
1019 		s1 = index(map, '\n');
1020 		if (s1) {
1021 			len = (int) (s1 - map);
1022 			s1++;
1023 		} else {
1024 			len = (int) strlen(map);
1025 			s1 = map + len;
1026 		}
1027 		for(i=0; i<len; i++)
1028 		  if((tmpmap[max_hig][i] = what_map_char(map[i])) == INVALID_TYPE) {
1029 		      lc_warning("Invalid character '%c' @ (%d, %d) - replacing with stone", map[i], max_hig, i);
1030 		      tmpmap[max_hig][i] = STONE;
1031 		    }
1032 		while(i < max_len)
1033 		    tmpmap[max_hig][i++] = STONE;
1034 		map = s1;
1035 		max_hig++;
1036 	}
1037 
1038 	/* Memorize boundaries */
1039 
1040 	max_x_map = max_len - 1;
1041 	max_y_map = max_hig - 1;
1042 
1043 
1044 	if(max_len > MAP_X_LIM || max_hig > MAP_Y_LIM) {
1045 	    lc_error("Map too large at (%d x %d), max is (%d x %d)", max_len, max_hig, MAP_X_LIM, MAP_Y_LIM);
1046 	}
1047 
1048 	mbuf = (char *) alloc(((max_hig-1) * max_len) + (max_len-1) + 2);
1049 	for (dy = 0; dy < max_hig; dy++)
1050 	    for (dx = 0; dx < max_len; dx++)
1051 		mbuf[(dy * max_len) + dx] = (tmpmap[dy][dx] + 1);
1052 
1053 	mbuf[((max_hig-1) * max_len) + (max_len-1) + 1] = '\0';
1054 
1055 	add_opvars(sp, "siio", mbuf, max_hig, max_len, SPO_MAP);
1056 
1057 	for (dy = 0; dy < max_hig; dy++)
1058 	    Free(tmpmap[dy]);
1059 	Free(mbuf);
1060 }
1061 
1062 
1063 /*
1064  * Output some info common to all special levels.
1065  */
1066 static boolean
write_common_data(fd,lvl)1067 write_common_data(fd, lvl)
1068 int fd;
1069 sp_lev *lvl;
1070 {
1071 	static struct version_info version_data = {
1072 			VERSION_NUMBER, VERSION_FEATURES,
1073 			VERSION_SANITY1, VERSION_SANITY2
1074 	};
1075 
1076 	Write(fd, &version_data, sizeof version_data);
1077 	/*Write(fd, &lvl->init_lev, sizeof(lev_init));*/
1078 	return TRUE;
1079 }
1080 
1081 
1082 /*
1083  * Here we write the sp_lev structure in the specified file (fd).
1084  * Also, we have to free the memory allocated via alloc().
1085  */
1086 static boolean
write_maze(fd,maze)1087 write_maze(fd, maze)
1088 int fd;
1089 sp_lev *maze;
1090 {
1091         int i;
1092         uchar len;
1093 
1094         if (!write_common_data(fd, maze))
1095             return FALSE;
1096 
1097 	Write(fd, &(maze->n_opcodes), sizeof(maze->n_opcodes));
1098 
1099         for (i = 0; i < maze->n_opcodes; i++) {
1100 	   _opcode tmpo = maze->opcodes[i];
1101 
1102 	   Write(fd, &(tmpo.opcode), sizeof(tmpo.opcode));
1103 
1104 	   if (tmpo.opcode < SPO_NULL || tmpo.opcode >= MAX_SP_OPCODES)
1105 	       panic("write_maze: unknown opcode (%i).", tmpo.opcode);
1106 
1107 	   if (tmpo.opcode == SPO_PUSH) {
1108 	       genericptr_t opdat = tmpo.opdat;
1109 	       if (opdat) {
1110 		   struct opvar *ov = (struct opvar *)opdat;
1111 		   int size;
1112 		   Write(fd, &(ov->spovartyp), sizeof(ov->spovartyp));
1113 		   switch (ov->spovartyp) {
1114 		   case SPOVAR_NULL: break;
1115 		   case SPOVAR_COORD:
1116 		   case SPOVAR_REGION:
1117 		   case SPOVAR_MAPCHAR:
1118 		   case SPOVAR_MONST:
1119 		   case SPOVAR_OBJ:
1120 		   case SPOVAR_INT:
1121 		       Write(fd, &(ov->vardata.l), sizeof(ov->vardata.l));
1122 		       break;
1123 		   case SPOVAR_VARIABLE:
1124 		   case SPOVAR_STRING:
1125 		       if (ov->vardata.str)
1126 			   size = strlen(ov->vardata.str);
1127 		       else size = 0;
1128 		       Write(fd, &size, sizeof(size));
1129 		       if (size) {
1130 			   Write(fd, ov->vardata.str, size);
1131 			   Free(ov->vardata.str);
1132 		       }
1133 		       break;
1134 		   default: panic("write_maze: unknown data type (%i).", ov->spovartyp);
1135 		   }
1136 	       } else panic("write_maze: PUSH with no data.");
1137 	   } else {
1138 	       /* sanity check */
1139 	       genericptr_t opdat = tmpo.opdat;
1140 	       if (opdat)
1141 		   panic("write_maze: opcode (%i) has data.", tmpo.opcode);
1142 	   }
1143 
1144 	   Free(tmpo.opdat);
1145 
1146 	}
1147         /* clear the struct for next user */
1148 	Free(maze->opcodes);
1149 	maze->opcodes = NULL;
1150         /*(void) memset((genericptr_t) &maze->init_lev, 0, sizeof maze->init_lev);*/
1151 
1152 	return TRUE;
1153 }
1154 
1155 
1156 static boolean
decompile_maze(fd,maze)1157 decompile_maze(fd, maze)
1158 int fd;
1159 sp_lev *maze;
1160 {
1161         int i;
1162         uchar len;
1163 	char debuf[128];
1164 	const char *opcodestr[MAX_SP_OPCODES] = {
1165 	    "null",
1166 	    "message",
1167 	    "monster",
1168 	    "object",
1169 	    "engraving",
1170 	    "room",
1171 	    "subroom",
1172 	    "door",
1173 	    "stair",
1174 	    "ladder",
1175 	    "altar",
1176 	    "fountain",
1177 	    "sink",
1178 	    "pool",
1179 	    "trap",
1180 	    "gold",
1181 	    "corridor",
1182 	    "levregion",
1183 	    "drawbridge",
1184 	    "mazewalk",
1185 	    "non_diggable",
1186 	    "non_passwall",
1187 	    "wallify",
1188 	    "map",
1189 	    "room_door",
1190 	    "region",
1191 	    "cmp",
1192 	    "jmp",
1193 	    "jl",
1194 	    "jle",
1195 	    "jg",
1196 	    "jge",
1197 	    "je",
1198 	    "jne",
1199 	    "spill",
1200 	    "terrain",
1201 	    "replaceterrain",
1202 	    "exit",
1203 	    "endroom",
1204 	    "pop_container",
1205 	    "push",
1206 	    "pop",
1207 	    "rn2",
1208 	    "dec",
1209 	    "inc",
1210 	    "add",
1211 	    "sub",
1212 	    "mul",
1213 	    "div",
1214 	    "mod",
1215 	    "copy",
1216 	    "mon_generation",
1217 	    "end_moninvent",
1218 	    "grave",
1219 	    "frame_push",
1220 	    "frame_pop",
1221 	    "call",
1222 	    "return",
1223 	    "init_map",
1224 	    "flags",
1225 	    "sounds",
1226 	    "wallwalk",
1227 	    "var_init",
1228 	    "shuffle_array",
1229 	    "dice",
1230 	    "selection_add",
1231 	    "selection_point",
1232 	    "selection_rect",
1233 	    "selection_fillrect",
1234 	    "selection_line",
1235 	    "selection_rndline",
1236 	    "selection_grow",
1237 	    "selection_flood",
1238 	    "selection_rndcoord",
1239 	    "selection_ellipse",
1240 	    "selection_filter",
1241 	};
1242 
1243 	/* don't bother with the header stuff */
1244 
1245         for (i=0;i<maze->n_opcodes;i++) {
1246 	   _opcode tmpo = maze->opcodes[i];
1247 
1248 	   if (tmpo.opcode < SPO_NULL || tmpo.opcode >= MAX_SP_OPCODES)
1249 	       panic("decompile_maze: unknown opcode (%i).", tmpo.opcode);
1250 
1251 	   if (tmpo.opcode == SPO_PUSH) {
1252 	       genericptr_t opdat = tmpo.opdat;
1253 	       if (opdat) {
1254 		   struct opvar *ov = (struct opvar *)opdat;
1255 		   int size;
1256 		   switch (ov->spovartyp) {
1257 		   case SPOVAR_NULL: break;
1258 		   case SPOVAR_COORD:
1259 		       snprintf(debuf, 127, "%li:\t%s\tcoord:(%i,%i)\n", i, opcodestr[tmpo.opcode],
1260 				(ov->vardata.l & 0xff), ((ov->vardata.l >> 16) & 0xff));
1261 			   Write(fd, debuf, strlen(debuf));
1262 			   break;
1263 		   case SPOVAR_REGION:
1264 		       snprintf(debuf, 127, "%li:\t%s\tregion:(%i,%i,%i,%i)\n", i, opcodestr[tmpo.opcode],
1265 				(ov->vardata.l & 0xff), ((ov->vardata.l >> 8) & 0xff),
1266 				((ov->vardata.l >> 16) & 0xff), ((ov->vardata.l >> 24) & 0xff));
1267 			   Write(fd, debuf, strlen(debuf));
1268 			   break;
1269 		   case SPOVAR_OBJ:
1270 		       snprintf(debuf, 127, "%li:\t%s\tobj:(id=%i,class=\'%c\')\n",
1271 				i, opcodestr[tmpo.opcode],
1272 				SP_OBJ_TYP(ov->vardata.l), SP_OBJ_CLASS(ov->vardata.l));
1273 		       Write(fd, debuf, strlen(debuf));
1274 		       break;
1275 		   case SPOVAR_MONST:
1276 		       snprintf(debuf, 127, "%li:\t%s\tmonster:(pm=%i, class='%c')\n", i, opcodestr[tmpo.opcode],
1277 				SP_MONST_PM(ov->vardata.l), SP_MONST_CLASS(ov->vardata.l));
1278 		       Write(fd, debuf, strlen(debuf));
1279 		       break;
1280 		   case SPOVAR_MAPCHAR:
1281 		       snprintf(debuf, 127, "%li:\t%s\tmapchar:(%li,%i)\n", i, opcodestr[tmpo.opcode],
1282 				(int)SP_MAPCHAR_TYP(ov->vardata.l), (schar)SP_MAPCHAR_LIT(ov->vardata.l));
1283 		       Write(fd, debuf, strlen(debuf));
1284 		       break;
1285 		   case SPOVAR_INT:
1286 		       if (ov->vardata.l >= ' ' && ov->vardata.l <= '~')
1287 			   snprintf(debuf, 127, "%li:\t%s\tint:%li\t# '%c'\n", i, opcodestr[tmpo.opcode], ov->vardata.l, (char)ov->vardata.l);
1288 		       else
1289 			   snprintf(debuf, 127, "%li:\t%s\tint:%li\n", i, opcodestr[tmpo.opcode], ov->vardata.l);
1290 		       Write(fd, debuf, strlen(debuf));
1291 		       break;
1292 		   case SPOVAR_VARIABLE:
1293 		   case SPOVAR_STRING:
1294 		       if (ov->vardata.str)
1295 			   size = strlen(ov->vardata.str);
1296 		       else size = 0;
1297 		       if (size) {
1298 			   int x;
1299 			   int ok = (size > 127) ? 0 : 1;
1300 			   if (ok)
1301 			       for (x = 0; x < size; x++)
1302 				   if (ov->vardata.str[x] < ' ' || ov->vardata.str[x] > '~') {
1303 				       ok = 0;
1304 				       break;
1305 				   }
1306 			   if (ok) {
1307 			       if (ov->spovartyp == SPOVAR_VARIABLE)
1308 				   snprintf(debuf, 127, "%li:\t%s\tvar:$%s\n", i, opcodestr[tmpo.opcode], ov->vardata.str);
1309 			       else
1310 				   snprintf(debuf, 127, "%li:\t%s\tstr:\"%s\"\n", i, opcodestr[tmpo.opcode], ov->vardata.str);
1311 			       Write(fd, debuf, strlen(debuf));
1312 			   } else {
1313 			       snprintf(debuf, 127, "%li:\t%s\tstr:", i, opcodestr[tmpo.opcode]);
1314 			       Write(fd, debuf, strlen(debuf));
1315 			       for (x = 0; x < size; x++) {
1316 				   snprintf(debuf, 127, "%02x ", ov->vardata.str[x]);
1317 				   Write(fd, debuf, strlen(debuf));
1318 			       }
1319 			       snprintf(debuf, 127, "\n");
1320 			       Write(fd, debuf, strlen(debuf));
1321 			   }
1322 		       }
1323 		       break;
1324 		   default: panic("decompile_maze: unknown data type (%i).", ov->spovartyp);
1325 		   }
1326 	       } else panic("decompile_maze: PUSH with no data.");
1327 	   } else {
1328 	       /* sanity check */
1329 	       genericptr_t opdat = tmpo.opdat;
1330 	       if (opdat)
1331 		   panic("decompile_maze: opcode (%i) has data.", tmpo.opcode);
1332 	       snprintf(debuf, 127, "%li:\t%s\n", i, opcodestr[tmpo.opcode]);
1333 	       Write(fd, debuf, strlen(debuf));
1334 	   }
1335 
1336 	}
1337 	return TRUE;
1338 }
1339 
1340 /*
1341  * Open and write special level file.
1342  * Return TRUE on success, FALSE on failure.
1343  */
1344 boolean
write_level_file(filename,lvl)1345 write_level_file(filename, lvl)
1346 char *filename;
1347 sp_lev *lvl;
1348 {
1349 	int fout;
1350 	char lbuf[60];
1351 
1352 	if (decompile) {
1353 	    lbuf[0] = '\0';
1354 #ifdef PREFIX
1355 	    Strcat(lbuf, PREFIX);
1356 #endif
1357 	    Strcat(lbuf, filename);
1358 	    Strcat(lbuf, "_lev.txt");
1359 	    fout = open(lbuf, O_TRUNC|O_WRONLY|O_CREAT, OMASK);
1360 	    if (fout < 0) return FALSE;
1361 	    decompile_maze(fout, lvl);
1362 	    (void) close(fout);
1363 	}
1364 
1365 	lbuf[0] = '\0';
1366 #ifdef PREFIX
1367 	Strcat(lbuf, PREFIX);
1368 #endif
1369 	Strcat(lbuf, filename);
1370 	Strcat(lbuf, LEV_EXT);
1371 
1372 	fout = open(lbuf, O_WRONLY|O_CREAT|O_BINARY, OMASK);
1373 	if (fout < 0) return FALSE;
1374 
1375         if (!lvl) panic("write_level_file");
1376 
1377 	if (be_verbose)
1378 	    fprintf(stdout, "File: '%s', opcodes: %li\n", lbuf, lvl->n_opcodes);
1379 
1380         if (!write_maze(fout, lvl))
1381           return FALSE;
1382 
1383 	(void) close(fout);
1384 
1385 	return TRUE;
1386 }
1387 
1388 #ifdef STRICT_REF_DEF
1389 /*
1390  * Any globals declared in hack.h and descendents which aren't defined
1391  * in the modules linked into lev_comp should be defined here.  These
1392  * definitions can be dummies:  their sizes shouldn't matter as long as
1393  * as their types are correct; actual values are irrelevant.
1394  */
1395 #define ARBITRARY_SIZE 1
1396 /* attrib.c */
1397 struct attribs attrmax, attrmin;
1398 /* files.c */
1399 const char *configfile;
1400 char lock[ARBITRARY_SIZE];
1401 char SAVEF[ARBITRARY_SIZE];
1402 # ifdef MICRO
1403 char SAVEP[ARBITRARY_SIZE];
1404 # endif
1405 /* termcap.c */
1406 struct tc_lcl_data tc_lcl_data;
1407 # ifdef TEXTCOLOR
1408 #  ifdef TOS
1409 const char *hilites[CLR_MAX];
1410 #  else
1411 char NEARDATA *hilites[CLR_MAX];
1412 #  endif
1413 # endif
1414 /* trap.c */
1415 const char *traps[TRAPNUM];
1416 /* window.c */
1417 struct window_procs windowprocs;
1418 /* xxxtty.c */
1419 # ifdef DEFINE_OSPEED
1420 short ospeed;
1421 # endif
1422 #endif	/* STRICT_REF_DEF */
1423 
1424 /*lev_main.c*/
1425