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 void VDECL(lc_error, (const char *, ...));
113 void VDECL(add_opvars, (sp_lev *, const char *, ...));
114
115 static const struct {
116 long functype;
117 long objtyp;
118 const char *methodname;
119 long retval;
120 } core_methods[] = {
121 {COREFUNC_COORD_X, SPOVAR_COORD, "x", SPOVAR_INT}, /* $coord.x */
122 {COREFUNC_COORD_Y, SPOVAR_COORD, "y", SPOVAR_INT}, /* $coord.y */
123 {COREFUNC_ARRAY_LEN, SPOVAR_INT|SPOVAR_ARRAY, "length", SPOVAR_INT},
124 {COREFUNC_ARRAY_LEN, SPOVAR_STRING|SPOVAR_ARRAY, "length", SPOVAR_INT},
125 {COREFUNC_ARRAY_LEN, SPOVAR_COORD|SPOVAR_ARRAY, "length", SPOVAR_INT},
126 {COREFUNC_ARRAY_LEN, SPOVAR_REGION|SPOVAR_ARRAY, "length", SPOVAR_INT},
127 {COREFUNC_ARRAY_LEN, SPOVAR_MAPCHAR|SPOVAR_ARRAY, "length", SPOVAR_INT},
128 {COREFUNC_ARRAY_LEN, SPOVAR_MONST|SPOVAR_ARRAY, "length", SPOVAR_INT},
129 {COREFUNC_ARRAY_LEN, SPOVAR_OBJ|SPOVAR_ARRAY, "length", SPOVAR_INT},
130 {COREFUNC_ARRAY_LEN, SPOVAR_SEL|SPOVAR_ARRAY, "length", SPOVAR_INT},
131 {0, 0, NULL, 0}
132 };
133
134 long
method_defined(char * methname,long o,long * ftyp)135 method_defined(char *methname, long o, long *ftyp)
136 {
137 int i;
138 for (i = 0; core_methods[i].methodname; i++)
139 if (core_methods[i].objtyp == o && !strcmp(core_methods[i].methodname, methname)) {
140 *ftyp = core_methods[i].functype;
141 return core_methods[i].retval;
142 }
143 return 0;
144 }
145
146
147 static const struct {
148 int functype;
149 const char *name;
150 const char *params;
151 char retval;
152 } core_vars[] = {
153 {COREFUNC_DISCORDIAN_HOLIDAY, "time.discordian_holiday", "", 'i'},
154 {COREFUNC_PIRATEDAY, "time.pirateday", "", 'i'},
155 {COREFUNC_APRILFOOLSDAY, "time.aprilfoolsday", "", 'i'},
156 {COREFUNC_PIDAY, "time.piday", "", 'i'},
157 {COREFUNC_TOWELDAY, "time.towelday", "", 'i'},
158 {COREFUNC_MIDNIGHT, "time.midnight", "", 'i'},
159 {COREFUNC_NIGHT, "time.night", "", 'i'},
160 {COREFUNC_FRIDAY_13TH, "time.friday_13th", "", 'i'},
161 {COREFUNC_POM, "time.phase_of_the_moon", "", 'i'},
162 {COREFUNC_YYYYMMDD, "time.yyyymmdd", "", 'i'},
163 {COREFUNC_LEVEL_DIFFICULTY, "level.difficulty", "", 'i'},
164 {COREFUNC_LEVEL_DEPTH, "level.depth", "", 'i'},
165 {COREFUNC_SOBJ_AT, "level.obj_at", "Oc", 'i'},
166 {COREFUNC_MON_AT, "level.mon_at", "Mc", 'i'},
167 {COREFUNC_PLNAME, "hero.name", "", 's'},
168 {COREFUNC_ROLE, "hero.role", "", 's'},
169 {COREFUNC_RACE, "hero.race", "", 's'},
170 {COREFUNC_CARRYING, "hero.carrying", "O", 'i'},
171 {COREFUNC_TOSTRING, "string", "i", 's'},
172 {COREFUNC_TOSTRING, "str", "i", 's'},
173 {COREFUNC_TOINT, "integer", "s", 'i'},
174 {COREFUNC_TOINT, "int", "s", 'i'},
175 {COREFUNC_TOCOORD, "coord", "ii", 'c'},
176 {COREFUNC_TOREGION, "region", "iiii", 'r'},
177 {COREFUNC_RN2, "rnd", "i", 'i'},
178 {COREFUNC_ROOM_WID, "room.width", "", 'i'},
179 {COREFUNC_ROOM_HEI, "room.height", "", 'i'},
180 {COREFUNC_ROOM_X, "room.x", "", 'i'},
181 {COREFUNC_ROOM_Y, "room.y", "", 'i'},
182 {0, NULL, NULL, 0}
183 };
184
185 static struct {
186 const char *name;
187 int type;
188 } trap_types[] = {
189 { "arrow", ARROW_TRAP },
190 { "dart", DART_TRAP },
191 { "falling rock", ROCKTRAP },
192 { "board", SQKY_BOARD },
193 { "bear", BEAR_TRAP },
194 { "land mine", LANDMINE },
195 { "rolling boulder", ROLLING_BOULDER_TRAP },
196 { "sleep gas", SLP_GAS_TRAP },
197 { "rust", RUST_TRAP },
198 { "fire", FIRE_TRAP },
199 { "pit", PIT },
200 { "spiked pit", SPIKED_PIT },
201 { "hole", HOLE },
202 { "trap door", TRAPDOOR },
203 { "teleport", TELEP_TRAP },
204 { "level teleport", LEVEL_TELEP },
205 { "magic portal", MAGIC_PORTAL },
206 { "web", WEB },
207 { "statue", STATUE_TRAP },
208 { "magic", MAGIC_TRAP },
209 { "anti magic", ANTI_MAGIC },
210 { "polymorph", POLY_TRAP },
211 { "cold", ICE_TRAP},
212 { 0, 0 }
213 };
214
215 static struct {
216 const char *name;
217 int type;
218 } room_types[] = {
219 /* for historical reasons, room types are not contiguous numbers */
220 /* (type 1 is skipped) */
221 { "ordinary", OROOM },
222 { "rndvault", RNDVAULT },
223 { "throne", COURT },
224 { "swamp", SWAMP },
225 { "vault", VAULT },
226 { "beehive", BEEHIVE },
227 { "morgue", MORGUE },
228 { "barracks", BARRACKS },
229 { "zoo", ZOO },
230 { "delphi", DELPHI },
231 { "temple", TEMPLE },
232 { "lemurepit", LEMUREPIT },
233 { "anthole", ANTHOLE },
234 { "cocknest", COCKNEST },
235 { "garden", GARDEN },
236 { "leprehall", LEPREHALL },
237 { "shop", SHOPBASE },
238 { "armor shop", ARMORSHOP },
239 { "scroll shop", SCROLLSHOP },
240 { "potion shop", POTIONSHOP },
241 { "weapon shop", WEAPONSHOP },
242 { "food shop", FOODSHOP },
243 { "ring shop", RINGSHOP },
244 { "wand shop", WANDSHOP },
245 { "tool shop", TOOLSHOP },
246 { "book shop", BOOKSHOP },
247 { "tin shop", TINSHOP },
248 { "music shop", INSTRUMENTSHOP },
249 { "candle shop", CANDLESHOP },
250 { "pet shop", PETSHOP }, /* Stephen White */
251 #ifdef BLACKMARKET
252 { "black market", BLACKSHOP },
253 { "black market foyer", BLACKFOYER },
254 #endif /* BLACKMARKET */
255 { 0, 0 }
256 };
257
258 const char *fname = "(stdin)";
259 int fatal_error = 0;
260 int got_errors = 0;
261 int be_verbose = 0;
262 int decompile = 0;
263 int is_rnd_vault = 0;
264 int rnd_vault_freq = 1;
265 int fname_counter = 1;
266
267 #ifdef FLEX23_BUG
268 /* Flex 2.3 bug work around; not needed for 2.3.6 or later */
269 int yy_more_len = 0;
270 #endif
271
272 extern unsigned int max_x_map, max_y_map;
273
274 extern int line_number, colon_line_number;
275 extern int token_start_pos;
276 extern char curr_token[512];
277
278 struct lc_vardefs *variable_definitions = NULL;
279 struct lc_funcdefs *function_definitions = NULL;
280
281 extern int allow_break_statements;
282 extern struct lc_breakdef *break_list;
283
284 int
main(argc,argv)285 main(argc, argv)
286 int argc;
287 char **argv;
288 {
289 FILE *fin;
290 int i;
291 boolean errors_encountered = FALSE;
292 #if defined(MAC) && (defined(THINK_C) || defined(__MWERKS__))
293 static char *mac_argv[] = { "lev_comp", /* dummy argv[0] */
294 ":dat:Arch.des",
295 ":dat:Barb.des",
296 ":dat:Caveman.des",
297 ":dat:Healer.des",
298 ":dat:Knight.des",
299 ":dat:Monk.des",
300 ":dat:Priest.des",
301 ":dat:Ranger.des",
302 ":dat:Rogue.des",
303 ":dat:Samurai.des",
304 ":dat:Tourist.des",
305 ":dat:Valkyrie.des",
306 ":dat:Wizard.des",
307 ":dat:bigroom.des",
308 ":dat:castle.des",
309 ":dat:endgame.des",
310 ":dat:gehennom.des",
311 ":dat:knox.des",
312 ":dat:medusa.des",
313 ":dat:mines.des",
314 ":dat:oracle.des",
315 ":dat:sheol.des",
316 ":dat:sokoban.des",
317 ":dat:tower.des",
318 ":dat:yendor.des"
319 };
320
321 argc = SIZE(mac_argv);
322 argv = mac_argv;
323 #endif
324 /* Note: these initializers don't do anything except guarantee that
325 we're linked properly.
326 */
327 monst_init();
328 objects_init();
329 decl_init();
330 /* this one does something... */
331 init_obj_classes();
332
333 init_yyout(stdout);
334 if (argc == 1) { /* Read standard input */
335 init_yyin(stdin);
336 (void) yyparse();
337 if (fatal_error > 0 || got_errors > 0) {
338 errors_encountered = TRUE;
339 }
340 } else { /* Otherwise every argument is a filename */
341 for(i=1; i<argc; i++) {
342 fname = argv[i];
343 if(!strcmp(fname, "-v")) {
344 be_verbose++;
345 continue;
346 }
347 if(!strcmp(fname, "-d")) {
348 decompile = 1;
349 continue;
350 }
351 fin = freopen(fname, "r", stdin);
352 if (!fin) {
353 (void) fprintf(stderr,"Can't open \"%s\" for input.\n",
354 fname);
355 perror(fname);
356 errors_encountered = TRUE;
357 } else {
358 fname_counter = 1;
359 init_yyin(fin);
360 (void) yyparse();
361 line_number = 1;
362 if (fatal_error > 0 || got_errors > 0) {
363 errors_encountered = TRUE;
364 fatal_error = 0;
365 }
366 }
367 (void) fclose(fin);
368 funcdef_free_all(function_definitions);
369 }
370 }
371 exit(errors_encountered ? EXIT_FAILURE : EXIT_SUCCESS);
372 /*NOTREACHED*/
373 return 0;
374 }
375
376 /*
377 * Each time the parser detects an error, it uses this function.
378 * Here we take count of the errors. To continue farther than
379 * MAX_ERRORS wouldn't be reasonable.
380 */
381 void
yyerror(s)382 yyerror(s)
383 const char *s;
384 {
385 char *e = ((char *)s + strlen(s) - 1);
386 (void) fprintf(stderr, "%s: line %d, pos %d : %s",
387 fname, line_number,
388 token_start_pos-strlen(curr_token), s);
389 if (*e != '.' && *e != '!')
390 (void) fprintf(stderr, " at \"%s\"", curr_token);
391 (void) fprintf(stderr, "\n");
392
393 if (++fatal_error > MAX_ERRORS) {
394 (void) fprintf(stderr,"Too many errors, good bye!\n");
395 exit(EXIT_FAILURE);
396 }
397 }
398
399
400 void
lc_error(const char * fmt,...)401 lc_error(const char *fmt, ...)
402 {
403 char buf[512];
404 va_list argp;
405
406 va_start(argp, fmt);
407 (void) vsnprintf(buf, 511, fmt, argp);
408 va_end(argp);
409
410 yyerror(buf);
411 }
412
413
414 /*
415 * Just display a warning (that is : a non fatal error)
416 */
417 void
yywarning(s)418 yywarning(s)
419 const char *s;
420 {
421 (void) fprintf(stderr, "%s: line %d : WARNING : %s\n",
422 fname, line_number, s);
423 }
424
425 void
lc_warning(const char * fmt,...)426 lc_warning(const char *fmt, ...)
427 {
428 char buf[512];
429 va_list argp;
430
431 va_start(argp, fmt);
432 (void) vsnprintf(buf, 511, fmt, argp);
433 va_end(argp);
434
435 yywarning(buf);
436 }
437
438 char *
decode_parm_chr(chr)439 decode_parm_chr(chr)
440 char chr;
441 {
442 static char buf[32];
443 switch (chr) {
444 default: sprintf(buf, "unknown"); break;
445 case 'i': sprintf(buf, "int"); break;
446 case 'r': sprintf(buf, "region"); break;
447 case 's': sprintf(buf, "str"); break;
448 case 'O': sprintf(buf, "obj"); break;
449 case 'c': sprintf(buf, "coord"); break;
450 case ' ': sprintf(buf, "nothing"); break;
451 case 'm': sprintf(buf, "mapchar"); break;
452 case 'M': sprintf(buf, "monster"); break;
453 }
454 return buf;
455 }
456
457 char *
decode_parm_str(str)458 decode_parm_str(str)
459 char *str;
460 {
461 static char tmpbuf[1024];
462 char *p = str;
463 tmpbuf[0] = '\0';
464 if (str) {
465 for ( ; *p; p++) {
466 Strcat(tmpbuf, decode_parm_chr(*p));
467 if (*(p + 1)) Strcat(tmpbuf, ", ");
468 }
469 }
470 return tmpbuf;
471 }
472
473 int
is_core_func(char * str)474 is_core_func(char *str)
475 {
476 int i;
477 for (i = 0; core_vars[i].name; i++)
478 if (!strcmp(core_vars[i].name, str))
479 return core_vars[i].functype;
480 return 0;
481 }
482
483 int
core_func_idx(char * str)484 core_func_idx(char *str)
485 {
486 int i;
487 for (i = 0; core_vars[i].name; i++)
488 if (!strcmp(core_vars[i].name, str))
489 return i;
490 return -1;
491 }
492
493 char
core_func_retval(int idx)494 core_func_retval(int idx)
495 {
496 return core_vars[idx].retval;
497 }
498
499 const char *
core_func_params(int idx)500 core_func_params(int idx)
501 {
502 return core_vars[idx].params;
503 }
504
505 const char *
core_func_name(int idx)506 core_func_name(int idx)
507 {
508 return core_vars[idx].name;
509 }
510
511 int
handle_corefunc(splev,funcname,parmlist,retc)512 handle_corefunc(splev, funcname, parmlist, retc)
513 sp_lev *splev;
514 char *funcname;
515 char *parmlist;
516 char retc;
517 {
518 int f = is_core_func(funcname);
519 int i;
520 char *p, *dp;
521 if (!f) {
522 lc_error("Unknown core function '%s'", funcname);
523 return 0;
524 }
525 i = core_func_idx(funcname);
526 p = (char *)core_func_params(i);
527 if (strcmp(parmlist, p)) {
528 if (!strcmp(p, "")) {
529 lc_error("Core function '%s' takes no parameters.", funcname);
530 } else {
531 dp = strdup(decode_parm_str(p));
532 lc_error("Core function '%s' requires '%s' parameter%s, got '%s' instead.",
533 funcname, dp,
534 (strlen(p) > 1 ? "s" : ""),
535 decode_parm_str(parmlist));
536 free(dp);
537 }
538 return 0;
539 }
540 if (core_func_retval(i) != retc) {
541 lc_error("Core function '%s' does not return '%s' value.", funcname, decode_parm_chr(retc));
542 return 0;
543 }
544 add_opvars(splev, "io", f, SPO_COREFUNC);
545 return 1;
546 }
547
548 struct opvar *
set_opvar_int(ov,val)549 set_opvar_int(ov, val)
550 struct opvar *ov;
551 long val;
552 {
553 if (ov) {
554 ov->spovartyp = SPOVAR_INT;
555 ov->vardata.l = val;
556 }
557 return ov;
558 }
559
560 struct opvar *
set_opvar_coord(ov,val)561 set_opvar_coord(ov, val)
562 struct opvar *ov;
563 long val;
564 {
565 if (ov) {
566 ov->spovartyp = SPOVAR_COORD;
567 ov->vardata.l = val;
568 }
569 return ov;
570 }
571
572 struct opvar *
set_opvar_region(ov,val)573 set_opvar_region(ov, val)
574 struct opvar *ov;
575 long val;
576 {
577 if (ov) {
578 ov->spovartyp = SPOVAR_REGION;
579 ov->vardata.l = val;
580 }
581 return ov;
582 }
583
584 struct opvar *
set_opvar_mapchar(ov,val)585 set_opvar_mapchar(ov, val)
586 struct opvar *ov;
587 long val;
588 {
589 if (ov) {
590 ov->spovartyp = SPOVAR_MAPCHAR;
591 ov->vardata.l = val;
592 }
593 return ov;
594 }
595
596 struct opvar *
set_opvar_monst(ov,val)597 set_opvar_monst(ov, val)
598 struct opvar *ov;
599 long val;
600 {
601 if (ov) {
602 ov->spovartyp = SPOVAR_MONST;
603 ov->vardata.l = val;
604 }
605 return ov;
606 }
607
608 struct opvar *
set_opvar_obj(ov,val)609 set_opvar_obj(ov, val)
610 struct opvar *ov;
611 long val;
612 {
613 if (ov) {
614 ov->spovartyp = SPOVAR_OBJ;
615 ov->vardata.l = val;
616 }
617 return ov;
618 }
619
620 struct opvar *
set_opvar_str(ov,val)621 set_opvar_str(ov, val)
622 struct opvar *ov;
623 char *val;
624 {
625 if (ov) {
626 ov->spovartyp = SPOVAR_STRING;
627 ov->vardata.str = (val) ? strdup(val) : NULL;
628 }
629 return ov;
630 }
631
632 struct opvar *
set_opvar_var(ov,val)633 set_opvar_var(ov, val)
634 struct opvar *ov;
635 char *val;
636 {
637 if (ov) {
638 ov->spovartyp = SPOVAR_VARIABLE;
639 ov->vardata.str = (val) ? strdup(val) : NULL;
640 }
641 return ov;
642 }
643
644 #define New(type) \
645 (type *) memset((genericptr_t)alloc(sizeof(type)), 0, sizeof(type))
646
647 void
add_opvars(sp_lev * sp,const char * fmt,...)648 add_opvars(sp_lev *sp, const char *fmt, ...)
649 {
650 const char *p;
651 va_list argp;
652
653 va_start(argp, fmt);
654
655 for(p = fmt; *p != '\0'; p++) {
656 switch(*p) {
657 case ' ': break;
658 case 'i':
659 {
660 struct opvar *ov = New(struct opvar);
661 set_opvar_int(ov, va_arg(argp, long));
662 add_opcode(sp, SPO_PUSH, ov);
663 break;
664 }
665 case 'c':
666 {
667 struct opvar *ov = New(struct opvar);
668 set_opvar_coord(ov, va_arg(argp, long));
669 add_opcode(sp, SPO_PUSH, ov);
670 break;
671 }
672 case 'r':
673 {
674 struct opvar *ov = New(struct opvar);
675 set_opvar_region(ov, va_arg(argp, long));
676 add_opcode(sp, SPO_PUSH, ov);
677 break;
678 }
679 case 'm':
680 {
681 struct opvar *ov = New(struct opvar);
682 set_opvar_mapchar(ov, va_arg(argp, long));
683 add_opcode(sp, SPO_PUSH, ov);
684 break;
685 }
686 case 'M':
687 {
688 struct opvar *ov = New(struct opvar);
689 set_opvar_monst(ov, va_arg(argp, long));
690 add_opcode(sp, SPO_PUSH, ov);
691 break;
692 }
693 case 'O':
694 {
695 struct opvar *ov = New(struct opvar);
696 set_opvar_obj(ov, va_arg(argp, long));
697 add_opcode(sp, SPO_PUSH, ov);
698 break;
699 }
700 case 's':
701 {
702 struct opvar *ov = New(struct opvar);
703 set_opvar_str(ov, va_arg(argp, char *));
704 add_opcode(sp, SPO_PUSH, ov);
705 break;
706 }
707 case 'v':
708 {
709 struct opvar *ov = New(struct opvar);
710 set_opvar_var(ov, va_arg(argp, char *));
711 add_opcode(sp, SPO_PUSH, ov);
712 break;
713 }
714 case 'o':
715 {
716 long i = va_arg(argp, int);
717 if (i < 0 || i >= MAX_SP_OPCODES)
718 fprintf(stderr, "add_opvars: unknown opcode '%i'.\n", i);
719 add_opcode(sp, i, NULL);
720 break;
721 }
722 default:
723 fprintf(stderr, "add_opvars: illegal format character '%c'.\n", *p);
724 break;
725 }
726 }
727
728 va_end(argp);
729 }
730
731 void
break_stmt_start()732 break_stmt_start()
733 {
734 allow_break_statements++;
735 }
736
737 void
break_stmt_end(splev)738 break_stmt_end(splev)
739 sp_lev *splev;
740 {
741 struct lc_breakdef *tmp = break_list;
742 struct lc_breakdef *prv = NULL;
743 while (tmp) {
744 if (tmp->break_depth == allow_break_statements) {
745 struct lc_breakdef *nxt = tmp->next;
746 set_opvar_int(tmp->breakpoint, splev->n_opcodes - tmp->breakpoint->vardata.l-1);
747 tmp->next = NULL;
748 Free(tmp);
749 if (!prv) break_list = NULL;
750 else prv->next = nxt;
751 tmp = nxt;
752 } else {
753 prv = tmp;
754 tmp = tmp->next;
755 }
756 }
757 allow_break_statements--;
758 }
759
760 void
break_stmt_new(splev,i)761 break_stmt_new(splev,i)
762 sp_lev *splev;
763 long i;
764 {
765 struct lc_breakdef *tmp = New(struct lc_breakdef);
766 tmp->breakpoint = New(struct opvar);
767 tmp->break_depth = allow_break_statements;
768 tmp->next = break_list;
769 break_list = tmp;
770 set_opvar_int(tmp->breakpoint, i);
771 add_opcode(splev, SPO_PUSH, tmp->breakpoint);
772 add_opcode(splev, SPO_JMP, NULL);
773 }
774
775 struct lc_funcdefs *
funcdef_new(addr,name)776 funcdef_new(addr, name)
777 long addr;
778 char *name;
779 {
780 struct lc_funcdefs *f = New(struct lc_funcdefs);
781 if (!f) {
782 lc_error("Could not alloc function definition for '%s'.", name);
783 return NULL;
784 }
785 f->next = NULL;
786 f->addr = addr;
787 f->name = strdup(name);
788 f->n_called = 0;
789 f->n_params = 0;
790 f->params = NULL;
791 f->code.opcodes = NULL;
792 f->code.n_opcodes = 0;
793 return f;
794 }
795
796 void
funcdef_free_all(fchain)797 funcdef_free_all(fchain)
798 struct lc_funcdefs *fchain;
799 {
800 struct lc_funcdefs *tmp = fchain;
801 struct lc_funcdefs *nxt;
802 struct lc_funcdefs_parm *tmpparam;
803 while (tmp) {
804 nxt = tmp->next;
805 Free(tmp->name);
806 while (tmp->params) {
807 tmpparam = tmp->params->next;
808 Free(tmp->params->name);
809 tmp->params = tmpparam;
810 }
811 /* FIXME: free tmp->code */
812 Free(tmp);
813 tmp = nxt;
814 }
815 }
816
817
818 char *
funcdef_paramtypes(f)819 funcdef_paramtypes(f)
820 struct lc_funcdefs *f;
821 {
822 int i = 0;
823 struct lc_funcdefs_parm *fp = f->params;
824 char *tmp = (char *)alloc((f->n_params) + 1);
825 if (!tmp) return NULL;
826 while (fp) {
827 tmp[i++] = fp->parmtype;
828 fp = fp->next;
829 }
830 tmp[i] = '\0';
831 return tmp;
832 }
833
834 struct lc_funcdefs *
funcdef_defined(f,name,casesense)835 funcdef_defined(f, name, casesense)
836 struct lc_funcdefs *f;
837 char *name;
838 int casesense;
839 {
840 while (f) {
841 if (casesense) {
842 if (!strcmp(name, f->name)) return f;
843 } else {
844 if (!strcasecmp(name, f->name)) return f;
845 }
846 f = f->next;
847 }
848 return NULL;
849 }
850
851
852 struct lc_vardefs *
vardef_new(typ,name)853 vardef_new(typ, name)
854 long typ;
855 char *name;
856 {
857 struct lc_vardefs *f = New(struct lc_vardefs);
858 if (!f) {
859 lc_error("Could not alloc variable definition for '%s'.", name);
860 return NULL;
861 }
862 f->next = NULL;
863 f->var_type = typ;
864 f->name = strdup(name);
865 f->n_used = 0;
866 return f;
867 }
868
869 void
vardef_free_all(fchain)870 vardef_free_all(fchain)
871 struct lc_vardefs *fchain;
872 {
873 struct lc_vardefs *tmp = fchain;
874 struct lc_vardefs *nxt;
875 while (tmp) {
876 if (be_verbose && (tmp->n_used == 0))
877 lc_warning("Unused variable '%s'", tmp->name);
878 nxt = tmp->next;
879 Free(tmp->name);
880 Free(tmp);
881 tmp = nxt;
882 }
883 }
884
885 struct lc_vardefs *
vardef_defined(f,name,casesense)886 vardef_defined(f, name, casesense)
887 struct lc_vardefs *f;
888 char *name;
889 int casesense;
890 {
891 while (f) {
892 if (casesense) {
893 if (!strcmp(name, f->name)) return f;
894 } else {
895 if (!strcasecmp(name, f->name)) return f;
896 }
897 f = f->next;
898 }
899 return NULL;
900 }
901
902 const char *
spovar2str(spovar)903 spovar2str(spovar)
904 long spovar;
905 {
906 static int togl = 0;
907 static char buf[2][128];
908 char *n = NULL;
909 int is_array = (spovar & SPOVAR_ARRAY);
910 spovar &= ~SPOVAR_ARRAY;
911
912 switch (spovar) {
913 default: lc_error("spovar2str(%li)", spovar); break;
914 case SPOVAR_INT: n = "integer"; break;
915 case SPOVAR_STRING: n = "string"; break;
916 case SPOVAR_VARIABLE: n = "variable"; break;
917 case SPOVAR_COORD: n = "coordinate"; break;
918 case SPOVAR_REGION: n = "region"; break;
919 case SPOVAR_MAPCHAR: n = "mapchar"; break;
920 case SPOVAR_MONST: n = "monster"; break;
921 case SPOVAR_OBJ: n = "object"; break;
922 }
923
924 togl = ((togl + 1) % 2);
925
926 snprintf(buf[togl], 127, "%s%s", n, (is_array ? " array" : ""));
927 return buf[togl];
928 }
929
930 void
vardef_used(vd,varname)931 vardef_used(vd, varname)
932 struct lc_vardefs *vd;
933 char *varname;
934 {
935 struct lc_vardefs *tmp;
936 if ((tmp = vardef_defined(vd, varname, 1))) tmp->n_used++;
937 }
938
939 void
check_vardef_type(vd,varname,vartype)940 check_vardef_type(vd, varname, vartype)
941 struct lc_vardefs *vd;
942 char *varname;
943 long vartype;
944 {
945 struct lc_vardefs *tmp;
946 if ((tmp = vardef_defined(vd, varname, 1))) {
947 if (tmp->var_type != vartype)
948 lc_error("Trying to use variable '%s' as %s, when it is %s.",
949 varname, spovar2str(vartype), spovar2str(tmp->var_type));
950 } else lc_error("Variable '%s' not defined.", varname);
951 }
952
953 struct lc_vardefs *
add_vardef_type(vd,varname,vartype)954 add_vardef_type(vd, varname, vartype)
955 struct lc_vardefs *vd;
956 char *varname;
957 long vartype;
958 {
959 struct lc_vardefs *tmp;
960 if ((tmp = vardef_defined(vd, varname, 1))) {
961 if (tmp->var_type != vartype)
962 lc_error("Trying to redefine variable '%s' as %s, when it is %s.",
963 varname, spovar2str(vartype), spovar2str(tmp->var_type));
964 } else {
965 tmp = vardef_new(vartype, varname);
966 tmp->next = vd;
967 return tmp;
968 }
969 return vd;
970 }
971
972 int
reverse_jmp_opcode(opcode)973 reverse_jmp_opcode(opcode)
974 int opcode;
975 {
976 switch (opcode) {
977 case SPO_JE: return SPO_JNE;
978 case SPO_JNE: return SPO_JE;
979 case SPO_JL: return SPO_JGE;
980 case SPO_JG: return SPO_JLE;
981 case SPO_JLE: return SPO_JG;
982 case SPO_JGE: return SPO_JL;
983 default: lc_error("Cannot reverse comparison jmp opcode %i.", opcode); return SPO_NULL;
984 }
985 }
986
987 /* basically copied from src/sp_lev.c */
988 struct opvar *
opvar_clone(ov)989 opvar_clone(ov)
990 struct opvar *ov;
991 {
992 if (ov) {
993 struct opvar *tmpov = (struct opvar *)alloc(sizeof(struct opvar));
994 if (!tmpov) panic("could not alloc opvar struct");
995 switch (ov->spovartyp) {
996 case SPOVAR_COORD:
997 case SPOVAR_REGION:
998 case SPOVAR_MAPCHAR:
999 case SPOVAR_MONST:
1000 case SPOVAR_OBJ:
1001 case SPOVAR_INT:
1002 {
1003 tmpov->spovartyp = ov->spovartyp;
1004 tmpov->vardata.l = ov->vardata.l;
1005 }
1006 break;
1007 case SPOVAR_VARIABLE:
1008 case SPOVAR_STRING:
1009 {
1010 int len = strlen(ov->vardata.str);
1011 tmpov->spovartyp = ov->spovartyp;
1012 tmpov->vardata.str = (char *)alloc(len+1);
1013 (void)memcpy((genericptr_t)tmpov->vardata.str,
1014 (genericptr_t)ov->vardata.str, len);
1015 tmpov->vardata.str[len] = '\0';
1016 }
1017 break;
1018 default:
1019 {
1020 lc_error("Unknown opvar_clone value type (%i)!", ov->spovartyp);
1021 }
1022 }
1023 return tmpov;
1024 }
1025 return NULL;
1026 }
1027
1028
1029 void
splev_add_from(splev,from_splev)1030 splev_add_from(splev, from_splev)
1031 sp_lev *splev;
1032 sp_lev *from_splev;
1033 {
1034 int i;
1035 if (splev && from_splev)
1036 for (i = 0; i < from_splev->n_opcodes; i++)
1037 add_opcode(splev, from_splev->opcodes[i].opcode, opvar_clone(from_splev->opcodes[i].opdat));
1038 }
1039
1040
1041 /*
1042 * Find the type of floor, knowing its char representation.
1043 */
1044 int
get_floor_type(c)1045 get_floor_type(c)
1046 char c;
1047 {
1048 int val;
1049
1050 SpinCursor(3);
1051 val = what_map_char(c);
1052 if(val == INVALID_TYPE) {
1053 val = ERR;
1054 lc_warning("Invalid fill character '%c' in MAZE declaration", c);
1055 }
1056 return val;
1057 }
1058
1059 /*
1060 * Find the type of a room in the table, knowing its name.
1061 */
1062 int
get_room_type(s)1063 get_room_type(s)
1064 char *s;
1065 {
1066 register int i;
1067
1068 SpinCursor(3);
1069 for(i=0; room_types[i].name; i++)
1070 if (!strcmp(s, room_types[i].name))
1071 return ((int) room_types[i].type);
1072 return ERR;
1073 }
1074
1075 /*
1076 * Find the type of a trap in the table, knowing its name.
1077 */
1078 int
get_trap_type(s)1079 get_trap_type(s)
1080 char *s;
1081 {
1082 register int i;
1083
1084 SpinCursor(3);
1085 for (i=0; trap_types[i].name; i++)
1086 if(!strcmp(s,trap_types[i].name))
1087 return trap_types[i].type;
1088 return ERR;
1089 }
1090
1091 /*
1092 * Find the index of a monster in the table, knowing its name.
1093 */
1094 int
get_monster_id(s,c)1095 get_monster_id(s, c)
1096 char *s;
1097 char c;
1098 {
1099 register int i, class;
1100
1101 SpinCursor(3);
1102 class = c ? def_char_to_monclass(c) : 0;
1103 if (class == MAXMCLASSES) return ERR;
1104
1105 for (i = LOW_PM; i < NUMMONS; i++)
1106 if (!class || class == mons[i].mlet)
1107 if (!strcmp(s, mons[i].mname)) return i;
1108 /* didn't find it; lets try case insensitive search */
1109 for (i = LOW_PM; i < NUMMONS; i++)
1110 if (!class || class == mons[i].mlet)
1111 if (!strcasecmp(s, mons[i].mname)) {
1112 if (be_verbose)
1113 lc_warning("Monster type \"%s\" matches \"%s\".", s, mons[i].mname);
1114 return i;
1115 }
1116 return ERR;
1117 }
1118
1119 /*
1120 * Find the index of an object in the table, knowing its name.
1121 */
1122 int
get_object_id(s,c)1123 get_object_id(s, c)
1124 char *s;
1125 char c; /* class */
1126 {
1127 int i, class;
1128 const char *objname;
1129
1130 SpinCursor(3);
1131 class = (c > 0) ? def_char_to_objclass(c) : 0;
1132 if (class == MAXOCLASSES) return ERR;
1133
1134 for (i = class ? bases[class] : 0; i < NUM_OBJECTS; i++) {
1135 if (class && objects[i].oc_class != class) break;
1136 objname = obj_descr[i].oc_name;
1137 if (objname && !strcmp(s, objname))
1138 return i;
1139 }
1140
1141 for (i = class ? bases[class] : 0; i < NUM_OBJECTS; i++) {
1142 if (class && objects[i].oc_class != class) break;
1143 objname = obj_descr[i].oc_name;
1144 if (objname && !strcasecmp(s, objname)) {
1145 if (be_verbose)
1146 lc_warning("Object type \"%s\" matches \"%s\".", s, objname);
1147 return i;
1148 }
1149 }
1150
1151 return ERR;
1152 }
1153
1154 static void
init_obj_classes()1155 init_obj_classes()
1156 {
1157 int i, class, prev_class;
1158
1159 prev_class = -1;
1160 for (i = 0; i < NUM_OBJECTS; i++) {
1161 class = objects[i].oc_class;
1162 if (class != prev_class) {
1163 bases[class] = i;
1164 prev_class = class;
1165 }
1166 }
1167 }
1168
1169 /*
1170 * Is the character 'c' a valid monster class ?
1171 */
1172 boolean
check_monster_char(c)1173 check_monster_char(c)
1174 char c;
1175 {
1176 return (def_char_to_monclass(c) != MAXMCLASSES);
1177 }
1178
1179 /*
1180 * Is the character 'c' a valid object class ?
1181 */
1182 boolean
check_object_char(c)1183 check_object_char(c)
1184 char c;
1185 {
1186 return (def_char_to_objclass(c) != MAXOCLASSES);
1187 }
1188
1189 /*
1190 * Convert .des map letter into floor type.
1191 */
1192 char
what_map_char(c)1193 what_map_char(c)
1194 char c;
1195 {
1196 SpinCursor(3);
1197 switch(c) {
1198 case ' ' : return(STONE);
1199 case '#' : return(CORR);
1200 case '.' : return(ROOM);
1201 case '-' : return(HWALL);
1202 case '|' : return(VWALL);
1203 case '+' : return(DOOR);
1204 case 'A' : return(AIR);
1205 case 'B' : return(CROSSWALL); /* hack: boundary location */
1206 case 'C' : return(CLOUD);
1207 case 'S' : return(SDOOR);
1208 case 'H' : return(SCORR);
1209 case '{' : return(FOUNTAIN);
1210 case '\\' : return(THRONE);
1211 case 'K' :
1212 #ifdef SINKS
1213 return(SINK);
1214 #else
1215 lc_warning("Sinks ('K') are not allowed in this version! Ignoring...");
1216 return(ROOM);
1217 #endif
1218 case '}' : return(MOAT);
1219 case 'P' : return(POOL);
1220 case 'L' : return(LAVAPOOL);
1221 case 'I' : return(ICE);
1222 case 'W' : return(WATER);
1223 case 'T' : return(TREE);
1224 case 't' : return(DEADTREE);
1225 case 'F' : return(IRONBARS); /* Fe = iron */
1226 case 'M' : return(BOG); /* muddy swamp */
1227 case 'x' : return(MAX_TYPE); /* 'see-through' */
1228 case 'Y' : return(CRYSTALICEWALL);
1229 case 'U' : return(ICEWALL);
1230 }
1231 return(INVALID_TYPE);
1232 }
1233
1234 void
add_opcode(sp,opc,dat)1235 add_opcode(sp, opc, dat)
1236 sp_lev *sp;
1237 int opc;
1238 genericptr_t dat;
1239 {
1240 long nop = sp->n_opcodes;
1241 _opcode *tmp;
1242
1243 if ((opc < 0) || (opc >= MAX_SP_OPCODES))
1244 lc_error("Unknown opcode '%i'", opc);
1245
1246 tmp = (_opcode *)alloc(sizeof(_opcode)*(nop+1));
1247 if (sp->opcodes && nop) {
1248 (void) memcpy(tmp, sp->opcodes, sizeof(_opcode)*nop);
1249 free(sp->opcodes);
1250 } else if (!tmp)
1251 lc_error("Could not alloc opcode space");
1252
1253 sp->opcodes = tmp;
1254
1255 sp->opcodes[nop].opcode = opc;
1256 sp->opcodes[nop].opdat = dat;
1257
1258 sp->n_opcodes++;
1259 }
1260
1261 /*
1262 * Yep! LEX gives us the map in a raw mode.
1263 * Just analyze it here.
1264 */
1265 void
scan_map(map,sp)1266 scan_map(map, sp)
1267 char *map;
1268 sp_lev *sp;
1269 {
1270 register int i, len;
1271 register char *s1, *s2;
1272 long max_len = 0;
1273 long max_hig = 0;
1274 char *tmpmap[ROWNO];
1275 int dx,dy;
1276 char *mbuf;
1277
1278 /* First, strip out digits 0-9 (line numbering) */
1279 for (s1 = s2 = map; *s1; s1++)
1280 if (*s1 < '0' || *s1 > '9')
1281 *s2++ = *s1;
1282 *s2 = '\0';
1283
1284 /* Second, find the max width of the map */
1285 s1 = map;
1286 while (s1 && *s1) {
1287 s2 = index(s1, '\n');
1288 if (s2) {
1289 len = (int) (s2 - s1);
1290 s1 = s2 + 1;
1291 } else {
1292 len = (int) strlen(s1);
1293 s1 = (char *) 0;
1294 }
1295 if (len > max_len) max_len = len;
1296 }
1297
1298 /* Then parse it now */
1299 while (map && *map) {
1300 tmpmap[max_hig] = (char *) alloc(max_len);
1301 s1 = index(map, '\n');
1302 if (s1) {
1303 len = (int) (s1 - map);
1304 s1++;
1305 } else {
1306 len = (int) strlen(map);
1307 s1 = map + len;
1308 }
1309 for(i=0; i<len; i++)
1310 if((tmpmap[max_hig][i] = what_map_char(map[i])) == INVALID_TYPE) {
1311 lc_warning("Invalid character '%c' @ (%d, %d) - replacing with stone", map[i], max_hig, i);
1312 tmpmap[max_hig][i] = STONE;
1313 }
1314 while(i < max_len)
1315 tmpmap[max_hig][i++] = STONE;
1316 map = s1;
1317 max_hig++;
1318 }
1319
1320 /* Memorize boundaries */
1321
1322 max_x_map = max_len - 1;
1323 max_y_map = max_hig - 1;
1324
1325
1326 if(max_len > MAP_X_LIM || max_hig > MAP_Y_LIM) {
1327 lc_error("Map too large at (%d x %d), max is (%d x %d)", max_len, max_hig, MAP_X_LIM, MAP_Y_LIM);
1328 }
1329
1330 mbuf = (char *) alloc(((max_hig-1) * max_len) + (max_len-1) + 2);
1331 for (dy = 0; dy < max_hig; dy++)
1332 for (dx = 0; dx < max_len; dx++)
1333 mbuf[(dy * max_len) + dx] = (tmpmap[dy][dx] + 1);
1334
1335 mbuf[((max_hig-1) * max_len) + (max_len-1) + 1] = '\0';
1336
1337 add_opvars(sp, "siio", mbuf, max_hig, max_len, SPO_MAP);
1338
1339 for (dy = 0; dy < max_hig; dy++)
1340 Free(tmpmap[dy]);
1341 Free(mbuf);
1342 }
1343
1344
1345 /*
1346 * Output some info common to all special levels.
1347 */
1348 static boolean
write_common_data(fd,lvl)1349 write_common_data(fd, lvl)
1350 int fd;
1351 sp_lev *lvl;
1352 {
1353 static struct version_info version_data = {
1354 VERSION_NUMBER, VERSION_FEATURES,
1355 VERSION_SANITY1, VERSION_SANITY2
1356 };
1357
1358 Write(fd, &version_data, sizeof version_data);
1359 /*Write(fd, &lvl->init_lev, sizeof(lev_init));*/
1360 return TRUE;
1361 }
1362
1363
1364 /*
1365 * Here we write the sp_lev structure in the specified file (fd).
1366 * Also, we have to free the memory allocated via alloc().
1367 */
1368 static boolean
write_maze(fd,maze)1369 write_maze(fd, maze)
1370 int fd;
1371 sp_lev *maze;
1372 {
1373 int i;
1374
1375 if (!write_common_data(fd, maze))
1376 return FALSE;
1377
1378 Write(fd, &(maze->n_opcodes), sizeof(maze->n_opcodes));
1379
1380 for (i = 0; i < maze->n_opcodes; i++) {
1381 _opcode tmpo = maze->opcodes[i];
1382
1383 Write(fd, &(tmpo.opcode), sizeof(tmpo.opcode));
1384
1385 if (tmpo.opcode < SPO_NULL || tmpo.opcode >= MAX_SP_OPCODES)
1386 panic("write_maze: unknown opcode (%i).", tmpo.opcode);
1387
1388 if (tmpo.opcode == SPO_PUSH) {
1389 genericptr_t opdat = tmpo.opdat;
1390 if (opdat) {
1391 struct opvar *ov = (struct opvar *)opdat;
1392 int size;
1393 Write(fd, &(ov->spovartyp), sizeof(ov->spovartyp));
1394 switch (ov->spovartyp) {
1395 case SPOVAR_NULL: break;
1396 case SPOVAR_COORD:
1397 case SPOVAR_REGION:
1398 case SPOVAR_MAPCHAR:
1399 case SPOVAR_MONST:
1400 case SPOVAR_OBJ:
1401 case SPOVAR_INT:
1402 Write(fd, &(ov->vardata.l), sizeof(ov->vardata.l));
1403 break;
1404 case SPOVAR_VARIABLE:
1405 case SPOVAR_STRING:
1406 if (ov->vardata.str)
1407 size = strlen(ov->vardata.str);
1408 else size = 0;
1409 Write(fd, &size, sizeof(size));
1410 if (size) {
1411 Write(fd, ov->vardata.str, size);
1412 Free(ov->vardata.str);
1413 }
1414 break;
1415 default: panic("write_maze: unknown data type (%i).", ov->spovartyp);
1416 }
1417 } else panic("write_maze: PUSH with no data.");
1418 } else {
1419 /* sanity check */
1420 genericptr_t opdat = tmpo.opdat;
1421 if (opdat)
1422 panic("write_maze: opcode (%i) has data.", tmpo.opcode);
1423 }
1424
1425 Free(tmpo.opdat);
1426
1427 }
1428 /* clear the struct for next user */
1429 Free(maze->opcodes);
1430 maze->opcodes = NULL;
1431 /*(void) memset((genericptr_t) &maze->init_lev, 0, sizeof maze->init_lev);*/
1432
1433 return TRUE;
1434 }
1435
1436
1437 static boolean
decompile_maze(fd,maze)1438 decompile_maze(fd, maze)
1439 int fd;
1440 sp_lev *maze;
1441 {
1442 int i;
1443 char debuf[128];
1444 const char *opcodestr[MAX_SP_OPCODES] = {
1445 "null",
1446 "message",
1447 "monster",
1448 "object",
1449 "engraving",
1450 "room",
1451 "subroom",
1452 "door",
1453 "stair",
1454 "ladder",
1455 "altar",
1456 "fountain",
1457 "sink",
1458 "pool",
1459 "trap",
1460 "gold",
1461 "corridor",
1462 "levregion",
1463 "drawbridge",
1464 "mazewalk",
1465 "non_diggable",
1466 "non_passwall",
1467 "wallify",
1468 "map",
1469 "room_door",
1470 "region",
1471 "cmp",
1472 "jmp",
1473 "jl",
1474 "jle",
1475 "jg",
1476 "jge",
1477 "je",
1478 "jne",
1479 "spill",
1480 "terrain",
1481 "replaceterrain",
1482 "exit",
1483 "endroom",
1484 "pop_container",
1485 "push",
1486 "pop",
1487 "rn2",
1488 "dec",
1489 "inc",
1490 "add",
1491 "sub",
1492 "mul",
1493 "div",
1494 "mod",
1495 "sign",
1496 "copy",
1497 "mon_generation",
1498 "end_moninvent",
1499 "grave",
1500 "frame_push",
1501 "frame_pop",
1502 "call",
1503 "return",
1504 "init_map",
1505 "flags",
1506 "sounds",
1507 "wallwalk",
1508 "var_init",
1509 "shuffle_array",
1510 "dice",
1511 "corefunc",
1512 "selection_add",
1513 "selection_point",
1514 "selection_rect",
1515 "selection_fillrect",
1516 "selection_line",
1517 "selection_rndline",
1518 "selection_grow",
1519 "selection_flood",
1520 "selection_rndcoord",
1521 "selection_ellipse",
1522 "selection_filter",
1523 "selection_gradient",
1524 "selection_complement",
1525 };
1526
1527 /* don't bother with the header stuff */
1528
1529 for (i=0;i<maze->n_opcodes;i++) {
1530 _opcode tmpo = maze->opcodes[i];
1531
1532 if (tmpo.opcode < SPO_NULL || tmpo.opcode >= MAX_SP_OPCODES)
1533 panic("decompile_maze: unknown opcode (%i).", tmpo.opcode);
1534
1535 if (tmpo.opcode == SPO_PUSH) {
1536 genericptr_t opdat = tmpo.opdat;
1537 if (opdat) {
1538 struct opvar *ov = (struct opvar *)opdat;
1539 int size;
1540 switch (ov->spovartyp) {
1541 case SPOVAR_NULL: break;
1542 case SPOVAR_COORD:
1543 snprintf(debuf, 127, "%li:\t%s\tcoord:(%i,%i)\n", i, opcodestr[tmpo.opcode],
1544 (ov->vardata.l & 0xff), ((ov->vardata.l >> 16) & 0xff));
1545 Write(fd, debuf, strlen(debuf));
1546 break;
1547 case SPOVAR_REGION:
1548 snprintf(debuf, 127, "%li:\t%s\tregion:(%i,%i,%i,%i)\n", i, opcodestr[tmpo.opcode],
1549 (ov->vardata.l & 0xff), ((ov->vardata.l >> 8) & 0xff),
1550 ((ov->vardata.l >> 16) & 0xff), ((ov->vardata.l >> 24) & 0xff));
1551 Write(fd, debuf, strlen(debuf));
1552 break;
1553 case SPOVAR_OBJ:
1554 snprintf(debuf, 127, "%li:\t%s\tobj:(id=%i,class=\'%c\')\n",
1555 i, opcodestr[tmpo.opcode],
1556 SP_OBJ_TYP(ov->vardata.l), SP_OBJ_CLASS(ov->vardata.l));
1557 Write(fd, debuf, strlen(debuf));
1558 break;
1559 case SPOVAR_MONST:
1560 snprintf(debuf, 127, "%li:\t%s\tmonster:(pm=%i, class='%c')\n", i, opcodestr[tmpo.opcode],
1561 SP_MONST_PM(ov->vardata.l), SP_MONST_CLASS(ov->vardata.l));
1562 Write(fd, debuf, strlen(debuf));
1563 break;
1564 case SPOVAR_MAPCHAR:
1565 snprintf(debuf, 127, "%li:\t%s\tmapchar:(%li,%i)\n", i, opcodestr[tmpo.opcode],
1566 (int)SP_MAPCHAR_TYP(ov->vardata.l), (schar)SP_MAPCHAR_LIT(ov->vardata.l));
1567 Write(fd, debuf, strlen(debuf));
1568 break;
1569 case SPOVAR_INT:
1570 if (ov->vardata.l >= ' ' && ov->vardata.l <= '~')
1571 snprintf(debuf, 127, "%li:\t%s\tint:%li\t# '%c'\n", i, opcodestr[tmpo.opcode], ov->vardata.l, (char)ov->vardata.l);
1572 else
1573 snprintf(debuf, 127, "%li:\t%s\tint:%li\n", i, opcodestr[tmpo.opcode], ov->vardata.l);
1574 Write(fd, debuf, strlen(debuf));
1575 break;
1576 case SPOVAR_VARIABLE:
1577 case SPOVAR_STRING:
1578 if (ov->vardata.str)
1579 size = strlen(ov->vardata.str);
1580 else size = 0;
1581 if (size) {
1582 int x;
1583 int ok = (size > 127) ? 0 : 1;
1584 if (ok)
1585 for (x = 0; x < size; x++)
1586 if (ov->vardata.str[x] < ' ' || ov->vardata.str[x] > '~') {
1587 ok = 0;
1588 break;
1589 }
1590 if (ok) {
1591 if (ov->spovartyp == SPOVAR_VARIABLE)
1592 snprintf(debuf, 127, "%li:\t%s\tvar:$%s\n", i, opcodestr[tmpo.opcode], ov->vardata.str);
1593 else
1594 snprintf(debuf, 127, "%li:\t%s\tstr:\"%s\"\n", i, opcodestr[tmpo.opcode], ov->vardata.str);
1595 Write(fd, debuf, strlen(debuf));
1596 } else {
1597 snprintf(debuf, 127, "%li:\t%s\tstr:", i, opcodestr[tmpo.opcode]);
1598 Write(fd, debuf, strlen(debuf));
1599 for (x = 0; x < size; x++) {
1600 snprintf(debuf, 127, "%02x ", ov->vardata.str[x]);
1601 Write(fd, debuf, strlen(debuf));
1602 }
1603 snprintf(debuf, 127, "\n");
1604 Write(fd, debuf, strlen(debuf));
1605 }
1606 }
1607 break;
1608 default: panic("decompile_maze: unknown data type (%i).", ov->spovartyp);
1609 }
1610 } else panic("decompile_maze: PUSH with no data.");
1611 } else {
1612 /* sanity check */
1613 genericptr_t opdat = tmpo.opdat;
1614 if (opdat)
1615 panic("decompile_maze: opcode (%i) has data.", tmpo.opcode);
1616 snprintf(debuf, 127, "%li:\t%s\n", i, opcodestr[tmpo.opcode]);
1617 Write(fd, debuf, strlen(debuf));
1618 }
1619
1620 }
1621 return TRUE;
1622 }
1623
1624 char *
mangle_fname(fname)1625 mangle_fname(fname)
1626 char *fname;
1627 {
1628 static char buf[256];
1629 char *p = strchr(fname, '%');
1630
1631 if (p) {
1632 char buf2[256];
1633 p++;
1634 while (*p && (*p >= '0') && (*p <= '9')) p++;
1635 if (*p != 'i') panic("Illegal counter variable '%%%c' in filename.", *p);
1636 if (strchr(p, '%')) panic("Only one counter variable (%%i) in filename allowed.");
1637 sprintf(buf2, "%s", fname);
1638 sprintf(buf, buf2, fname_counter);
1639 fname_counter++;
1640 } else {
1641 sprintf(buf, "%s", fname);
1642 }
1643 return buf;
1644 }
1645
1646
1647 /*
1648 * Open and write special level file.
1649 * Return TRUE on success, FALSE on failure.
1650 */
1651 boolean
write_level_file(filename,lvl)1652 write_level_file(filename, lvl)
1653 char *filename;
1654 sp_lev *lvl;
1655 {
1656 int fout;
1657 char lbuf[60];
1658 char * mangled = mangle_fname(filename);
1659
1660 if (decompile) {
1661 lbuf[0] = '\0';
1662 #ifdef PREFIX
1663 Strcat(lbuf, PREFIX);
1664 #endif
1665 Strcat(lbuf, mangled);
1666 Strcat(lbuf, "_lev.txt");
1667 fout = open(lbuf, O_TRUNC|O_WRONLY|O_CREAT, OMASK);
1668 if (fout < 0) return FALSE;
1669 decompile_maze(fout, lvl);
1670 (void) close(fout);
1671 }
1672
1673 lbuf[0] = '\0';
1674 #ifdef PREFIX
1675 Strcat(lbuf, PREFIX);
1676 #endif
1677 Strcat(lbuf, mangled);
1678 Strcat(lbuf, LEV_EXT);
1679
1680 fout = open(lbuf, O_WRONLY|O_CREAT|O_BINARY, OMASK);
1681 if (fout < 0) return FALSE;
1682
1683 if (!lvl) panic("write_level_file");
1684
1685 if (be_verbose)
1686 fprintf(stdout, "File: '%s', opcodes: %li\n", lbuf, lvl->n_opcodes);
1687
1688 if (!write_maze(fout, lvl))
1689 return FALSE;
1690
1691 (void) close(fout);
1692
1693 if (is_rnd_vault) {
1694 char debuf[256];
1695 lbuf[0] = '\0';
1696 #ifdef PREFIX
1697 Strcat(lbuf, PREFIX);
1698 #endif
1699 Strcat(lbuf, "vaults.dat");
1700 fout = open(lbuf, O_WRONLY|O_APPEND|O_CREAT, OMASK);
1701 snprintf(debuf, 255, "%i %s\n", rnd_vault_freq, mangled);
1702 Write(fout, debuf, strlen(debuf));
1703 (void) close(fout);
1704 }
1705
1706 return TRUE;
1707 }
1708
1709 #ifdef STRICT_REF_DEF
1710 /*
1711 * Any globals declared in hack.h and descendents which aren't defined
1712 * in the modules linked into lev_comp should be defined here. These
1713 * definitions can be dummies: their sizes shouldn't matter as long as
1714 * as their types are correct; actual values are irrelevant.
1715 */
1716 #define ARBITRARY_SIZE 1
1717 /* attrib.c */
1718 struct attribs attrmax, attrmin;
1719 /* files.c */
1720 const char *configfile;
1721 char lock[ARBITRARY_SIZE];
1722 char SAVEF[ARBITRARY_SIZE];
1723 # ifdef MICRO
1724 char SAVEP[ARBITRARY_SIZE];
1725 # endif
1726 /* termcap.c */
1727 struct tc_lcl_data tc_lcl_data;
1728 # ifdef TEXTCOLOR
1729 # ifdef TOS
1730 const char *hilites[CLR_MAX];
1731 # else
1732 char NEARDATA *hilites[CLR_MAX];
1733 # endif
1734 # endif
1735 /* trap.c */
1736 const char *traps[TRAPNUM];
1737 /* window.c */
1738 struct window_procs windowprocs;
1739 /* xxxtty.c */
1740 # ifdef DEFINE_OSPEED
1741 short ospeed;
1742 # endif
1743 #endif /* STRICT_REF_DEF */
1744
1745 /*lev_main.c*/
1746