NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / util / lev_main.c
blobac6b19c6f055accd446461875ae0f32b88ce2dbc
1 /* aNetHack 0.0.1 lev_main.c $ANH-Date: 1448074107 2015/11/21 02:48:27 $ $ANH-Branch: master $:$ANH-Revision: 1.43 $ */
2 /* Copyright (c) 1989 by Jean-Christophe Collet */
3 /* aNetHack may be freely redistributed. See license for details. */
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 USE_OLDARGS (sp_lev.h) and for MPW (macconf.h) */
11 #define NEED_VARARGS
12 #include "hack.h"
13 #include "date.h"
14 #include "sp_lev.h"
15 #ifdef STRICT_REF_DEF
16 #include "tcap.h"
17 #endif
18 #include <ctype.h>
20 #ifdef MAC
21 #if defined(__SC__) || defined(__MRC__)
22 #define MPWTOOL
23 #define PREFIX ":dungeon:" /* place output files here */
24 #include <CursorCtl.h>
25 #else
26 #if !defined(__MACH__)
27 #define PREFIX ":lib:" /* place output files here */
28 #endif
29 #endif
30 #endif
32 #ifdef WIN_CE
33 #define PREFIX "\\anethack\\dat\\"
34 #endif
36 #ifndef MPWTOOL
37 #define SpinCursor(x)
38 #endif
40 #if defined(AMIGA) && defined(DLB)
41 #define PREFIX "NH:slib/"
42 #endif
44 #ifndef O_WRONLY
45 #include <fcntl.h>
46 #endif
47 #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
55 #if defined(MICRO) || defined(WIN32)
56 #define OMASK FCMASK
57 #else
58 #define OMASK 0644
59 #endif
61 #define ERR (-1)
63 #define NewTab(type, size) (type **) alloc(sizeof(type *) * size)
64 #define Free(ptr) \
65 if (ptr) \
66 free((genericptr_t)(ptr))
67 /* write() returns a signed value but its size argument is unsigned;
68 types might be int and unsigned or ssize_t and size_t; casting
69 to long should be safe for all permutations (even if size_t is
70 bigger, since the values involved won't be too big for long) */
71 #define Write(fd, item, size) \
72 if ((long) write(fd, (genericptr_t)(item), size) != (long) (size)) \
73 return FALSE;
75 #if defined(__BORLANDC__) && !defined(_WIN32)
76 extern unsigned _stklen = STKSIZ;
77 #endif
78 #define MAX_ERRORS 25
80 extern int NDECL(yyparse);
81 extern void FDECL(init_yyin, (FILE *));
82 extern void FDECL(init_yyout, (FILE *));
84 int FDECL(main, (int, char **));
85 void FDECL(yyerror, (const char *));
86 void FDECL(yywarning, (const char *));
87 int NDECL(yywrap);
88 int FDECL(get_floor_type, (CHAR_P));
89 int FDECL(get_room_type, (char *));
90 int FDECL(get_trap_type, (char *));
91 int FDECL(get_monster_id, (char *, CHAR_P));
92 int FDECL(get_object_id, (char *, CHAR_P));
93 boolean FDECL(check_monster_char, (CHAR_P));
94 boolean FDECL(check_object_char, (CHAR_P));
95 char FDECL(what_map_char, (CHAR_P));
96 void FDECL(scan_map, (char *, sp_lev *));
97 boolean NDECL(check_subrooms);
98 boolean FDECL(write_level_file, (char *, sp_lev *));
100 struct lc_funcdefs *FDECL(funcdef_new, (long, char *));
101 void FDECL(funcdef_free_all, (struct lc_funcdefs *));
102 struct lc_funcdefs *FDECL(funcdef_defined,
103 (struct lc_funcdefs *, char *, int));
105 struct lc_vardefs *FDECL(vardef_new, (long, char *));
106 void FDECL(vardef_free_all, (struct lc_vardefs *));
107 struct lc_vardefs *FDECL(vardef_defined, (struct lc_vardefs *, char *, int));
109 void FDECL(splev_add_from, (sp_lev *, sp_lev *));
111 extern void NDECL(monst_init);
112 extern void NDECL(objects_init);
113 extern void NDECL(decl_init);
115 void FDECL(add_opcode, (sp_lev *, int, genericptr_t));
117 static boolean FDECL(write_common_data, (int));
118 static boolean FDECL(write_maze, (int, sp_lev *));
119 static void NDECL(init_obj_classes);
120 static int FDECL(case_insensitive_comp, (const char *, const char *));
122 void VDECL(lc_pline, (const char *, ...));
123 void VDECL(lc_error, (const char *, ...));
124 void VDECL(lc_warning, (const char *, ...));
125 char *FDECL(decode_parm_chr, (CHAR_P));
126 char *FDECL(decode_parm_str, (char *));
127 struct opvar *FDECL(set_opvar_int, (struct opvar *, long));
128 struct opvar *FDECL(set_opvar_coord, (struct opvar *, long));
129 struct opvar *FDECL(set_opvar_region, (struct opvar *, long));
130 struct opvar *FDECL(set_opvar_mapchar, (struct opvar *, long));
131 struct opvar *FDECL(set_opvar_monst, (struct opvar *, long));
132 struct opvar *FDECL(set_opvar_obj, (struct opvar *, long));
133 struct opvar *FDECL(set_opvar_str, (struct opvar *, const char *));
134 struct opvar *FDECL(set_opvar_var, (struct opvar *, const char *));
135 void VDECL(add_opvars, (sp_lev *, const char *, ...));
136 void NDECL(break_stmt_start);
137 void FDECL(break_stmt_end, (sp_lev *));
138 void FDECL(break_stmt_new, (sp_lev *, long));
139 char *FDECL(funcdef_paramtypes, (struct lc_funcdefs *));
140 const char *FDECL(spovar2str, (long));
141 void FDECL(vardef_used, (struct lc_vardefs *, char *));
142 void FDECL(check_vardef_type, (struct lc_vardefs *, char *, long));
143 struct lc_vardefs *FDECL(add_vardef_type,
144 (struct lc_vardefs *, char *, long));
145 int FDECL(reverse_jmp_opcode, (int));
146 struct opvar *FDECL(opvar_clone, (struct opvar *));
147 void FDECL(start_level_def, (sp_lev **, char *));
149 static struct {
150 const char *name;
151 int type;
152 } trap_types[] = { { "arrow", ARROW_TRAP },
153 { "dart", DART_TRAP },
154 { "falling rock", ROCKTRAP },
155 { "board", SQKY_BOARD },
156 { "bear", BEAR_TRAP },
157 { "land mine", LANDMINE },
158 { "rolling boulder", ROLLING_BOULDER_TRAP },
159 { "sleep gas", SLP_GAS_TRAP },
160 { "rust", RUST_TRAP },
161 { "fire", FIRE_TRAP },
162 { "pit", PIT },
163 { "spiked pit", SPIKED_PIT },
164 { "hole", HOLE },
165 { "trap door", TRAPDOOR },
166 { "teleport", TELEP_TRAP },
167 { "level teleport", LEVEL_TELEP },
168 { "magic portal", MAGIC_PORTAL },
169 { "web", WEB },
170 { "statue", STATUE_TRAP },
171 { "magic", MAGIC_TRAP },
172 { "anti magic", ANTI_MAGIC },
173 { "polymorph", POLY_TRAP },
174 { "vibrating square", VIBRATING_SQUARE },
175 { 0, 0 } };
177 static struct {
178 const char *name;
179 int type;
180 } room_types[] = {
181 /* for historical reasons, room types are not contiguous numbers */
182 /* (type 1 is skipped) */
183 { "ordinary", OROOM },
184 { "throne", COURT },
185 { "swamp", SWAMP },
186 { "vault", VAULT },
187 { "beehive", BEEHIVE },
188 { "morgue", MORGUE },
189 { "barracks", BARRACKS },
190 { "zoo", ZOO },
191 { "delphi", DELPHI },
192 { "temple", TEMPLE },
193 { "anthole", ANTHOLE },
194 { "cocknest", COCKNEST },
195 { "leprehall", LEPREHALL },
196 { "shop", SHOPBASE },
197 { "armor shop", ARMORSHOP },
198 { "scroll shop", SCROLLSHOP },
199 { "potion shop", POTIONSHOP },
200 { "weapon shop", WEAPONSHOP },
201 { "food shop", FOODSHOP },
202 { "ring shop", RINGSHOP },
203 { "wand shop", WANDSHOP },
204 { "tool shop", TOOLSHOP },
205 { "book shop", BOOKSHOP },
206 { "health food shop", FODDERSHOP },
207 { "candle shop", CANDLESHOP },
208 { 0, 0 }
211 const char *fname = "(stdin)";
212 int fatal_error = 0;
213 int got_errors = 0;
214 int be_verbose = 0;
215 int fname_counter = 1;
217 #ifdef FLEX23_BUG
218 /* Flex 2.3 bug work around; not needed for 2.3.6 or later */
219 int yy_more_len = 0;
220 #endif
222 extern unsigned int max_x_map, max_y_map;
224 extern int nh_line_number;
226 extern int token_start_pos;
227 extern char curr_token[512];
229 struct lc_vardefs *variable_definitions = NULL;
230 struct lc_funcdefs *function_definitions = NULL;
232 extern int allow_break_statements;
233 extern struct lc_breakdef *break_list;
236 main(argc, argv)
237 int argc;
238 char **argv;
240 FILE *fin;
241 int i;
242 boolean errors_encountered = FALSE;
243 #if defined(MAC) && (defined(THINK_C) || defined(__MWERKS__))
244 static char *mac_argv[] = {
245 "lev_comp", /* dummy argv[0] */
246 ":dat:Arch.des", ":dat:Barb.des", ":dat:Caveman.des",
247 ":dat:Healer.des", ":dat:Knight.des", ":dat:Monk.des",
248 ":dat:Priest.des", ":dat:Ranger.des", ":dat:Rogue.des",
249 ":dat:Samurai.des", ":dat:Tourist.des", ":dat:Valkyrie.des",
250 ":dat:Wizard.des", ":dat:bigroom.des", ":dat:castle.des",
251 ":dat:endgame.des", ":dat:gehennom.des", ":dat:knox.des",
252 ":dat:medusa.des", ":dat:mines.des", ":dat:oracle.des",
253 ":dat:sokoban.des", ":dat:tower.des", ":dat:yendor.des"
256 argc = SIZE(mac_argv);
257 argv = mac_argv;
258 #endif
259 /* Note: these initializers don't do anything except guarantee that
260 * we're linked properly.
262 monst_init();
263 objects_init();
264 decl_init();
265 /* this one does something... */
266 init_obj_classes();
268 init_yyout(stdout);
269 if (argc == 1) { /* Read standard input */
270 init_yyin(stdin);
271 (void) yyparse();
272 if (fatal_error > 0) {
273 errors_encountered = TRUE;
275 } else { /* Otherwise every argument is a filename */
276 for (i = 1; i < argc; i++) {
277 fname = argv[i];
278 if (!strcmp(fname, "-v")) {
279 be_verbose++;
280 continue;
282 fin = freopen(fname, "r", stdin);
283 if (!fin) {
284 lc_pline("Can't open \"%s\" for input.\n", fname);
285 perror(fname);
286 errors_encountered = TRUE;
287 } else {
288 fname_counter = 1;
289 init_yyin(fin);
290 (void) yyparse();
291 nh_line_number = 1;
292 if (fatal_error > 0 || got_errors > 0) {
293 errors_encountered = TRUE;
294 fatal_error = 0;
299 exit(errors_encountered ? EXIT_FAILURE : EXIT_SUCCESS);
300 /*NOTREACHED*/
301 return 0;
305 * Each time the parser detects an error, it uses this function.
306 * Here we take count of the errors. To continue farther than
307 * MAX_ERRORS wouldn't be reasonable.
308 * Assume that explicit calls from lev_comp.y have the 1st letter
309 * capitalized, to allow printing of the line containing the start of
310 * the current declaration, instead of the beginning of the next declaration.
312 void
313 yyerror(s)
314 const char *s;
316 char *e = ((char *) s + strlen(s) - 1);
318 (void) fprintf(stderr, "%s: line %d, pos %d: %s", fname, nh_line_number,
319 token_start_pos - (int) strlen(curr_token), s);
320 if (*e != '.' && *e != '!')
321 (void) fprintf(stderr, " at \"%s\"", curr_token);
322 (void) fprintf(stderr, "\n");
324 if (++fatal_error > MAX_ERRORS) {
325 (void) fprintf(stderr, "Too many errors, good bye!\n");
326 exit(EXIT_FAILURE);
331 * Just display a warning (that is : a non fatal error)
333 void
334 yywarning(s)
335 const char *s;
337 (void) fprintf(stderr, "%s: line %d : WARNING : %s\n", fname,
338 nh_line_number, s);
342 * Stub needed for lex interface.
345 yywrap()
347 return 1;
351 * lc_pline(): lev_comp version of pline(), stripped down version of
352 * core's pline(), with convoluted handling for variadic arguments to
353 * support <stdarg.h>, <varargs.h>, and neither of the above.
355 * Using state for message/warning/error mode simplifies calling interface.
357 #define LC_PLINE_MESSAGE 0
358 #define LC_PLINE_WARNING 1
359 #define LC_PLINE_ERROR 2
360 static int lc_pline_mode = LC_PLINE_MESSAGE;
362 #if defined(USE_STDARG) || defined(USE_VARARGS)
363 static void FDECL(lc_vpline, (const char *, va_list));
365 void lc_pline
366 VA_DECL(const char *, line)
368 VA_START(line);
369 VA_INIT(line, char *);
370 lc_vpline(line, VA_ARGS);
371 VA_END();
374 #ifdef USE_STDARG
375 static void
376 lc_vpline(const char *line, va_list the_args)
377 #else
378 static void
379 lc_vpline(line, the_args)
380 const char *line;
381 va_list the_args;
382 #endif
384 #else /* USE_STDARG | USE_VARARG */
386 #define lc_vpline lc_pline
388 void
389 lc_pline
390 VA_DECL(const char *, line)
391 #endif /* USE_STDARG | USE_VARARG */
392 { /* opening brace for lc_vpline, nested block for USE_OLDARGS lc_pline */
394 char pbuf[3 * BUFSZ];
395 static char nomsg[] = "(no message)";
396 /* Do NOT use VA_START and VA_END in here... see above */
398 if (!line || !*line)
399 line = nomsg; /* shouldn't happen */
400 if (index(line, '%')) {
401 Vsprintf(pbuf, line, VA_ARGS);
402 pbuf[BUFSZ - 1] = '\0'; /* truncate if long */
403 line = pbuf;
405 switch (lc_pline_mode) {
406 case LC_PLINE_ERROR:
407 yyerror(line);
408 break;
409 case LC_PLINE_WARNING:
410 yywarning(line);
411 break;
412 default:
413 (void) fprintf(stderr, "%s\n", line);
414 break;
416 lc_pline_mode = LC_PLINE_MESSAGE; /* reset to default */
417 return;
418 #if !(defined(USE_STDARG) || defined(USE_VARARGS))
419 VA_END(); /* closing brace ofr USE_OLDARGS's nested block */
420 #endif
423 /*VARARGS1*/
424 void
425 lc_error
426 VA_DECL(const char *, line)
428 VA_START(line);
429 VA_INIT(line, const char *);
430 lc_pline_mode = LC_PLINE_ERROR;
431 lc_vpline(line, VA_ARGS);
432 VA_END();
433 return;
436 /*VARARGS1*/
437 void
438 lc_warning
439 VA_DECL(const char *, line)
441 VA_START(line);
442 VA_INIT(line, const char *);
443 lc_pline_mode = LC_PLINE_WARNING;
444 lc_vpline(line, VA_ARGS);
445 VA_END();
446 return;
449 char *
450 decode_parm_chr(chr)
451 char chr;
453 static char buf[32];
455 switch (chr) {
456 default:
457 Strcpy(buf, "unknown");
458 break;
459 case 'i':
460 Strcpy(buf, "int");
461 break;
462 case 'r':
463 Strcpy(buf, "region");
464 break;
465 case 's':
466 Strcpy(buf, "str");
467 break;
468 case 'O':
469 Strcpy(buf, "obj");
470 break;
471 case 'c':
472 Strcpy(buf, "coord");
473 break;
474 case ' ':
475 Strcpy(buf, "nothing");
476 break;
477 case 'm':
478 Strcpy(buf, "mapchar");
479 break;
480 case 'M':
481 Strcpy(buf, "monster");
482 break;
484 return buf;
487 char *
488 decode_parm_str(str)
489 char *str;
491 static char tmpbuf[1024];
492 char *p = str;
493 tmpbuf[0] = '\0';
494 if (str) {
495 for (; *p; p++) {
496 Strcat(tmpbuf, decode_parm_chr(*p));
497 if (*(p + 1))
498 Strcat(tmpbuf, ", ");
501 return tmpbuf;
504 struct opvar *
505 set_opvar_int(ov, val)
506 struct opvar *ov;
507 long val;
509 if (ov) {
510 ov->spovartyp = SPOVAR_INT;
511 ov->vardata.l = val;
513 return ov;
516 struct opvar *
517 set_opvar_coord(ov, val)
518 struct opvar *ov;
519 long val;
521 if (ov) {
522 ov->spovartyp = SPOVAR_COORD;
523 ov->vardata.l = val;
525 return ov;
528 struct opvar *
529 set_opvar_region(ov, val)
530 struct opvar *ov;
531 long val;
533 if (ov) {
534 ov->spovartyp = SPOVAR_REGION;
535 ov->vardata.l = val;
537 return ov;
540 struct opvar *
541 set_opvar_mapchar(ov, val)
542 struct opvar *ov;
543 long val;
545 if (ov) {
546 ov->spovartyp = SPOVAR_MAPCHAR;
547 ov->vardata.l = val;
549 return ov;
552 struct opvar *
553 set_opvar_monst(ov, val)
554 struct opvar *ov;
555 long val;
557 if (ov) {
558 ov->spovartyp = SPOVAR_MONST;
559 ov->vardata.l = val;
561 return ov;
564 struct opvar *
565 set_opvar_obj(ov, val)
566 struct opvar *ov;
567 long val;
569 if (ov) {
570 ov->spovartyp = SPOVAR_OBJ;
571 ov->vardata.l = val;
573 return ov;
576 struct opvar *
577 set_opvar_str(ov, val)
578 struct opvar *ov;
579 const char *val;
581 if (ov) {
582 ov->spovartyp = SPOVAR_STRING;
583 ov->vardata.str = (val) ? strdup(val) : NULL;
585 return ov;
588 struct opvar *
589 set_opvar_var(ov, val)
590 struct opvar *ov;
591 const char *val;
593 if (ov) {
594 ov->spovartyp = SPOVAR_VARIABLE;
595 ov->vardata.str = (val) ? strdup(val) : NULL;
597 return ov;
600 #define New(type) \
601 (type *) memset((genericptr_t) alloc(sizeof(type)), 0, sizeof(type))
603 #if defined(USE_STDARG) || defined(USE_VARARGS)
604 static void FDECL(vadd_opvars, (sp_lev *, const char *, va_list));
606 void add_opvars
607 VA_DECL2(sp_lev *, sp, const char *, fmt)
609 VA_START(fmt);
610 VA_INIT(fmt, char *);
611 vadd_opvars(sp, fmt, VA_ARGS);
612 VA_END();
615 #ifdef USE_STDARG
616 static void
617 vadd_opvars(sp_lev *sp, const char *fmt, va_list the_args)
619 #else
620 static void
621 vadd_opvars(sp, fmt, the_args)
622 sp_lev *sp;
623 const char *fmt;
624 va_list the_args;
626 #endif
628 #else /* USE_STDARG | USE_VARARG */
630 #define vadd_opvars add_opvars
632 void add_opvars
633 VA_DECL2(sp_lev *, sp, const char *, fmt)
634 #endif /* USE_STDARG | USE_VARARG */
636 const char *p, *lp;
637 long la;
638 /* Do NOT use VA_START and VA_END in here... see above */
640 for (p = fmt; *p != '\0'; p++) {
641 switch (*p) {
642 case ' ':
643 break;
644 case 'i': /* integer */
646 struct opvar *ov = New(struct opvar);
647 set_opvar_int(ov, VA_NEXT(la, long) );
648 add_opcode(sp, SPO_PUSH, ov);
649 break;
651 case 'c': /* coordinate */
653 struct opvar *ov = New(struct opvar);
654 set_opvar_coord(ov, VA_NEXT(la, long) );
655 add_opcode(sp, SPO_PUSH, ov);
656 break;
658 case 'r': /* region */
660 struct opvar *ov = New(struct opvar);
661 set_opvar_region(ov, VA_NEXT(la, long) );
662 add_opcode(sp, SPO_PUSH, ov);
663 break;
665 case 'm': /* mapchar */
667 struct opvar *ov = New(struct opvar);
668 set_opvar_mapchar(ov, VA_NEXT(la, long) );
669 add_opcode(sp, SPO_PUSH, ov);
670 break;
672 case 'M': /* monster */
674 struct opvar *ov = New(struct opvar);
675 set_opvar_monst(ov, VA_NEXT(la, long) );
676 add_opcode(sp, SPO_PUSH, ov);
677 break;
679 case 'O': /* object */
681 struct opvar *ov = New(struct opvar);
682 set_opvar_obj(ov, VA_NEXT(la, long) );
683 add_opcode(sp, SPO_PUSH, ov);
684 break;
686 case 's': /* string */
688 struct opvar *ov = New(struct opvar);
689 set_opvar_str(ov, VA_NEXT(lp, const char *) );
690 add_opcode(sp, SPO_PUSH, ov);
691 break;
693 case 'v': /* variable */
695 struct opvar *ov = New(struct opvar);
696 set_opvar_var(ov, VA_NEXT(lp, const char *) );
697 add_opcode(sp, SPO_PUSH, ov);
698 break;
700 case 'o': /* opcode */
702 long i = VA_NEXT(la, int);
703 if (i < 0 || i >= MAX_SP_OPCODES)
704 lc_pline("add_opvars: unknown opcode '%ld'.", i);
705 add_opcode(sp, i, NULL);
706 break;
708 default:
709 lc_pline("add_opvars: illegal format character '%c'.", *p);
710 break;
713 return;
716 void
717 break_stmt_start()
719 allow_break_statements++;
722 void
723 break_stmt_end(splev)
724 sp_lev *splev;
726 struct lc_breakdef *tmp = break_list;
727 struct lc_breakdef *prv = NULL;
729 while (tmp) {
730 if (tmp->break_depth == allow_break_statements) {
731 struct lc_breakdef *nxt = tmp->next;
732 set_opvar_int(tmp->breakpoint,
733 splev->n_opcodes - tmp->breakpoint->vardata.l - 1);
734 tmp->next = NULL;
735 Free(tmp);
736 if (!prv)
737 break_list = NULL;
738 else
739 prv->next = nxt;
740 tmp = nxt;
741 } else {
742 prv = tmp;
743 tmp = tmp->next;
746 allow_break_statements--;
749 void
750 break_stmt_new(splev, i)
751 sp_lev *splev;
752 long i;
754 struct lc_breakdef *tmp = New(struct lc_breakdef);
756 tmp->breakpoint = New(struct opvar);
757 tmp->break_depth = allow_break_statements;
758 tmp->next = break_list;
759 break_list = tmp;
760 set_opvar_int(tmp->breakpoint, i);
761 add_opcode(splev, SPO_PUSH, tmp->breakpoint);
762 add_opcode(splev, SPO_JMP, NULL);
765 struct lc_funcdefs *
766 funcdef_new(addr, name)
767 long addr;
768 char *name;
770 struct lc_funcdefs *f = New(struct lc_funcdefs);
772 if (!f) {
773 lc_error("Could not alloc function definition for '%s'.", name);
774 return NULL;
776 f->next = NULL;
777 f->addr = addr;
778 f->name = strdup(name);
779 f->n_called = 0;
780 f->n_params = 0;
781 f->params = NULL;
782 f->code.opcodes = NULL;
783 f->code.n_opcodes = 0;
784 return f;
787 void
788 funcdef_free_all(fchain)
789 struct lc_funcdefs *fchain;
791 struct lc_funcdefs *tmp = fchain;
792 struct lc_funcdefs *nxt;
793 struct lc_funcdefs_parm *tmpparam;
795 while (tmp) {
796 nxt = tmp->next;
797 Free(tmp->name);
798 while (tmp->params) {
799 tmpparam = tmp->params->next;
800 Free(tmp->params->name);
801 tmp->params = tmpparam;
803 /* FIXME: free tmp->code */
804 Free(tmp);
805 tmp = nxt;
809 char *
810 funcdef_paramtypes(f)
811 struct lc_funcdefs *f;
813 int i = 0;
814 struct lc_funcdefs_parm *fp = f->params;
815 char *tmp = (char *) alloc((f->n_params) + 1);
817 if (!tmp)
818 return NULL;
819 while (fp) {
820 tmp[i++] = fp->parmtype;
821 fp = fp->next;
823 tmp[i] = '\0';
824 return tmp;
827 struct lc_funcdefs *
828 funcdef_defined(f, name, casesense)
829 struct lc_funcdefs *f;
830 char *name;
831 int casesense;
833 while (f) {
834 if (casesense) {
835 if (!strcmp(name, f->name))
836 return f;
837 } else {
838 if (!case_insensitive_comp(name, f->name))
839 return f;
841 f = f->next;
843 return NULL;
846 struct lc_vardefs *
847 vardef_new(typ, name)
848 long typ;
849 char *name;
851 struct lc_vardefs *f = New(struct lc_vardefs);
853 if (!f) {
854 lc_error("Could not alloc variable definition for '%s'.", name);
855 return NULL;
857 f->next = NULL;
858 f->var_type = typ;
859 f->name = strdup(name);
860 f->n_used = 0;
861 return f;
864 void
865 vardef_free_all(fchain)
866 struct lc_vardefs *fchain;
868 struct lc_vardefs *tmp = fchain;
869 struct lc_vardefs *nxt;
871 while (tmp) {
872 if (be_verbose && (tmp->n_used == 0))
873 lc_warning("Unused variable '%s'", tmp->name);
874 nxt = tmp->next;
875 Free(tmp->name);
876 Free(tmp);
877 tmp = nxt;
881 struct lc_vardefs *
882 vardef_defined(f, name, casesense)
883 struct lc_vardefs *f;
884 char *name;
885 int casesense;
887 while (f) {
888 if (casesense) {
889 if (!strcmp(name, f->name))
890 return f;
891 } else {
892 if (!case_insensitive_comp(name, f->name))
893 return f;
895 f = f->next;
897 return NULL;
900 const char *
901 spovar2str(spovar)
902 long spovar;
904 static int togl = 0;
905 static char buf[2][128];
906 const char *n = NULL;
907 int is_array = (spovar & SPOVAR_ARRAY);
909 spovar &= ~SPOVAR_ARRAY;
910 switch (spovar) {
911 default:
912 lc_error("spovar2str(%ld)", spovar);
913 break;
914 case SPOVAR_INT:
915 n = "integer";
916 break;
917 case SPOVAR_STRING:
918 n = "string";
919 break;
920 case SPOVAR_VARIABLE:
921 n = "variable";
922 break;
923 case SPOVAR_COORD:
924 n = "coordinate";
925 break;
926 case SPOVAR_REGION:
927 n = "region";
928 break;
929 case SPOVAR_MAPCHAR:
930 n = "mapchar";
931 break;
932 case SPOVAR_MONST:
933 n = "monster";
934 break;
935 case SPOVAR_OBJ:
936 n = "object";
937 break;
940 togl = ((togl + 1) % 2);
942 Sprintf(buf[togl], "%s%s", n, (is_array ? " array" : ""));
943 return buf[togl];
946 void
947 vardef_used(vd, varname)
948 struct lc_vardefs *vd;
949 char *varname;
951 struct lc_vardefs *tmp;
953 if ((tmp = vardef_defined(vd, varname, 1)) != 0)
954 tmp->n_used++;
957 void
958 check_vardef_type(vd, varname, vartype)
959 struct lc_vardefs *vd;
960 char *varname;
961 long vartype;
963 struct lc_vardefs *tmp;
965 if ((tmp = vardef_defined(vd, varname, 1)) != 0) {
966 if (tmp->var_type != vartype)
967 lc_error("Trying to use variable '%s' as %s, when it is %s.",
968 varname, spovar2str(vartype), spovar2str(tmp->var_type));
969 } else
970 lc_error("Variable '%s' not defined.", varname);
973 struct lc_vardefs *
974 add_vardef_type(vd, varname, vartype)
975 struct lc_vardefs *vd;
976 char *varname;
977 long vartype;
979 struct lc_vardefs *tmp;
981 if ((tmp = vardef_defined(vd, varname, 1)) != 0) {
982 if (tmp->var_type != vartype)
983 lc_error("Trying to redefine variable '%s' as %s, when it is %s.",
984 varname, spovar2str(vartype), spovar2str(tmp->var_type));
985 } else {
986 tmp = vardef_new(vartype, varname);
987 tmp->next = vd;
988 return tmp;
990 return vd;
994 reverse_jmp_opcode(opcode)
995 int opcode;
997 switch (opcode) {
998 case SPO_JE:
999 return SPO_JNE;
1000 case SPO_JNE:
1001 return SPO_JE;
1002 case SPO_JL:
1003 return SPO_JGE;
1004 case SPO_JG:
1005 return SPO_JLE;
1006 case SPO_JLE:
1007 return SPO_JG;
1008 case SPO_JGE:
1009 return SPO_JL;
1010 default:
1011 lc_error("Cannot reverse comparison jmp opcode %d.", opcode);
1012 return SPO_NULL;
1016 /* basically copied from src/sp_lev.c */
1017 struct opvar *
1018 opvar_clone(ov)
1019 struct opvar *ov;
1021 if (ov) {
1022 struct opvar *tmpov = (struct opvar *) alloc(sizeof(struct opvar));
1024 if (!tmpov) { /* lint suppression */
1025 /*NOTREACHED*/
1026 #if 0
1027 /* not possible; alloc() never returns Null */
1028 panic("could not alloc opvar struct");
1029 /*NOTREACHED*/
1030 #endif
1031 return (struct opvar *) 0;
1033 switch (ov->spovartyp) {
1034 case SPOVAR_COORD:
1035 case SPOVAR_REGION:
1036 case SPOVAR_MAPCHAR:
1037 case SPOVAR_MONST:
1038 case SPOVAR_OBJ:
1039 case SPOVAR_INT: {
1040 tmpov->spovartyp = ov->spovartyp;
1041 tmpov->vardata.l = ov->vardata.l;
1042 } break;
1043 case SPOVAR_VARIABLE:
1044 case SPOVAR_STRING: {
1045 int len = strlen(ov->vardata.str);
1046 tmpov->spovartyp = ov->spovartyp;
1047 tmpov->vardata.str = (char *) alloc(len + 1);
1048 (void) memcpy((genericptr_t) tmpov->vardata.str,
1049 (genericptr_t) ov->vardata.str, len);
1050 tmpov->vardata.str[len] = '\0';
1051 } break;
1052 default: {
1053 lc_error("Unknown opvar_clone value type (%d)!", ov->spovartyp);
1054 } /* default */
1055 } /* switch */
1056 return tmpov;
1058 return (struct opvar *) 0;
1061 void
1062 splev_add_from(splev, from_splev)
1063 sp_lev *splev;
1064 sp_lev *from_splev;
1066 int i;
1068 if (splev && from_splev)
1069 for (i = 0; i < from_splev->n_opcodes; i++)
1070 add_opcode(splev, from_splev->opcodes[i].opcode,
1071 opvar_clone(from_splev->opcodes[i].opdat));
1074 void
1075 start_level_def(splev, ldfname)
1076 sp_lev **splev;
1077 char *ldfname;
1079 struct lc_funcdefs *f;
1081 if (index(ldfname, '.'))
1082 lc_error("Invalid dot ('.') in level name '%s'.", ldfname);
1083 if ((int) strlen(ldfname) > 14)
1084 lc_error("Level names limited to 14 characters ('%s').", ldfname);
1085 f = function_definitions;
1086 while (f) {
1087 f->n_called = 0;
1088 f = f->next;
1090 *splev = (sp_lev *) alloc(sizeof(sp_lev));
1091 (*splev)->n_opcodes = 0;
1092 (*splev)->opcodes = NULL;
1094 vardef_free_all(variable_definitions);
1095 variable_definitions = NULL;
1099 * Find the type of floor, knowing its char representation.
1102 get_floor_type(c)
1103 char c;
1105 int val;
1107 SpinCursor(3);
1108 val = what_map_char(c);
1109 if (val == INVALID_TYPE) {
1110 val = ERR;
1111 yywarning("Invalid fill character in MAZE declaration");
1113 return val;
1117 * Find the type of a room in the table, knowing its name.
1120 get_room_type(s)
1121 char *s;
1123 register int i;
1125 SpinCursor(3);
1126 for (i = 0; room_types[i].name; i++)
1127 if (!strcmp(s, room_types[i].name))
1128 return ((int) room_types[i].type);
1129 return ERR;
1133 * Find the type of a trap in the table, knowing its name.
1136 get_trap_type(s)
1137 char *s;
1139 register int i;
1141 SpinCursor(3);
1142 for (i = 0; trap_types[i].name; i++)
1143 if (!strcmp(s, trap_types[i].name))
1144 return trap_types[i].type;
1145 return ERR;
1149 * Find the index of a monster in the table, knowing its name.
1152 get_monster_id(s, c)
1153 char *s;
1154 char c;
1156 register int i, class;
1158 SpinCursor(3);
1159 class = c ? def_char_to_monclass(c) : 0;
1160 if (class == MAXMCLASSES)
1161 return ERR;
1163 for (i = LOW_PM; i < NUMMONS; i++)
1164 if (!class || class == mons[i].mlet)
1165 if (!strcmp(s, mons[i].mname))
1166 return i;
1167 /* didn't find it; lets try case insensitive search */
1168 for (i = LOW_PM; i < NUMMONS; i++)
1169 if (!class || class == mons[i].mlet)
1170 if (!case_insensitive_comp(s, mons[i].mname)) {
1171 if (be_verbose)
1172 lc_warning("Monster type \"%s\" matches \"%s\".", s,
1173 mons[i].mname);
1174 return i;
1176 return ERR;
1180 * Find the index of an object in the table, knowing its name.
1183 get_object_id(s, c)
1184 char *s;
1185 char c; /* class */
1187 int i, class;
1188 const char *objname;
1190 SpinCursor(3);
1191 class = (c > 0) ? def_char_to_objclass(c) : 0;
1192 if (class == MAXOCLASSES)
1193 return ERR;
1195 for (i = class ? bases[class] : 0; i < NUM_OBJECTS; i++) {
1196 if (class && objects[i].oc_class != class)
1197 break;
1198 objname = obj_descr[i].oc_name;
1199 if (objname && !strcmp(s, objname))
1200 return i;
1202 for (i = class ? bases[class] : 0; i < NUM_OBJECTS; i++) {
1203 if (class && objects[i].oc_class != class)
1204 break;
1205 objname = obj_descr[i].oc_name;
1206 if (objname && !case_insensitive_comp(s, objname)) {
1207 if (be_verbose)
1208 lc_warning("Object type \"%s\" matches \"%s\".", s, objname);
1209 return i;
1212 return ERR;
1215 static void
1216 init_obj_classes()
1218 int i, class, prev_class;
1220 prev_class = -1;
1221 for (i = 0; i < NUM_OBJECTS; i++) {
1222 class = objects[i].oc_class;
1223 if (class != prev_class) {
1224 bases[class] = i;
1225 prev_class = class;
1231 * Is the character 'c' a valid monster class ?
1233 boolean
1234 check_monster_char(c)
1235 char c;
1237 return (def_char_to_monclass(c) != MAXMCLASSES);
1241 * Is the character 'c' a valid object class ?
1243 boolean
1244 check_object_char(c)
1245 char c;
1247 return (def_char_to_objclass(c) != MAXOCLASSES);
1251 * Convert .des map letter into floor type.
1253 char
1254 what_map_char(c)
1255 char c;
1257 SpinCursor(3);
1258 switch (c) {
1259 case ' ':
1260 return (STONE);
1261 case '#':
1262 return (CORR);
1263 case '.':
1264 return (ROOM);
1265 case '-':
1266 return (HWALL);
1267 case '|':
1268 return (VWALL);
1269 case '+':
1270 return (DOOR);
1271 case 'A':
1272 return (AIR);
1273 case 'B':
1274 return (CROSSWALL); /* hack: boundary location */
1275 case 'C':
1276 return (CLOUD);
1277 case 'S':
1278 return (SDOOR);
1279 case 'H':
1280 return (SCORR);
1281 case '{':
1282 return (FOUNTAIN);
1283 case '\\':
1284 return (THRONE);
1285 case 'K':
1286 return (SINK);
1287 case '}':
1288 return (MOAT);
1289 case 'P':
1290 return (POOL);
1291 case 'L':
1292 return (LAVAPOOL);
1293 case 'I':
1294 return (ICE);
1295 case 'W':
1296 return (WATER);
1297 case 'T':
1298 return (TREE);
1299 case 'F':
1300 return (IRONBARS); /* Fe = iron */
1301 case 'x':
1302 return (MAX_TYPE); /* "see-through" */
1304 return (INVALID_TYPE);
1307 void
1308 add_opcode(sp, opc, dat)
1309 sp_lev *sp;
1310 int opc;
1311 genericptr_t dat;
1313 long nop = sp->n_opcodes;
1314 _opcode *tmp;
1316 if ((opc < 0) || (opc >= MAX_SP_OPCODES))
1317 lc_error("Unknown opcode '%d'", opc);
1319 tmp = (_opcode *) alloc(sizeof(_opcode) * (nop + 1));
1320 if (!tmp) { /* lint suppression */
1321 /*NOTREACHED*/
1322 #if 0
1323 /* not possible; alloc() never returns Null */
1324 lc_error("Could not alloc opcode space");
1325 #endif
1326 return;
1329 if (sp->opcodes && nop) {
1330 (void) memcpy(tmp, sp->opcodes, sizeof(_opcode) * nop);
1331 free(sp->opcodes);
1333 sp->opcodes = tmp;
1335 sp->opcodes[nop].opcode = opc;
1336 sp->opcodes[nop].opdat = dat;
1338 sp->n_opcodes++;
1342 * Yep! LEX gives us the map in a raw mode.
1343 * Just analyze it here.
1345 void
1346 scan_map(map, sp)
1347 char *map;
1348 sp_lev *sp;
1350 register int i, len;
1351 register char *s1, *s2;
1352 int max_len = 0;
1353 int max_hig = 0;
1354 char *tmpmap[MAP_Y_LIM+1];
1355 int dx, dy;
1356 char *mbuf;
1358 /* First, strip out digits 0-9 (line numbering) */
1359 for (s1 = s2 = map; *s1; s1++)
1360 if (*s1 < '0' || *s1 > '9')
1361 *s2++ = *s1;
1362 *s2 = '\0';
1364 /* Second, find the max width of the map */
1365 s1 = map;
1366 while (s1 && *s1) {
1367 s2 = index(s1, '\n');
1368 if (s2) {
1369 len = (int) (s2 - s1);
1370 s1 = s2 + 1;
1371 } else {
1372 len = (int) strlen(s1);
1373 s1 = (char *) 0;
1375 if (len > max_len)
1376 max_len = len;
1379 /* Then parse it now */
1380 while (map && *map) {
1381 if (max_hig > MAP_Y_LIM)
1382 break;
1383 tmpmap[max_hig] = (char *) alloc(max_len);
1384 s1 = index(map, '\n');
1385 if (s1) {
1386 len = (int) (s1 - map);
1387 s1++;
1388 } else {
1389 len = (int) strlen(map);
1390 s1 = map + len;
1392 for (i = 0; i < len; i++)
1393 if ((tmpmap[max_hig][i] = what_map_char(map[i]))
1394 == INVALID_TYPE) {
1395 lc_warning("Invalid character '%c' @ (%d, %d) - replacing "
1396 "with stone",
1397 map[i], max_hig, i);
1398 tmpmap[max_hig][i] = STONE;
1400 while (i < max_len)
1401 tmpmap[max_hig][i++] = STONE;
1402 map = s1;
1403 max_hig++;
1406 /* Memorize boundaries */
1408 max_x_map = max_len - 1;
1409 max_y_map = max_hig - 1;
1411 if (max_len > MAP_X_LIM || max_hig > MAP_Y_LIM) {
1412 lc_error("Map too large at (%d x %d), max is (%d x %d)", max_len,
1413 max_hig, MAP_X_LIM, MAP_Y_LIM);
1416 mbuf = (char *) alloc(((max_hig - 1) * max_len) + (max_len - 1) + 2);
1417 for (dy = 0; dy < max_hig; dy++)
1418 for (dx = 0; dx < max_len; dx++)
1419 mbuf[(dy * max_len) + dx] = (tmpmap[dy][dx] + 1);
1421 mbuf[((max_hig - 1) * max_len) + (max_len - 1) + 1] = '\0';
1423 add_opvars(sp, "siio", VA_PASS4(mbuf, max_hig, max_len, SPO_MAP));
1425 for (dy = 0; dy < max_hig; dy++)
1426 Free(tmpmap[dy]);
1427 Free(mbuf);
1431 * Output some info common to all special levels.
1433 static boolean
1434 write_common_data(fd)
1435 int fd;
1437 static struct version_info version_data = {
1438 VERSION_NUMBER, VERSION_FEATURES, VERSION_SANITY1, VERSION_SANITY2,
1439 VERSION_SANITY3
1442 Write(fd, &version_data, sizeof version_data);
1443 return TRUE;
1447 * Here we write the sp_lev structure in the specified file (fd).
1448 * Also, we have to free the memory allocated via alloc().
1450 static boolean
1451 write_maze(fd, maze)
1452 int fd;
1453 sp_lev *maze;
1455 int i;
1457 if (!write_common_data(fd))
1458 return FALSE;
1460 Write(fd, &(maze->n_opcodes), sizeof(maze->n_opcodes));
1462 for (i = 0; i < maze->n_opcodes; i++) {
1463 _opcode tmpo = maze->opcodes[i];
1465 Write(fd, &(tmpo.opcode), sizeof(tmpo.opcode));
1467 if (tmpo.opcode < SPO_NULL || tmpo.opcode >= MAX_SP_OPCODES)
1468 panic("write_maze: unknown opcode (%d).", tmpo.opcode);
1470 if (tmpo.opcode == SPO_PUSH) {
1471 genericptr_t opdat = tmpo.opdat;
1472 if (opdat) {
1473 struct opvar *ov = (struct opvar *) opdat;
1474 int size;
1475 Write(fd, &(ov->spovartyp), sizeof(ov->spovartyp));
1476 switch (ov->spovartyp) {
1477 case SPOVAR_NULL:
1478 break;
1479 case SPOVAR_COORD:
1480 case SPOVAR_REGION:
1481 case SPOVAR_MAPCHAR:
1482 case SPOVAR_MONST:
1483 case SPOVAR_OBJ:
1484 case SPOVAR_INT:
1485 Write(fd, &(ov->vardata.l), sizeof(ov->vardata.l));
1486 break;
1487 case SPOVAR_VARIABLE:
1488 case SPOVAR_STRING:
1489 if (ov->vardata.str)
1490 size = strlen(ov->vardata.str);
1491 else
1492 size = 0;
1493 Write(fd, &size, sizeof(size));
1494 if (size) {
1495 Write(fd, ov->vardata.str, size);
1496 Free(ov->vardata.str);
1498 break;
1499 default:
1500 panic("write_maze: unknown data type (%d).",
1501 ov->spovartyp);
1503 } else
1504 panic("write_maze: PUSH with no data.");
1505 } else {
1506 /* sanity check */
1507 genericptr_t opdat = tmpo.opdat;
1508 if (opdat)
1509 panic("write_maze: opcode (%d) has data.", tmpo.opcode);
1512 Free(tmpo.opdat);
1514 /* clear the struct for next user */
1515 Free(maze->opcodes);
1516 maze->opcodes = NULL;
1517 /*(void) memset((genericptr_t) &maze->init_lev, 0, sizeof
1518 * maze->init_lev);*/
1520 return TRUE;
1524 * Open and write maze or rooms file, based on which pointer is non-null.
1525 * Return TRUE on success, FALSE on failure.
1527 boolean
1528 write_level_file(filename, lvl)
1529 char *filename;
1530 sp_lev *lvl;
1532 int fout;
1533 char lbuf[60];
1535 lbuf[0] = '\0';
1536 #ifdef PREFIX
1537 Strcat(lbuf, PREFIX);
1538 #endif
1539 Strcat(lbuf, filename);
1540 Strcat(lbuf, LEV_EXT);
1542 #if defined(MAC) && (defined(__SC__) || defined(__MRC__))
1543 fout = open(lbuf, O_WRONLY | O_CREAT | O_BINARY);
1544 #else
1545 fout = open(lbuf, O_WRONLY | O_CREAT | O_BINARY, OMASK);
1546 #endif
1547 if (fout < 0)
1548 return FALSE;
1550 if (!lvl)
1551 panic("write_level_file");
1553 if (be_verbose)
1554 fprintf(stdout, "File: '%s', opcodes: %ld\n", lbuf, lvl->n_opcodes);
1556 if (!write_maze(fout, lvl))
1557 return FALSE;
1559 (void) close(fout);
1561 return TRUE;
1564 static int
1565 case_insensitive_comp(s1, s2)
1566 const char *s1;
1567 const char *s2;
1569 uchar u1, u2;
1571 for (;; s1++, s2++) {
1572 u1 = (uchar) *s1;
1573 if (isupper(u1))
1574 u1 = tolower(u1);
1575 u2 = (uchar) *s2;
1576 if (isupper(u2))
1577 u2 = tolower(u2);
1578 if (u1 == '\0' || u1 != u2)
1579 break;
1581 return u1 - u2;
1584 #ifdef STRICT_REF_DEF
1586 * Any globals declared in hack.h and descendents which aren't defined
1587 * in the modules linked into lev_comp should be defined here. These
1588 * definitions can be dummies: their sizes shouldn't matter as long as
1589 * as their types are correct; actual values are irrelevant.
1591 #define ARBITRARY_SIZE 1
1592 /* attrib.c */
1593 struct attribs attrmax, attrmin;
1594 /* files.c */
1595 const char *configfile;
1596 char lock[ARBITRARY_SIZE];
1597 char SAVEF[ARBITRARY_SIZE];
1598 #ifdef MICRO
1599 char SAVEP[ARBITRARY_SIZE];
1600 #endif
1601 /* termcap.c */
1602 struct tc_lcl_data tc_lcl_data;
1603 #ifdef TEXTCOLOR
1604 #ifdef TOS
1605 const char *hilites[CLR_MAX];
1606 #else
1607 char NEARDATA *hilites[CLR_MAX];
1608 #endif
1609 #endif
1610 /* trap.c */
1611 const char *traps[TRAPNUM];
1612 /* window.c */
1613 #ifdef HANGUPHANDLING
1614 volatile
1615 #endif
1616 struct window_procs windowprocs;
1617 /* xxxtty.c */
1618 #ifdef DEFINE_OSPEED
1619 short ospeed;
1620 #endif
1621 #endif /* STRICT_REF_DEF */
1623 /*lev_main.c*/